ZoomComboBox.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / TrustUi / MS / Internal / documents / Application / ZoomComboBox.cs / 1 / ZoomComboBox.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: A derived ComboBox with some extra functionality 
// for the Zoom behaviours of DocumentApplicationUI.
// 
// History:
// 05/04/2005 - [....] - Created.
//
//--------------------------------------------------------------------------- 
// Used to support the warnings disabled below
#pragma warning disable 1634, 1691 
 
using System;
using System.ComponentModel; 
using System.Globalization;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Automation.Peers; 
using System.Windows.Automation.Provider;
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Input;         // For event args
using System.Windows.TrustUI;       // For string resources 

/// 
/// A derived ComboBox with some extra functionality for the Zoom behaviours of DocumentApplicationUI.
///  
namespace MS.Internal.Documents.Application
{ 
    internal sealed class ZoomComboBox : ComboBox 
    {
        //----------------------------------------------------- 
        //
        //  Constructors
        //
        //----------------------------------------------------- 

        #region Constructors 
        ///  
        /// Static ZoomComboBox constructor
        ///  
        static ZoomComboBox()
        {
            // Override this ComboBox property so that any zoom values that are found in the TextBox
            // (either from user input, or databinding) are not looked up in the drop down list. 
            IsTextSearchEnabledProperty.OverrideMetadata(typeof(ZoomComboBox), new FrameworkPropertyMetadata(false));
        } 
 
        /// 
        /// Default ZoomComboBox constructor. 
        /// 
        internal ZoomComboBox()
        {
            // Set any ComboBox properties. 
            SetDefaults();
 
            // Setup any ComboBox event handlers. 
            SetHandlers();
        } 
        #endregion Constructors

        //------------------------------------------------------
        // 
        //  Public Properties
        // 
        //----------------------------------------------------- 

        #region Public Properties 
        /// 
        /// A reference to the TextBox contained within the ZoomComboBox.
        /// 
        public TextBox TextBox 
        {
            get 
            { 
                return _editableTextBox;
            } 
        }

        public static readonly DependencyProperty ZoomProperty =
            DependencyProperty.Register( 
                    "Zoom",
                    typeof(double), 
                    typeof(ZoomComboBox), 
                    new FrameworkPropertyMetadata(
                            _zoomDefault, //default value 
                            FrameworkPropertyMetadataOptions.None, //MetaData flags
                            new PropertyChangedCallback(OnZoomChanged)));  //changed callback

        ///  
        /// Process returns true if selection events generated from the ZoomComboBox
        /// should be used to update the actual zoom.  This is usually not the case 
        /// since we want to ignore the user going through the combobox with the 
        /// arrow keys until they actually apply the selection.
        ///  
        public bool ProcessSelections
        {
            get
            { 
                return _processSelections;
            } 
        } 

        #endregion Public Properties 

        //------------------------------------------------------
        //
        //  Public Methods 
        //
        //------------------------------------------------------ 
 
        #region Public Methods
        ///  
        /// OnApplyTemplate is called when the ComboBox's Template is applied,
        /// at this point we can get the TextBox from the Template.
        /// 
        public override void OnApplyTemplate() 
        {
            base.OnApplyTemplate(); 
 
            _editableTextBox = GetTemplateChild("PART_EditableTextBox") as TextBox;
 
            if (_editableTextBox != null)
            {
                _editableTextBox.TextAlignment = TextAlignment.Right;
 
                // Since ZoomComboBox primarily supports input as numbers, we should disable
                // IME options so that we don't need multiple Enter presses to parse 
                // the input. This means that we don't handle the IME equivalent of %, but 
                // we'll still handle everything else.
                InputMethod.SetIsInputMethodEnabled(_editableTextBox, false); 
            }
        }

        ///  
        /// Sets the current Zoom value being displayed in the ComboBox's TextBox.
        ///  
        public void SetZoom(double zoom) 
        {
            string zoomString; 
            if (ZoomValueToString(zoom, out zoomString))
            {
                this.Text = zoomString;
                _isEditingText = false; 
                // If this is currently focused, refocus to reset text selection.
                if ((_editableTextBox != null) && (_editableTextBox.IsFocused)) 
                { 
                    _editableTextBox.SelectAll();
                } 

            }
        }
        #endregion Public Methods 

