diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckComboBox/Implementation/CheckComboBox.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckComboBox/Implementation/CheckComboBox.cs new file mode 100644 index 00000000..5bdbfecd --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckComboBox/Implementation/CheckComboBox.cs @@ -0,0 +1,137 @@ +using System; +using System.Windows; +using Microsoft.Windows.Controls.Primitives; + +namespace Microsoft.Windows.Controls +{ + public class CheckComboBox : Selector + { + private bool _surpressTextUpdate; + + #region Constructors + + static CheckComboBox() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckComboBox), new FrameworkPropertyMetadata(typeof(CheckComboBox))); + } + + public CheckComboBox() + { + + } + + #endregion //Constructors + + #region Properties + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(CheckComboBox), new UIPropertyMetadata(null)); + public string Text + { + get { return (string)GetValue(TextProperty); } + set { SetValue(TextProperty, value); } + } + + #region IsDropDownOpen + + public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(CheckComboBox), new UIPropertyMetadata(false, OnIsDropDownOpenChanged)); + public bool IsDropDownOpen + { + get { return (bool)GetValue(IsDropDownOpenProperty); } + set { SetValue(IsDropDownOpenProperty, value); } + } + + private static void OnIsDropDownOpenChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + CheckComboBox comboBox = o as CheckComboBox; + if (comboBox != null) + comboBox.OnIsDropDownOpenChanged((bool)e.OldValue, (bool)e.NewValue); + } + + protected virtual void OnIsDropDownOpenChanged(bool oldValue, bool newValue) + { + // TODO: Add your property changed side-effects. Descendants can override as well. + } + + #endregion //IsDropDownOpen + + #endregion //Properties + + #region Base Class Overrides + + protected override void OnSelectedValueChanged(string oldValue, string newValue) + { + base.OnSelectedValueChanged(oldValue, newValue); + + if (!_surpressTextUpdate) + UpdateTextFromSelectedValue(); + } + + protected override void Update(object item, bool remove) + { + _surpressTextUpdate = true; + base.Update(item, remove); + UpdateDisplayText(item, remove); + _surpressTextUpdate = false; + } + + #endregion //Base Class Overrides + + #region Methods + + private void UpdateDisplayText(object item, bool remove) + { + if (Text == null) + Text = String.Empty; + + var displayText = GetItemDisplayValue(item); + var resolvedDisplayText = GetDelimitedValue(displayText); + string updatedText = Text; + + if (remove) + { + if (Text.Contains(resolvedDisplayText)) + updatedText = Text.Replace(resolvedDisplayText, ""); + } + else + { + if (!Text.Contains(resolvedDisplayText)) + updatedText = Text + resolvedDisplayText; + } + + UpdateText(updatedText); + } + + private void UpdateText(string text) + { + if (!Text.Equals(text)) + Text = text; + } + + private void UpdateTextFromSelectedValue() + { + if (!String.IsNullOrEmpty(SelectedValue)) + { + string[] values = SelectedValue.Split(new string[] { Delimiter }, StringSplitOptions.RemoveEmptyEntries); + foreach (string value in values) + { + var item = ResolveItemByValue(value); + UpdateDisplayText(item, false); + } + } + } + + protected object GetItemDisplayValue(object item) + { + if (!String.IsNullOrEmpty(DisplayMemberPath)) + { + var property = item.GetType().GetProperty(DisplayMemberPath); + if (property != null) + return property.GetValue(item, null); + } + + return item; + } + + #endregion //Methods + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckComboBox/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckComboBox/Themes/Generic.xaml new file mode 100644 index 00000000..af3edc79 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckComboBox/Themes/Generic.xaml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + M 0,1 C0,1 0,0 0,0 0,0 3,0 3,0 3,0 3,1 3,1 3,1 4,1 4,1 4,1 4,0 4,0 4,0 7,0 7,0 7,0 7,1 7,1 7,1 6,1 6,1 6,1 6,2 6,2 6,2 5,2 5,2 5,2 5,3 5,3 5,3 4,3 4,3 4,3 4,4 4,4 4,4 3,4 3,4 3,4 3,3 3,3 3,3 2,3 2,3 2,3 2,2 2,2 2,2 1,2 1,2 1,2 1,1 1,1 1,1 0,1 0,1 z + + + + + + \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Selector.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Selector.cs new file mode 100644 index 00000000..ff800dcb --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Selector.cs @@ -0,0 +1,374 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Controls; +using System.Windows; +using System.Windows.Data; +using System.Collections; +using System.Collections.ObjectModel; + +namespace Microsoft.Windows.Controls.Primitives +{ + public class Selector : ItemsControl + { + #region Members + + private bool _surpressSelectionChanged; + private bool _surpressSelectedValueChanged; + + #endregion //Members + + #region Constructors + + public Selector() + { + SelectedItems = new ObservableCollection(); + AddHandler(Selector.SelectedEvent, new RoutedEventHandler(Selector_ItemSelected)); + AddHandler(Selector.UnSelectedEvent, new RoutedEventHandler(Selector_ItemUnSelected)); + } + + #endregion //Constructors + + #region Properties + + public static readonly DependencyProperty DelimiterProperty = DependencyProperty.Register("Delimiter", typeof(string), typeof(Selector), new UIPropertyMetadata(",")); + public string Delimiter + { + get { return (string)GetValue(DelimiterProperty); } + set { SetValue(DelimiterProperty, value); } + } + + #region SelectedItem + + public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(Selector), new UIPropertyMetadata(null, OnSelectedItemChanged)); + public object SelectedItem + { + get { return (object)GetValue(SelectedItemProperty); } + set { SetValue(SelectedItemProperty, value); } + } + + private static void OnSelectedItemChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + Selector selector = o as Selector; + if (selector != null) + selector.OnSelectedItemChanged((object)e.OldValue, (object)e.NewValue); + } + + protected virtual void OnSelectedItemChanged(object oldValue, object newValue) + { + // TODO: Add your property changed side-effects. Descendants can override as well. + } + + #endregion //SelectedItem + + #region SelectedItems + + public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register("SelectedItems", typeof(IList), typeof(Selector), new UIPropertyMetadata(null, OnSelectedItemsChanged)); + public IList SelectedItems + { + get { return (IList)GetValue(SelectedItemsProperty); } + set { SetValue(SelectedItemsProperty, value); } + } + + private static void OnSelectedItemsChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + Selector selector = o as Selector; + if (selector != null) + selector.OnSelectedItemsChanged((IList)e.OldValue, (IList)e.NewValue); + } + + protected virtual void OnSelectedItemsChanged(IList oldValue, IList newValue) + { + + } + + #endregion SelectedItems + + public static readonly DependencyProperty SelectedMemberPathProperty = DependencyProperty.Register("SelectedMemberPath", typeof(string), typeof(Selector), new UIPropertyMetadata(null)); + public string SelectedMemberPath + { + get { return (string)GetValue(SelectedMemberPathProperty); } + set { SetValue(SelectedMemberPathProperty, value); } + } + + #region SelectedValue + + public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register("SelectedValue", typeof(string), typeof(Selector), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedValueChanged)); + public string SelectedValue + { + get { return (string)GetValue(SelectedValueProperty); } + set { SetValue(SelectedValueProperty, value); } + } + + private static void OnSelectedValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + Selector selector = o as Selector; + if (selector != null) + selector.OnSelectedValueChanged((string)e.OldValue, (string)e.NewValue); + } + + protected virtual void OnSelectedValueChanged(string oldValue, string newValue) + { + //if (_surpressSelectedValueChanged) + // return; + + //if (ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated) + // UpdateSelectedItemsFromSelectedValue(); + } + + #endregion //SelectedValue + + public static readonly DependencyProperty SelectedValuePathProperty = DependencyProperty.Register("SelectedValuePath", typeof(string), typeof(Selector), new UIPropertyMetadata(null)); + public string SelectedValuePath + { + get { return (string)GetValue(SelectedValuePathProperty); } + set { SetValue(SelectedValuePathProperty, value); } + } + + #endregion //Properties + + #region Base Class Overrides + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + //if item containers are generated + //UpdateSelectedItemsFromDelimiterValue(); + } + + protected override bool IsItemItsOwnContainerOverride(object item) + { + return item is SelectorItem; + } + + protected override DependencyObject GetContainerForItemOverride() + { + return new SelectorItem(); + } + + protected override void PrepareContainerForItemOverride(DependencyObject element, object item) + { + _surpressSelectionChanged = true; + var selectorItem = element as FrameworkElement; + + //first try resolving SelectorItem.IsSelected by data binding to the SelectedMemeberPath property + if (!String.IsNullOrEmpty(SelectedMemberPath)) + { + Binding selectedBinding = new Binding(SelectedMemberPath); + selectedBinding.Mode = BindingMode.TwoWay; + selectedBinding.Source = item; + selectorItem.SetBinding(SelectorItem.IsSelectedProperty, selectedBinding); + } + else + { + //if the SelectedMemberPath property is not set, then default to the value of the item + var value = item; + + //now let's check if we can find a value on the item using the SelectedValuePath property + if (!String.IsNullOrEmpty(SelectedValuePath)) + { + var property = item.GetType().GetProperty(SelectedValuePath); + if (property != null) + { + value = property.GetValue(item, null); + } + } + + //now check to see if the SelectedValue string contains our value. If it does then set Selector.IsSelected to true + if (!String.IsNullOrEmpty(SelectedValue) && SelectedValue.Contains(GetDelimitedValue(value))) + selectorItem.SetValue(SelectorItem.IsSelectedProperty, true); + } + + base.PrepareContainerForItemOverride(element, item); + _surpressSelectionChanged = false; + } + + #endregion //Base Class Overrides + + #region Events + + public static readonly RoutedEvent SelectedEvent = EventManager.RegisterRoutedEvent("SelectedEvent", RoutingStrategy.Bubble, typeof(SelectionChangedEventHandler), typeof(Selector)); + public static readonly RoutedEvent UnSelectedEvent = EventManager.RegisterRoutedEvent("UnSelectedEvent", RoutingStrategy.Bubble, typeof(SelectionChangedEventHandler), typeof(Selector)); + + public static readonly RoutedEvent SelectionChangedEvent = EventManager.RegisterRoutedEvent("SelectionChanged", RoutingStrategy.Bubble, typeof(SelectionChangedEventHandler), typeof(Selector)); + public event SelectionChangedEventHandler SelectionChanged + { + add { AddHandler(SelectionChangedEvent, value); } + remove { RemoveHandler(SelectionChangedEvent, value); } + } + + #endregion //Events + + #region Event Handlers + + protected virtual void Selector_ItemSelected(object sender, RoutedEventArgs e) + { + OnItemSelected(e.OriginalSource, false); + } + + protected virtual void Selector_ItemUnSelected(object sender, RoutedEventArgs e) + { + OnItemSelected(e.OriginalSource, true); + } + + #endregion //Event Handlers + + #region Methods + + protected object GetItemValue(object item) + { + if (!String.IsNullOrEmpty(SelectedValuePath)) + { + var property = item.GetType().GetProperty(SelectedValuePath); + if (property != null) + return property.GetValue(item, null); + } + + return item; + } + + protected static object GetDataContextItem(object item) + { + var element = item as FrameworkElement; + + if (element != null) + return element.DataContext; + else + return null; + } + + protected string GetDelimitedValue(object value) + { + return String.Format("{0}{1}", value, Delimiter); + } + + protected virtual void OnItemSelected(object source, bool remove) + { + var item = GetDataContextItem(source); + Update(item, remove); + + if (remove) + OnSelectionChanged(new List() { item }, new List()); + else + OnSelectionChanged(new List(), new List() { item }); + } + + private void OnSelectionChanged(IList removedItems, IList addedItems) + { + if (_surpressSelectionChanged) + return; + + RaiseEvent(new SelectionChangedEventArgs(Selector.SelectionChangedEvent, removedItems, addedItems)); + } + + protected virtual void Update(object item, bool remove) + { + UpdateSelectedItem(item); + UpdateSelectedItems(item, remove); + UpdateSelectedValue(item, remove); + } + + private void UpdateSelectedItem(object item) + { + if (_surpressSelectionChanged) + return; + + SelectedItem = item; + } + + private void UpdateSelectedItems(object item, bool remove) + { + if (remove) + { + if (SelectedItems.Contains(item)) + SelectedItems.Remove(item); + } + else + { + if (!SelectedItems.Contains(item)) + SelectedItems.Add(item); + } + } + + private void UpdateSelectedValue(object item, bool remove) + { + if (SelectedValue == null) + SelectedValue = String.Empty; + + var value = GetItemValue(item); + var resolvedValue = GetDelimitedValue(value); + string updateValue = SelectedValue; + + if (remove) + { + if (SelectedValue.Contains(resolvedValue)) + updateValue = SelectedValue.Replace(resolvedValue, ""); + } + else + { + if (!SelectedValue.Contains(resolvedValue)) + updateValue = SelectedValue + resolvedValue; + } + + UpdateSelectedValue(updateValue); + } + + private void UpdateSelectedValue(string value) + { + _surpressSelectedValueChanged = true; + + if (!SelectedValue.Equals(value)) + SelectedValue = value; + + _surpressSelectedValueChanged = false; + } + + //private void UpdateSelectedItemsFromSelectedValue() + //{ + // //if we have a SelectedMemberPath we will rely on Databinding to select items + // if (!String.IsNullOrEmpty(SelectedMemberPath)) + // return; + + // if (!String.IsNullOrEmpty(SelectedValue)) + // { + // string[] values = SelectedValue.Split(new string[] { Delimiter }, StringSplitOptions.RemoveEmptyEntries); + // foreach (string value in values) + // { + // var item = ResolveItemByValue(value); + // var selectorItem = ItemContainerGenerator.ContainerFromItem(item) as SelectorItem; + // if (selectorItem != null) + // { + // if (!selectorItem.IsSelected) + // selectorItem.IsSelected = true; + // } + // } + // } + //} + + protected object ResolveItemByValue(string value) + { + if (!String.IsNullOrEmpty(SelectedValuePath)) + { + if (ItemsSource != null) + { + foreach (object item in ItemsSource) + { + var property = item.GetType().GetProperty(SelectedValuePath); + if (property != null) + { + var propertyValue = property.GetValue(item, null); + if (value.Equals(propertyValue.ToString(), StringComparison.InvariantCultureIgnoreCase)) + return item; + } + } + } + } + + return value; + } + + #endregion //Methods + } +} \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SelectorItem.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SelectorItem.cs new file mode 100644 index 00000000..9f9151be --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SelectorItem.cs @@ -0,0 +1,79 @@ +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; + +namespace Microsoft.Windows.Controls.Primitives +{ + public class SelectorItem : ContentControl + { + #region Constructors + + static SelectorItem() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(SelectorItem), new FrameworkPropertyMetadata(typeof(SelectorItem))); + } + + public SelectorItem() + { + AddHandler(Mouse.MouseDownEvent, new MouseButtonEventHandler(OnMouseDown)); + } + + #endregion //Constructors + + #region Properties + + public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(SelectorItem), new UIPropertyMetadata(false, OnIsSelectedChanged)); + public bool IsSelected + { + get { return (bool)GetValue(IsSelectedProperty); } + set { SetValue(IsSelectedProperty, value); } + } + + private static void OnIsSelectedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + SelectorItem selectorItem = o as SelectorItem; + if (selectorItem != null) + selectorItem.OnIsSelectedChanged((bool)e.OldValue, (bool)e.NewValue); + } + + protected virtual void OnIsSelectedChanged(bool oldValue, bool newValue) + { + if (newValue) + RaiseSelectionChangedEvent(new RoutedEventArgs(Selector.SelectedEvent, this)); + else + RaiseSelectionChangedEvent(new RoutedEventArgs(Selector.UnSelectedEvent, this)); + } + + internal Selector ParentSelector + { + get { return ItemsControl.ItemsControlFromItemContainer(this) as Selector; } + } + + #endregion //Properties + + #region Events + + public static readonly RoutedEvent SelectedEvent = Selector.SelectedEvent.AddOwner(typeof(SelectorItem)); + public static readonly RoutedEvent UnselectedEvent = Selector.UnSelectedEvent.AddOwner(typeof(SelectorItem)); + + #endregion + + #region Event Hanlders + + void OnMouseDown(object sender, MouseButtonEventArgs e) + { + IsSelected = !IsSelected; + } + + #endregion //Event Hanlders + + #region Methods + + private void RaiseSelectionChangedEvent(RoutedEventArgs e) + { + base.RaiseEvent(e); + } + + #endregion //Methods + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/ComboBoxEditor.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/ComboBoxEditor.cs index a0d995ad..12632cca 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/ComboBoxEditor.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/ComboBoxEditor.cs @@ -3,11 +3,11 @@ using System.Windows.Controls; namespace Microsoft.Windows.Controls.PropertyGrid.Editors { - public abstract class ComboBoxEditor : TypeEditor + public abstract class ComboBoxEditor : TypeEditor { protected override void SetValueDependencyProperty() { - ValueProperty = ComboBox.SelectedItemProperty; + ValueProperty = System.Windows.Controls.ComboBox.SelectedItemProperty; } protected override void ResolveValueBinding(PropertyItem propertyItem) diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Common/Generic_Common.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Common/Generic_Common.xaml index e1ef5440..cb7d3894 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Common/Generic_Common.xaml +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Common/Generic_Common.xaml @@ -2,6 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:local="clr-namespace:Microsoft.Windows.Controls" + xmlns:primitives="clr-namespace:Microsoft.Windows.Controls.Primitives" xmlns:coreConverters="clr-namespace:Microsoft.Windows.Controls.Core.Converters" xmlns:magConverters="clr-namespace:Microsoft.Windows.Controls.Mag.Converters" xmlns:chrome="clr-namespace:Microsoft.Windows.Controls.Chromes"> @@ -96,4 +97,39 @@ + + + + + + + \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml index 3bb76652..0e62e9fe 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml @@ -1,16 +1,18 @@ + + - - + + diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj index 427355de..3acb4d06 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj @@ -99,6 +99,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -190,6 +194,7 @@ + @@ -198,6 +203,8 @@ + + @@ -387,6 +394,7 @@ +