DataGridComboBoxColumn.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / DataGridComboBoxColumn.cs / 1305600 / DataGridComboBoxColumn.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System; 
using System.Collections; 
using System.ComponentModel;
using System.Diagnostics; 
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
 
namespace System.Windows.Controls
{ 
    ///  
    ///     A column that displays a drop-down list while in edit mode.
    ///  
    public class DataGridComboBoxColumn : DataGridColumn
    {
        #region Constructors
 
        static DataGridComboBoxColumn()
        { 
            SortMemberPathProperty.OverrideMetadata(typeof(DataGridComboBoxColumn), new FrameworkPropertyMetadata(null, OnCoerceSortMemberPath)); 
        }
 
        #endregion

        #region Helper Type for Styling
 
        internal class TextBlockComboBox : ComboBox
        { 
            static TextBlockComboBox() 
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBlockComboBox), new FrameworkPropertyMetadata(DataGridComboBoxColumn.TextBlockComboBoxStyleKey)); 
                KeyboardNavigation.IsTabStopProperty.OverrideMetadata(typeof(TextBlockComboBox), new FrameworkPropertyMetadata(false));
            }
        }
 
        /// 
        ///     Style key for TextBlockComboBox 
        ///  
        public static ComponentResourceKey TextBlockComboBoxStyleKey
        { 
            get
            {
                return SystemResourceKey.DataGridComboBoxColumnTextBlockComboBoxStyleKey;
            } 
        }
 
        #endregion 

        #region Binding 

        private static object OnCoerceSortMemberPath(DependencyObject d, object baseValue)
        {
            var column = (DataGridComboBoxColumn)d; 
            var sortMemberPath = (string)baseValue;
 
            if (string.IsNullOrEmpty(sortMemberPath)) 
            {
                var bindingSortMemberPath = DataGridHelper.GetPathFromBinding(column.EffectiveBinding as Binding); 
                if (!string.IsNullOrEmpty(bindingSortMemberPath))
                {
                    sortMemberPath = bindingSortMemberPath;
                } 
            }
 
            return sortMemberPath; 
        }
 
        /// 
        ///     Chooses either SelectedItemBinding, TextBinding, SelectedValueBinding or  based which are set.
        /// 
        private BindingBase EffectiveBinding 
        {
            get 
            { 
                if (SelectedItemBinding != null)
                { 
                    return SelectedItemBinding;
                }
                else if (SelectedValueBinding != null)
                { 
                    return SelectedValueBinding;
                } 
                else 
                {
                    return TextBinding; 
                }
            }
        }
 
        /// 
        ///     The binding that will be applied to the SelectedValue property of the ComboBox.  This works in conjunction with SelectedValuePath 
        ///  
        /// 
        ///     This isn't a DP because if it were getting the value would evaluate the binding. 
        /// 
        public virtual BindingBase SelectedValueBinding
        {
            get 
            {
                return _selectedValueBinding; 
            } 

            set 
            {
                if (_selectedValueBinding != value)
                {
                    BindingBase oldBinding = _selectedValueBinding; 
                    _selectedValueBinding = value;
                    CoerceValue(IsReadOnlyProperty); 
                    CoerceValue(SortMemberPathProperty); 
                    OnSelectedValueBindingChanged(oldBinding, _selectedValueBinding);
                } 
            }
        }

        protected override bool OnCoerceIsReadOnly(bool baseValue) 
        {
            if (DataGridHelper.IsOneWay(EffectiveBinding)) 
            { 
                return true;
            } 

            // only call the base if we dont want to force IsReadOnly true
            return base.OnCoerceIsReadOnly(baseValue);
        } 

        ///  
        ///     The binding that will be applied to the SelectedItem property of the ComboBoxValue. 
        /// 
        ///  
        ///     This isn't a DP because if it were getting the value would evaluate the binding.
        /// 
        public virtual BindingBase SelectedItemBinding
        { 
            get
            { 
                return _selectedItemBinding; 
            }
 
            set
            {
                if (_selectedItemBinding != value)
                { 
                    BindingBase oldBinding = _selectedItemBinding;
                    _selectedItemBinding = value; 
                    CoerceValue(IsReadOnlyProperty); 
                    CoerceValue(SortMemberPathProperty);
                    OnSelectedItemBindingChanged(oldBinding, _selectedItemBinding); 
                }
            }
        }
 
        /// 
        ///     The binding that will be applied to the Text property of the ComboBoxValue. 
        ///  
        /// 
        ///     This isn't a DP because if it were getting the value would evaluate the binding. 
        /// 
        public virtual BindingBase TextBinding
        {
            get 
            {
                return _textBinding; 
            } 

            set 
            {
                if (_textBinding != value)
                {
                    BindingBase oldBinding = _textBinding; 
                    _textBinding = value;
                    CoerceValue(IsReadOnlyProperty); 
                    CoerceValue(SortMemberPathProperty); 
                    OnTextBindingChanged(oldBinding, _textBinding);
                } 
            }
        }

        ///  
        ///     Called when SelectedValueBinding changes.
        ///  
        /// The old binding. 
        /// The new binding.
        protected virtual void OnSelectedValueBindingChanged(BindingBase oldBinding, BindingBase newBinding) 
        {
            NotifyPropertyChanged("SelectedValueBinding");
        }
 
        /// 
        ///     Called when SelectedItemBinding changes. 
        ///  
        /// The old binding.
        /// The new binding. 
        protected virtual void OnSelectedItemBindingChanged(BindingBase oldBinding, BindingBase newBinding)
        {
            NotifyPropertyChanged("SelectedItemBinding");
        } 

        ///  
        ///     Called when TextBinding changes. 
        /// 
        /// The old binding. 
        /// The new binding.
        protected virtual void OnTextBindingChanged(BindingBase oldBinding, BindingBase newBinding)
        {
            NotifyPropertyChanged("TextBinding"); 
        }
 
        #endregion 

        #region Styling 

        /// 
        ///     The default value of the ElementStyle property.
        ///     This value can be used as the BasedOn for new styles. 
        /// 
        public static Style DefaultElementStyle 
        { 
            get
            { 
                if (_defaultElementStyle == null)
                {
                    Style style = new Style(typeof(ComboBox));
 
                    // Set IsSynchronizedWithCurrentItem to false by default
                    style.Setters.Add(new Setter(ComboBox.IsSynchronizedWithCurrentItemProperty, false)); 
 
                    style.Seal();
                    _defaultElementStyle = style; 
                }

                return _defaultElementStyle;
            } 
        }
 
        ///  
        ///     The default value of the EditingElementStyle property.
        ///     This value can be used as the BasedOn for new styles. 
        /// 
        public static Style DefaultEditingElementStyle
        {
            get 
            {
                // return the same as that of DefaultElementStyle 
                return DefaultElementStyle; 
            }
        } 

        /// 
        ///     A style that is applied to the generated element when not editing.
        ///     The TargetType of the style depends on the derived column class. 
        /// 
        public Style ElementStyle 
        { 
            get { return (Style)GetValue(ElementStyleProperty); }
            set { SetValue(ElementStyleProperty, value); } 
        }

        /// 
        ///     The DependencyProperty for the ElementStyle property. 
        /// 
        public static readonly DependencyProperty ElementStyleProperty = 
            DataGridBoundColumn.ElementStyleProperty.AddOwner(typeof(DataGridComboBoxColumn), new FrameworkPropertyMetadata(DefaultElementStyle)); 

        ///  
        ///     A style that is applied to the generated element when editing.
        ///     The TargetType of the style depends on the derived column class.
        /// 
        public Style EditingElementStyle 
        {
            get { return (Style)GetValue(EditingElementStyleProperty); } 
            set { SetValue(EditingElementStyleProperty, value); } 
        }
 
        /// 
        ///     The DependencyProperty for the EditingElementStyle property.
        /// 
        public static readonly DependencyProperty EditingElementStyleProperty = 
            DataGridBoundColumn.EditingElementStyleProperty.AddOwner(typeof(DataGridComboBoxColumn), new FrameworkPropertyMetadata(DefaultEditingElementStyle));
 
        ///  
        ///     Assigns the ElementStyle to the desired property on the given element.
        ///  
        private void ApplyStyle(bool isEditing, bool defaultToElementStyle, FrameworkElement element)
        {
            Style style = PickStyle(isEditing, defaultToElementStyle);
            if (style != null) 
            {
                element.Style = style; 
            } 
        }
 
        /// 
        ///     Assigns the ElementStyle to the desired property on the given element.
        /// 
        internal void ApplyStyle(bool isEditing, bool defaultToElementStyle, FrameworkContentElement element) 
        {
            Style style = PickStyle(isEditing, defaultToElementStyle); 
            if (style != null) 
            {
                element.Style = style; 
            }
        }

        private Style PickStyle(bool isEditing, bool defaultToElementStyle) 
        {
            Style style = isEditing ? EditingElementStyle : ElementStyle; 
            if (isEditing && defaultToElementStyle && (style == null)) 
            {
                style = ElementStyle; 
            }

            return style;
        } 

        ///  
        ///     Assigns the Binding to the desired property on the target object. 
        /// 
        private static void ApplyBinding(BindingBase binding, DependencyObject target, DependencyProperty property) 
        {
            if (binding != null)
            {
                BindingOperations.SetBinding(target, property, binding); 
            }
            else 
            { 
                BindingOperations.ClearBinding(target, property);
            } 
        }

        #endregion
 
        #region Clipboard Copy/Paste
 
        ///  
        /// If base ClipboardContentBinding is not set we use Binding.
        ///  
        public override BindingBase ClipboardContentBinding
        {
            get
            { 
                return base.ClipboardContentBinding ?? EffectiveBinding;
            } 
 
            set
            { 
                base.ClipboardContentBinding = value;
            }
        }
 
        #endregion
 
        #region ComboBox Column Properties 

        ///  
        ///     The ComboBox will attach to this ItemsSource.
        /// 
        public IEnumerable ItemsSource
        { 
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); } 
        } 

        ///  
        ///     The DependencyProperty for ItemsSource.
        /// 
        public static readonly DependencyProperty ItemsSourceProperty =
            ComboBox.ItemsSourceProperty.AddOwner(typeof(DataGridComboBoxColumn), new FrameworkPropertyMetadata(null, DataGridColumn.NotifyPropertyChangeForRefreshContent)); 

        ///  
        ///     DisplayMemberPath is a simple way to define a default template 
        ///     that describes how to convert Items into UI elements by using
        ///     the specified path. 
        /// 
        public string DisplayMemberPath
        {
            get { return (string)GetValue(DisplayMemberPathProperty); } 
            set { SetValue(DisplayMemberPathProperty, value); }
        } 
 
        /// 
        ///     The DependencyProperty for the DisplayMemberPath property. 
        /// 
        public static readonly DependencyProperty DisplayMemberPathProperty =
                ComboBox.DisplayMemberPathProperty.AddOwner(typeof(DataGridComboBoxColumn), new FrameworkPropertyMetadata(string.Empty, DataGridColumn.NotifyPropertyChangeForRefreshContent));
 
        /// 
        ///  The path used to retrieve the SelectedValue from the SelectedItem 
        ///  
        public string SelectedValuePath
        { 
            get { return (string)GetValue(SelectedValuePathProperty); }
            set { SetValue(SelectedValuePathProperty, value); }
        }
 
        /// 
        ///     SelectedValuePath DependencyProperty 
        ///  
        public static readonly DependencyProperty SelectedValuePathProperty =
                ComboBox.SelectedValuePathProperty.AddOwner(typeof(DataGridComboBoxColumn), new FrameworkPropertyMetadata(string.Empty, DataGridColumn.NotifyPropertyChangeForRefreshContent)); 

        #endregion

        #region Property Changed Handler 

        protected internal override void RefreshCellContent(FrameworkElement element, string propertyName) 
        { 
            DataGridCell cell = element as DataGridCell;
            if (cell != null) 
            {
                bool isCellEditing = cell.IsEditing;
                if ((string.Compare(propertyName, "ElementStyle", StringComparison.Ordinal) == 0 && !isCellEditing) ||
                    (string.Compare(propertyName, "EditingElementStyle", StringComparison.Ordinal) == 0 && isCellEditing)) 
                {
                    cell.BuildVisualTree(); 
                } 
                else
                { 
                    ComboBox comboBox = cell.Content as ComboBox;
                    switch (propertyName)
                    {
                        case "SelectedItemBinding": 
                            ApplyBinding(SelectedItemBinding, comboBox, ComboBox.SelectedItemProperty);
                            break; 
                        case "SelectedValueBinding": 
                            ApplyBinding(SelectedValueBinding, comboBox, ComboBox.SelectedValueProperty);
                            break; 
                        case "TextBinding":
                            ApplyBinding(TextBinding, comboBox, ComboBox.TextProperty);
                            break;
                        case "SelectedValuePath": 
                            DataGridHelper.SyncColumnProperty(this, comboBox, ComboBox.SelectedValuePathProperty, SelectedValuePathProperty);
                            break; 
                        case "DisplayMemberPath": 
                            DataGridHelper.SyncColumnProperty(this, comboBox, ComboBox.DisplayMemberPathProperty, DisplayMemberPathProperty);
                            break; 
                        case "ItemsSource":
                            DataGridHelper.SyncColumnProperty(this, comboBox, ComboBox.ItemsSourceProperty, ItemsSourceProperty);
                            break;
                        default: 
                            base.RefreshCellContent(element, propertyName);
                            break; 
                    } 
                }
            } 
            else
            {
                base.RefreshCellContent(element, propertyName);
            } 
        }
 
        #endregion 

        #region BindingTarget Helpers 

        /// 
        /// Helper method which returns selection value from
        /// combobox based on which Binding's were set. 
        /// 
        ///  
        ///  
        private object GetComboBoxSelectionValue(ComboBox comboBox)
        { 
            if (SelectedItemBinding != null)
            {
                return comboBox.SelectedItem;
            } 
            else if (SelectedValueBinding != null)
            { 
                return comboBox.SelectedValue; 
            }
            else 
            {
                return comboBox.Text;
            }
        } 

        #endregion 
 
        #region Element Generation
 
        /// 
        ///     Creates the visual tree for text based cells.
        /// 
        protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem) 
        {
            TextBlockComboBox comboBox = new TextBlockComboBox(); 
 
            ApplyStyle(/* isEditing = */ false, /* defaultToElementStyle = */ false, comboBox);
            ApplyColumnProperties(comboBox); 

            return comboBox;
        }
 
        /// 
        ///     Creates the visual tree for text based cells. 
        ///  
        protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
        { 
            ComboBox comboBox = new ComboBox();

            ApplyStyle(/* isEditing = */ true, /* defaultToElementStyle = */ false, comboBox);
            ApplyColumnProperties(comboBox); 

            return comboBox; 
        } 

        private void ApplyColumnProperties(ComboBox comboBox) 
        {
            ApplyBinding(SelectedItemBinding, comboBox, ComboBox.SelectedItemProperty);
            ApplyBinding(SelectedValueBinding, comboBox, ComboBox.SelectedValueProperty);
            ApplyBinding(TextBinding, comboBox, ComboBox.TextProperty); 

            DataGridHelper.SyncColumnProperty(this, comboBox, ComboBox.SelectedValuePathProperty, SelectedValuePathProperty); 
            DataGridHelper.SyncColumnProperty(this, comboBox, ComboBox.DisplayMemberPathProperty, DisplayMemberPathProperty); 
            DataGridHelper.SyncColumnProperty(this, comboBox, ComboBox.ItemsSourceProperty, ItemsSourceProperty);
        } 

        #endregion

        #region Editing 

        ///  
        ///     Called when a cell has just switched to edit mode. 
        /// 
        /// A reference to element returned by GenerateEditingElement. 
        /// The event args of the input event that caused the cell to go into edit mode. May be null.
        /// The unedited value of the cell.
        protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
        { 
            ComboBox comboBox = editingElement as ComboBox;
            if (comboBox != null) 
            { 
                comboBox.Focus();
                object originalValue = GetComboBoxSelectionValue(comboBox); 

                if (IsComboBoxOpeningInputEvent(editingEventArgs))
                {
                    comboBox.IsDropDownOpen = true; 
                }
 
                return originalValue; 
            }
 
            return null;
        }

        internal override void OnInput(InputEventArgs e) 
        {
            if (IsComboBoxOpeningInputEvent(e)) 
            { 
                BeginEdit(e);
            } 
        }

        private static bool IsComboBoxOpeningInputEvent(RoutedEventArgs e)
        { 
            KeyEventArgs keyArgs = e as KeyEventArgs;
            if ((keyArgs != null) && ((keyArgs.KeyStates & KeyStates.Down) == KeyStates.Down)) 
            { 
                bool isAltDown = (keyArgs.KeyboardDevice.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt;
 
                // We want to handle the ALT key. Get the real key if it is Key.System.
                Key key = keyArgs.Key;
                if (key == Key.System)
                { 
                    key = keyArgs.SystemKey;
                } 
 
                // F4 alone or ALT+Up or ALT+Down will open the drop-down
                return ((key == Key.F4) && !isAltDown) || 
                       (((key == Key.Up) || (key == Key.Down)) && isAltDown);
            }

            return false; 
        }
 
        #endregion 

        #region Data 

        private static Style _defaultElementStyle;

        private BindingBase _selectedValueBinding; 
        private BindingBase _selectedItemBinding;
        private BindingBase _textBinding; 
 
        #endregion
    } 
}

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