        //----------------------------------------------------- 
        // 
        //  Internal Events
        // 
        //------------------------------------------------------

        #region Internal Events
        ///  
        /// This event will be fired anytime a user was editing the TextBox but applied
        /// the new value (ie pressed enter, or tab). 
        ///  
        internal event EventHandler ZoomValueEdited;
 
        /// 
        /// This will fire a ZoomValueEdited event if required.
        /// 
        internal void OnZoomValueEdited() 
        {
            // Check if the TextBox is being edited 
            if (_isEditingText) 
            {
                _isEditingText = false; 

                // Since the TextBox was being edited, fire a cancelled event so that the value
                // may be applied (if desired by the UI).
                ZoomValueEdited(this, EventArgs.Empty); 
            }
        } 
 
        /// 
        /// This event will be fired anytime a user was editing the TextBox but chose not to apply 
        /// the new value (ie change of focus, or escape pressed).
        /// 
        internal event EventHandler ZoomValueEditCancelled;
 
        /// 
        /// This will fire a ZoomValueEditCancelled event if required. 
        ///  
        internal void OnZoomValueEditCancelled()
        { 
            // Check if the TextBox is being edited
            if (_isEditingText)
            {
                _isEditingText = false; 

                // Since the TextBox was being edited, fire a cancelled event so that the value 
                // may be reset (if desired by the UI). 
                ZoomValueEditCancelled(this, EventArgs.Empty);
            } 
        }
        #endregion Internal Events

        //----------------------------------------------------- 
        //
        //  Protected Methods 
        // 
        //-----------------------------------------------------
 
        /// 
        /// This will be fired anytime a selection has been made from the list
        /// or a new value has been entered into the TextBox
        ///  
        /// Event args.
        protected override void OnSelectionChanged(SelectionChangedEventArgs e) 
        { 
            // Only process selections when responding to a mouse click
            if (ProcessSelections) 
            {
                // If we were in edit mode, cancel it
                if (_isEditingText)
                { 
                    _isEditingText = false;
                } 
 
                // Since an item has been selected from the list, update the ComboBox
                base.OnSelectionChanged(e); 

                // Reset the focus to highlight the new value.
                Focus();
            } 
        }
 
        ///  
        /// Clears the current selection whenever the dropdown is opened.
        ///  
        /// 
        protected override void OnDropDownOpened(EventArgs e)
        {
            SelectedIndex = -1; 
        }
 
        ///  
        /// Creates AutomationPeer ()
        ///  
        protected override AutomationPeer OnCreateAutomationPeer()
        {
            return new ZoomComboBoxBoxAutomationPeer(this);
        } 

        ///  
        /// This will check incoming key presses for 'enter', 'escape', and 'tab' and take the 
        /// appropriate action.
        ///  
        /// A reference to the sender of the event.
        /// Arguments to the event, used for the key reference.
        protected override void OnPreviewKeyDown(KeyEventArgs e)
        { 
            // This will check for the use of 'enter', 'escape' and 'tab' and take the appropriate action
 
            // Ensure the arguments are not null. 
            if (e != null)
            { 
                // Check which Key was pressed.
                switch (e.Key)
                {
                    // Erasure keys -- these don't trigger OnPreviewTextInput but should 
                    // set _isEditingText nonetheless
                    case Key.Delete: 
                    case Key.Back: 
                        _isEditingText = true;
                        break; 

                    // Submission Keys
                    case Key.Return:  // This also covers: case Key.Enter
                    case Key.Tab: 
                    case Key.Execute:
                        if (IsDropDownOpen) 
                        { 
                            // If the user presses the enter key while the drop down is
                            // open, this is the final selection from the dropdown and 
                            // should be applied.  Since the selection of this item
                            // (via up/down) was ignored, first we must copy the selected
                            // value into the TextBox.  Then we process it as if the user
                            // had typed it in. 
                            if (SelectedItem != null)
                            { 
                                Text = ((ComboBoxItem)SelectedItem).Content.ToString(); 
                            }
                            _isEditingText = true; 
                        }
                        // Enter pressed, issue submit, mark input as handled.
                        OnZoomValueEdited();
                        break; 

                    // Rejection Keys 
                    case Key.Cancel: 
                    case Key.Escape:
                        // Escape pressed, issue cancel, mark input as handled. 
                        OnZoomValueEditCancelled();
                        break;
                    case Key.Up:
                    case Key.Down: 
                        // Open the drop down when up or down is pressed
                        if (!IsDropDownOpen) 
                        { 
                            IsDropDownOpen = true;
                            e.Handled = true; 
                            // Always open with the first item (400%) selected
                            SelectedIndex = 0;
                        }
                        break; 
                }
 
 
                if (!e.Handled)
                { 
                    base.OnPreviewKeyDown(e);
                }
            }
        } 

        //----------------------------------------------------- 
        // 
        //  Private Methods
        // 
        //------------------------------------------------------

        #region Private Methods
        ///  
        /// When the left mouse button is released, the resulting selection (if any) should
        /// be processed. 
        ///  
        /// A reference to the sender of the event (not used)
        /// Arguments to the event, used for the input text (not used) 
        private void OnPreviewMouseLeftButtonUp(object sender, EventArgs e)
        {
            _processSelections = true;
        } 

        ///  
        /// When the left mouse button press bubbles back up, we're done with it, so we 
        /// won't process further selections.
        ///  
        /// A reference to the sender of the event (not used)
        /// Arguments to the event, used for the input text (not used)
        private void OnMouseLeftButtonUp(object sender, EventArgs e)
        { 
            _processSelections = false;
        } 
 
        /// 
        /// This will check the characters that have been entered into the TextBox, and restrict it 
        /// to only the valid set.
        /// 
        /// A reference to the sender of the event.
        /// Arguments to the event, used for the input text. 
        private void OnPreviewTextInput(object sender, TextCompositionEventArgs e)
        { 
            // This will limit which characters are allowed to be entered into the TextBox 
            // Currently this is limited to 0-9, ',', '.', '%'
            if ((e != null) && (!String.IsNullOrEmpty(e.Text))) 
            {
                if (IsValidInputChar(e.Text[0]))
                {
                    // Set editing mode and allow the ComboBox to handle it. 
                    _isEditingText = true;
                } 
                else 
                {
                    // Do not allow any remaining characters for text input. 
                    e.Handled = true;
                }
            }
        } 

        ///  
        /// This will validate incoming strings pasted into the textbox, only pasting 
        /// valid (all digit) strings.
        ///  
        /// A reference to the sender of the event.
        /// Arguments to the event, used to determine the input.
        private void OnPaste(object sender, DataObjectPastingEventArgs e)
        { 
            // Validate the parameters, return if data is null.
            if ((e == null) || (e.DataObject == null) || (String.IsNullOrEmpty(e.FormatToApply))) 
            { 
                return;
            } 

            // Acquire a reference to the new string.
            string incomingString = e.DataObject.GetData(e.FormatToApply) as string;
 
            if (IsValidInputString(incomingString))
            { 
                // Since the new content is valid set the ZoomComboBox as in edit mode 
                // and allow the text to be processed normally (ie don't CancelCommand).
                _isEditingText = true; 
            }
            else
            {
                // Cancel the paste if the string is null, empty, or otherwise invalid. 
                e.Handled = true;
                e.CancelCommand(); 
            } 
        }
 
        /// 
        /// Checks if the given string contains valid characters for this control.  Used for pasting
        /// and UI Automation.
        ///  
        /// The string to test.
        private bool IsValidInputString(string incomingString) 
        { 
            if (String.IsNullOrEmpty(incomingString))
            { 
                return false;
            }
            // Check that each character is valid
            foreach (char c in incomingString.ToCharArray()) 
            {
                // If the character is not a digit or acceptable symbol then refuse new content. 
                if (!(IsValidInputChar(c))) 
                {
                    return false; 
                }
            }
            return true;
        } 

        ///  
        /// Returns true if the character is valid for input to this control. 
        /// 
        /// The character to test. 
        private bool IsValidInputChar(char c)
        {
            // After discussing this with localization this is an approved method for
            // checking for digit input, as it works regardless of the keyboard mapping. 
            // The ',' '.' and '%' are allowed, as they are the only other characters that
            // can be displayed (or input) in a percentage.  Localization informed me that 
            // although not every culture uses them (ie North America might not use ',' in 
            // a percentage) they are the only required characters, and as such we filter
            // to only allow them to be input. 
            return (Char.IsDigit(c)) || (c == ',') || (c == '.') || (c == '%');
        }