using System; 
using System.Collections; 
using System.ComponentModel;
using System.Diagnostics; 
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
 
namespace System.Windows.Controls
{ 
    ///  
    ///     A column that displays a drop-down list while in edit mode.
    ///  
    public class DataGridComboBoxColumn : DataGridColumn
    {
        #region Constructors
 
        static DataGridComboBoxColumn()
        { 
            SortMemberPathProperty.OverrideMetadata(typeof(DataGridComboBoxColumn), new FrameworkPropertyMetadata(null, OnCoerceSortMemberPath)); 
        }
 
        #endregion

        #region Helper Type for Styling
 
        internal class TextBlockComboBox : ComboBox
        { 
            static TextBlockComboBox() 
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBlockComboBox), new FrameworkPropertyMetadata(DataGridComboBoxColumn.TextBlockComboBoxStyleKey)); 
                KeyboardNavigation.IsTabStopProperty.OverrideMetadata(typeof(TextBlockComboBox), new FrameworkPropertyMetadata(false));
            }
        }
 
        /// 
        ///     Style key for TextBlockComboBox 
        ///  
        public static ComponentResourceKey TextBlockComboBoxStyleKey
        { 
            get
            {
                return SystemResourceKey.DataGridComboBoxColumnTextBlockComboBoxStyleKey;
            } 
        }
 
        #endregion 

        #region Binding 

        private static object OnCoerceSortMemberPath(DependencyObject d, object baseValue)
        {
            var column = (DataGridComboBoxColumn)d; 
            var sortMemberPath = (string)baseValue;
 
            if (string.IsNullOrEmpty(sortMemberPath)) 
            {
                var bindingSortMemberPath = DataGridHelper.GetPathFromBinding(column.EffectiveBinding as Binding); 
                if (!string.IsNullOrEmpty(bindingSortMemberPath))
                {
                    sortMemberPath = bindingSortMemberPath;
                } 
            }
 
            return sortMemberPath; 
        }
 
        /// 
        ///     Chooses either SelectedItemBinding, TextBinding, SelectedValueBinding or  based which are set.
        /// 
        private BindingBase EffectiveBinding 
        {
            get 
            { 
                if (SelectedItemBinding != null)
                { 
                    return SelectedItemBinding;
                }
                else if (SelectedValueBinding != null)
                { 
                    return SelectedValueBinding;
                } 
                else 
                {
                    return TextBinding; 
                }
            }
        }
 
        /// 
        ///     The binding that will be applied to the SelectedValue property of the ComboBox.  This works in conjunction with SelectedValuePath 
        ///  
        /// 
        ///     This isn't a DP because if it were getting the value would evaluate the binding. 
        /// 
        public virtual BindingBase SelectedValueBinding
        {
            get 
            {
                return _selectedValueBinding; 
            } 

            set 
            {
                if (_selectedValueBinding != value)
                {
                    BindingBase oldBinding = _selectedValueBinding; 
                    _selectedValueBinding = value;
                    CoerceValue(IsReadOnlyProperty); 
                    CoerceValue(SortMemberPathProperty); 
                    OnSelectedValueBindingChanged(oldBinding, _selectedValueBinding);
                } 
            }
        }

        protected override bool OnCoerceIsReadOnly(bool baseValue) 
        {
            if (DataGridHelper.IsOneWay(EffectiveBinding)) 
            { 
                return true;
            } 

            // only call the base if we dont want to force IsReadOnly true
            return base.OnCoerceIsReadOnly(baseValue);
        } 

        ///  
        ///     The binding that will be applied to the SelectedItem property of the ComboBoxValue. 
        /// 
        ///  
        ///     This isn't a DP because if it were getting the value would evaluate the binding.
        /// 
        public virtual BindingBase SelectedItemBinding
        { 
            get
            { 
                return _selectedItemBinding; 
            }
 
            set
            {
                if (_selectedItemBinding != value)
                { 
                    BindingBase oldBinding = _selectedItemBinding;
                    _selectedItemBinding = value; 
                    CoerceValue(IsReadOnlyProperty); 
                    CoerceValue(SortMemberPathProperty);
                    OnSelectedItemBindingChanged(oldBinding, _selectedItemBinding); 
                }
            }
        }
 
        /// 
        ///     The binding that will be applied to the Text property of the ComboBoxValue. 
        ///  
        /// 
        ///     This isn't a DP because if it were getting the value would evaluate the binding. 
        /// 
        public virtual BindingBase TextBinding
        {
            get 
            {
                return _textBinding; 
            } 

            set 
            {
                if (_textBinding != value)
                {
                    BindingBase oldBinding = _textBinding; 
                    _textBinding = value;
                    CoerceValue(IsReadOnlyProperty); 
                    CoerceValue(SortMemberPathProperty); 
                    OnTextBindingChanged(oldBinding, _textBinding);
                } 
            }
        }

        ///  
        ///     Called when SelectedValueBinding changes.
        ///  
        /// The old binding. 
        /// The new binding.
        protected virtual void OnSelectedValueBindingChanged(BindingBase oldBinding, BindingBase newBinding) 
        {
            NotifyPropertyChanged("SelectedValueBinding");
        }
 
        /// 
        ///     Called when SelectedItemBinding changes. 
        ///  
        /// The old binding.
        /// The new binding. 
        protected virtual void OnSelectedItemBindingChanged(BindingBase oldBinding, BindingBase newBinding)
        {
            NotifyPropertyChanged("SelectedItemBinding");
        } 

        ///  
        ///     Called when TextBinding changes. 
        /// 
        /// The old binding. 
        /// The new binding.
        protected virtual void OnTextBindingChanged(BindingBase oldBinding, BindingBase newBinding)
        {
            NotifyPropertyChanged("TextBinding"); 
        }
 
        #endregion 

        #region Styling 

        /// 
        ///     The default value of the ElementStyle property.
        ///     This value can be used as the BasedOn for new styles. 
        /// 
        public static Style DefaultElementStyle 
        { 
            get
            { 
                if (_defaultElementStyle == null)
                {
                    Style style = new Style(typeof(ComboBox));
 
                    // Set IsSynchronizedWithCurrentItem to false by default
                    style.Setters.Add(new Setter(ComboBox.IsSynchronizedWithCurrentItemProperty, false)); 
 
                    style.Seal();
                    _defaultElementStyle = style; 
                }

                return _defaultElementStyle;
            } 
        }
 
        ///  
        ///     The default value of the EditingElementStyle property.
        ///     This value can be used as the BasedOn for new styles. 
        /// 
        public static Style DefaultEditingElementStyle
        {
            get 
            {
                // return the same as that of DefaultElementStyle 
                return DefaultElementStyle; 
            }
        } 

        /// 
        ///     A style that is applied to the generated element when not editing.
        ///     The TargetType of the style depends on the derived column class. 
        /// 
        public Style ElementStyle 
        { 
            get { return (Style)GetValue(ElementStyleProperty); }
            set { SetValue(ElementStyleProperty, value); } 
        }

        /// 
        ///     The DependencyProperty for the ElementStyle property. 
        /// 
        public static readonly DependencyProperty ElementStyleProperty = 
            DataGridBoundColumn.ElementStyleProperty.AddOwner(typeof(DataGridComboBoxColumn), new FrameworkPropertyMetadata(DefaultElementStyle)); 

        ///  
        ///     A style that is applied to the generated element when editing.
        ///     The TargetType of the style depends on the derived column class.
        /// 
        public Style EditingElementStyle 
        {
            get { return (Style)GetValue(EditingElementStyleProperty); } 
            set { SetValue(EditingElementStyleProperty, value); } 
        }
 
        /// 
        ///     The DependencyProperty for the EditingElementStyle property.
        /// 
        public static readonly DependencyProperty EditingElementStyleProperty = 
            DataGridBoundColumn.EditingElementStyleProperty.AddOwner(typeof(DataGridComboBoxColumn), new FrameworkPropertyMetadata(DefaultEditingElementStyle));
 
        ///  
        ///     Assigns the ElementStyle to the desired property on the given element.
        ///  
        private void ApplyStyle(bool isEditing, bool defaultToElementStyle, FrameworkElement element)
        {
            Style style = PickStyle(isEditing, defaultToElementStyle);
            if (style != null) 
            {
                element.Style = style; 
            } 
        }
 
        /// 
        ///     Assigns the ElementStyle to the desired property on the given element.
        /// 
        internal void ApplyStyle(bool isEditing, bool defaultToElementStyle, FrameworkContentElement element) 
        {
            Style style = PickStyle(isEditing, defaultToElementStyle); 
            if (style != null) 
            {
                element.Style = style; 
            }
        }

        private Style PickStyle(bool isEditing, bool defaultToElementStyle) 
        {
            Style style = isEditing ? EditingElementStyle : ElementStyle; 
            if (isEditing && defaultToElementStyle && (style == null)) 
            {
                style = ElementStyle; 
            }

            return style;
        } 

        ///  
        ///     Assigns the Binding to the desired property on the target object. 
        /// 
        private static void ApplyBinding(BindingBase binding, DependencyObject target, DependencyProperty property) 
        {
            if (binding != null)
            {
                BindingOperations.SetBinding(target, property, binding); 
            }
            else 
            { 
                BindingOperations.ClearBinding(target, property);
            } 
        }

        #endregion
 
        #region Clipboard Copy/Paste
 
        ///  
        /// If base ClipboardContentBinding is not set we use Binding.
        ///  
        public override BindingBase ClipboardContentBinding
        {
            get
            { 
                return base.ClipboardContentBinding ?? EffectiveBinding;
            } 
 
            set
            { 
                base.ClipboardContentBinding = value;
            }
        }
 
        #endregion
 
        #region ComboBox Column Properties 

        ///  
        ///     The ComboBox will attach to this ItemsSource.
        /// 
        public IEnumerable ItemsSource
        { 
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); } 
        } 

        ///  
        ///     The DependencyProperty for ItemsSource.
        /// 
        public static readonly DependencyProperty ItemsSourceProperty =
            ComboBox.ItemsSourceProperty.AddOwner(typeof(DataGridComboBoxColumn), new FrameworkPropertyMetadata(null, DataGridColumn.NotifyPropertyChangeForRefreshContent)); 

        ///  
        ///     DisplayMemberPath is a simple way to define a default template 
        ///     that describes how to convert Items into UI elements by using
        ///     the specified path. 
        /// 
        public string DisplayMemberPath
        {
            get { return (string)GetValue(DisplayMemberPathProperty); } 
            set { SetValue(DisplayMemberPathProperty, value); }
        } 
 
        /// 
        ///     The DependencyProperty for the DisplayMemberPath property. 
        /// 
        public static readonly DependencyProperty DisplayMemberPathProperty =
                ComboBox.DisplayMemberPathProperty.AddOwner(typeof(DataGridComboBoxColumn), new FrameworkPropertyMetadata(string.Empty, DataGridColumn.NotifyPropertyChangeForRefreshContent));
 
        /// 
        ///  The path used to retrieve the SelectedValue from the SelectedItem 
        ///  
        public string SelectedValuePath
        { 
            get { return (string)GetValue(SelectedValuePathProperty); }
            set { SetValue(SelectedValuePathProperty, value); }
        }
 
        /// 
        ///     SelectedValuePath DependencyProperty 
        ///  
        public static readonly DependencyProperty SelectedValuePathProperty =
                ComboBox.SelectedValuePathProperty.AddOwner(typeof(DataGridComboBoxColumn), new FrameworkPropertyMetadata(string.Empty, DataGridColumn.NotifyPropertyChangeForRefreshContent)); 

        #endregion

        #region Property Changed Handler 

        protected internal override void RefreshCellContent(FrameworkElement element, string propertyName) 
        { 
            DataGridCell cell = element as DataGridCell;
            if (cell != null) 
            {
                bool isCellEditing = cell.IsEditing;
                if ((string.Compare(propertyName, "ElementStyle", StringComparison.Ordinal) == 0 && !isCellEditing) ||
                    (string.Compare(propertyName, "EditingElementStyle", StringComparison.Ordinal) == 0 && isCellEditing)) 
                {
                    cell.BuildVisualTree(); 
                } 
                else
                { 
                    ComboBox comboBox = cell.Content as ComboBox;
                    switch (propertyName)
                    {
                        case "SelectedItemBinding": 
                            ApplyBinding(SelectedItemBinding, comboBox, ComboBox.SelectedItemProperty);
                            break; 
                        case "SelectedValueBinding": 
                            ApplyBinding(SelectedValueBinding, comboBox, ComboBox.SelectedValueProperty);
                            break; 
                        case "TextBinding":
                            ApplyBinding(TextBinding, comboBox, ComboBox.TextProperty);
                            break;
                        case "SelectedValuePath": 
                            DataGridHelper.SyncColumnProperty(this, comboBox, ComboBox.SelectedValuePathProperty, SelectedValuePathProperty);
                            break; 
                        case "DisplayMemberPath": 
                            DataGridHelper.SyncColumnProperty(this, comboBox, ComboBox.DisplayMemberPathProperty, DisplayMemberPathProperty);
                            break; 
                        case "ItemsSource":
                            DataGridHelper.SyncColumnProperty(this, comboBox, ComboBox.ItemsSourceProperty, ItemsSourceProperty);
                            break;
                        default: 
                            base.RefreshCellContent(element, propertyName);
                            break; 
                    } 
                }
            } 
            else
            {
                base.RefreshCellContent(element, propertyName);
            } 
        }
 
        #endregion 

        #region BindingTarget Helpers 

        /// 
        /// Helper method which returns selection value from
        /// combobox based on which Binding's were set. 
        /// 
        ///  
        ///  
        private object GetComboBoxSelectionValue(ComboBox comboBox)
        { 
            if (SelectedItemBinding != null)
            {
                return comboBox.SelectedItem;
            } 
            else if (SelectedValueBinding != null)
            { 
                return comboBox.SelectedValue; 
            }
            else 
            {
                return comboBox.Text;
            }
        } 

        #endregion 
 
        #region Element Generation
 
        /// 
        ///     Creates the visual tree for text based cells.
        /// 
        protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem) 
        {
            TextBlockComboBox comboBox = new TextBlockComboBox(); 
 
            ApplyStyle(/* isEditing = */ false, /* defaultToElementStyle = */ false, comboBox);
            ApplyColumnProperties(comboBox); 

            return comboBox;
        }
 
        /// 
        ///     Creates the visual tree for text based cells. 
        ///  
        protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
        { 
            ComboBox comboBox = new ComboBox();

            ApplyStyle(/* isEditing = */ true, /* defaultToElementStyle = */ false, comboBox);
            ApplyColumnProperties(comboBox); 

            return comboBox; 
        } 

        private void ApplyColumnProperties(ComboBox comboBox) 
        {
            ApplyBinding(SelectedItemBinding, comboBox, ComboBox.SelectedItemProperty);
            ApplyBinding(SelectedValueBinding, comboBox, ComboBox.SelectedValueProperty);
            ApplyBinding(TextBinding, comboBox, ComboBox.TextProperty); 

            DataGridHelper.SyncColumnProperty(this, comboBox, ComboBox.SelectedValuePathProperty, SelectedValuePathProperty); 
            DataGridHelper.SyncColumnProperty(this, comboBox, ComboBox.DisplayMemberPathProperty, DisplayMemberPathProperty); 
            DataGridHelper.SyncColumnProperty(this, comboBox, ComboBox.ItemsSourceProperty, ItemsSourceProperty);
        } 

        #endregion

        #region Editing 

        ///  
        ///     Called when a cell has just switched to edit mode. 
        /// 
        /// A reference to element returned by GenerateEditingElement. 
        /// The event args of the input event that caused the cell to go into edit mode. May be null.
        /// The unedited value of the cell.
        protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
        { 
            ComboBox comboBox = editingElement as ComboBox;
            if (comboBox != null) 
            { 
                comboBox.Focus();
                object originalValue = GetComboBoxSelectionValue(comboBox); 

                if (IsComboBoxOpeningInputEvent(editingEventArgs))
                {
                    comboBox.IsDropDownOpen = true; 
                }
 
                return originalValue; 
            }
 
            return null;
        }

        internal override void OnInput(InputEventArgs e) 
        {
            if (IsComboBoxOpeningInputEvent(e)) 
            { 
                BeginEdit(e);
            } 
        }

        private static bool IsComboBoxOpeningInputEvent(RoutedEventArgs e)
        { 
            KeyEventArgs keyArgs = e as KeyEventArgs;
            if ((keyArgs != null) && ((keyArgs.KeyStates & KeyStates.Down) == KeyStates.Down)) 
            { 
                bool isAltDown = (keyArgs.KeyboardDevice.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt;
 
                // We want to handle the ALT key. Get the real key if it is Key.System.
                Key key = keyArgs.Key;
                if (key == Key.System)
                { 
                    key = keyArgs.SystemKey;
                } 
 
                // F4 alone or ALT+Up or ALT+Down will open the drop-down
                return ((key == Key.F4) && !isAltDown) || 
                       (((key == Key.Up) || (key == Key.Down)) && isAltDown);
            }

            return false; 
        }
 
        #endregion 

        #region Data 

        private static Style _defaultElementStyle;

        private BindingBase _selectedValueBinding; 
        private BindingBase _selectedItemBinding;
        private BindingBase _textBinding; 
 
        #endregion
    } 
}

// 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