        ///  
        /// Callback for the Zoom DependencyProperty.
        ///  
        /// The ZoomComboBox to update 
        /// The associated arguments.
        private static void OnZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            ZoomComboBox zoomComboBox = (ZoomComboBox)d;

            zoomComboBox.SetZoom((double)e.NewValue); 
        }
 
        ///  
        /// Converts a double Zoom value to a corresponding string (with % sign)
        ///  
        /// The zoom value to convert
        /// The converted string value
        /// 
        private static bool ZoomValueToString(double zoomValue, out string zoomString) 
        {
            // Check that value is a valid double. 
            if (!(double.IsNaN(zoomValue)) && !(double.IsInfinity(zoomValue))) 
            {
                try 
                {
                    // Ensure output string is formatted to current globalization standards.
                    zoomString = String.Format(CultureInfo.CurrentCulture,
                        SR.Get(SRID.ZoomPercentageConverterStringFormat), zoomValue); 
                    return true;
                } 
                // Allow empty catch statements. 
#pragma warning disable 56502
 
                catch (ArgumentNullException) { }
                catch (FormatException) { }

                // Disallow empty catch statements. 
#pragma warning restore 56502
            } 
 
            // Invalid zoom value encountered.
            zoomString = String.Empty; 
            return false;
        }

        ///  
        /// Set the default ComboBox properties
        ///  
        private void SetDefaults() 
        {
            ToolTip = SR.Get(SRID.ZoomComboBoxToolTip); 
            IsReadOnly = false;
            IsEditable = true;
            IsTabStop = false;
            IsTextSearchEnabled = false; 
        }
 
        ///  
        /// Attach any needed ComboBox event handlers.
        ///  
        private void SetHandlers()
        {
            PreviewTextInput += OnPreviewTextInput;
            PreviewMouseLeftButtonUp += OnPreviewMouseLeftButtonUp; 
            AddHandler(ComboBox.MouseLeftButtonUpEvent, new RoutedEventHandler(OnMouseLeftButtonUp), true);
            DataObject.AddPastingHandler(this, new DataObjectPastingEventHandler(OnPaste)); 
        } 
        #endregion Private Methods
 
        #region Nested Classes
        /// 
        /// AutomationPeer associated with ZoomComboBox
        ///  
        private class ZoomComboBoxBoxAutomationPeer : ComboBoxAutomationPeer, IValueProvider
        { 
            ///  
            /// Constructor
            ///  
            /// Owner of the AutomationPeer.
            public ZoomComboBoxBoxAutomationPeer(ZoomComboBox owner)
                : base(owner)
            { } 

            ///  
            ///  
            /// 
            override protected string GetClassNameCore() 
            {
                return "ZoomComboBox";
            }
 
            /// 
            ///  
            ///  
            override public object GetPattern(PatternInterface patternInterface)
            { 
                if (patternInterface == PatternInterface.Value)
                {
                    return this;
                } 
                else
                { 
                    return base.GetPattern(patternInterface); 
                }
            } 

            void IValueProvider.SetValue(string value)
            {
                if (value == null) 
                {
                    throw new ArgumentNullException("value"); 
                } 

                if (!IsEnabled()) 
                {
                    throw new ElementNotEnabledException();
                }
 
                ZoomComboBox owner = (ZoomComboBox)Owner;
 
                if (owner.IsReadOnly) 
                {
                    throw new ElementNotEnabledException(); 
                }

                if (owner.IsValidInputString(value))
                { 
                    owner.Text = value;
                    owner._isEditingText = true; 
                    owner.OnZoomValueEdited(); 
                }
            } 
        }
        #endregion

        //----------------------------------------------------- 
        //
        //  Private Fields 
        // 
        //------------------------------------------------------
 
        private bool _isEditingText;
        private bool _processSelections = false;
        private TextBox _editableTextBox;
        private const string _editableTextBoxName = "PART_EditableTextBox"; 
        private const double _zoomDefault = 0.0;
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK