From 7c10f04894cd7469ad0a8a0c5ce43f48c07efd2c Mon Sep 17 00:00:00 2001 From: brianlagunas_cp Date: Mon, 17 Oct 2011 18:32:14 +0000 Subject: [PATCH] made some slight changes to the CheckListBox/CheckComboBox. IMPORTANT: There is a SelectedItems property for both controls, but it is intended to be ReadOnly. You cannot data bind to ReadOnly DependencyProperties, so in order to enable the scenario of data binding to the SelectedItems from a ViewModel, I had to leave it as a public get/set property. For this binding to work correctly, you MUST set the binding Mode=OneWayToSource for the SelectedItems property. --- .../Implementation/CheckComboBox.cs | 55 +------- .../Core/Primitives/Selector.cs | 127 ++++++++---------- 2 files changed, 60 insertions(+), 122 deletions(-) diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckComboBox/Implementation/CheckComboBox.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckComboBox/Implementation/CheckComboBox.cs index 598043b4..4e574cb2 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckComboBox/Implementation/CheckComboBox.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckComboBox/Implementation/CheckComboBox.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Windows; using Microsoft.Windows.Controls.Primitives; @@ -56,66 +57,22 @@ namespace Microsoft.Windows.Controls #region Base Class Overrides - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - } - protected override void OnSelectedValueChanged(string oldValue, string newValue) { base.OnSelectedValueChanged(oldValue, newValue); - UpdateTextFromSelectedValue(); + UpdateText(); } #endregion //Base Class Overrides #region Methods - private void UpdateDisplayText(object item, bool remove) + private void UpdateText() { - 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; - } + string newValue = String.Join(Delimiter, SelectedItems.Cast().Select(x => GetItemDisplayValue(x))); - UpdateText(updatedText); - } - - private void UpdateText(string text) - { - if (String.IsNullOrEmpty(Text)) - Text = string.Empty; - - if (!Text.Equals(text)) - Text = text; - } - - private void UpdateTextFromSelectedValue() - { - UpdateText(String.Empty); - - 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); - } - } + if (String.IsNullOrEmpty(Text) || !Text.Equals(newValue)) + Text = newValue; } protected object GetItemDisplayValue(object item) diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Selector.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Selector.cs index 7502606e..1cb47170 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Selector.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Selector.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.ObjectModel; using System.ComponentModel; +using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Data; @@ -24,10 +25,19 @@ namespace Microsoft.Windows.Controls.Primitives public Selector() { SelectedItems = new ObservableCollection(); + //ItemContainerGenerator.StatusChanged += new EventHandler(ItemContainerGenerator_StatusChanged); AddHandler(Selector.SelectedEvent, new RoutedEventHandler(Selector_ItemSelected)); AddHandler(Selector.UnSelectedEvent, new RoutedEventHandler(Selector_ItemUnselected)); } + //void ItemContainerGenerator_StatusChanged(object sender, EventArgs e) + //{ + // if (ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated) + // { + // UpdateSelectedItemsFromSelectedValue(); + // } + //} + #endregion //Constructors #region Properties @@ -54,7 +64,8 @@ namespace Microsoft.Windows.Controls.Primitives set { SetValue(SelectedItemProperty, value); } } - //Make Read Only + //Since you cannot data bind to ReadOnly DependencyProperty, I am leaving this a public get/set DP. This will allow you to data bind to the SelectedItems from a ViewModel, but it is + //intended to be ReadOnly. So you MUST set the binding Mode=OneWayToSource. Otherwise it will not behave as expected. public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register("SelectedItems", typeof(IList), typeof(Selector), new UIPropertyMetadata(null)); public IList SelectedItems { @@ -90,9 +101,7 @@ namespace Microsoft.Windows.Controls.Primitives if (_surpressSelectedValueChanged) return; - //if we are controling the selections from the SelectedValue we can only update the IsSelected property of the items if the containers have been generated - if (ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated) - UpdateSelectedItemsFromSelectedValue(); + UpdateSelectedItemsFromSelectedValue(); } #endregion //SelectedValue @@ -121,53 +130,31 @@ namespace Microsoft.Windows.Controls.Primitives protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { _surpressSelectionChanged = true; - bool isSelected = false; 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) - { - Mode = BindingMode.TwoWay, - Source = item + Binding selectedBinding = new Binding(SelectedMemberPath) + { + Mode = BindingMode.TwoWay, + Source = item }; selectorItem.SetBinding(SelectorItem.IsSelectedProperty, selectedBinding); } - else - { - var value = item; - - //let's check if we can find a value on the item using the SelectedValuePath property - if (!String.IsNullOrEmpty(ValueMemberPath)) - { - var property = item.GetType().GetProperty(ValueMemberPath); - 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))) - { - isSelected = true; - } - else if (SelectedItems != null) + //now let's search the SelectedItems for the current item. If it's there then mark it as selected + if (SelectedItems != null) + { + foreach (object selectedItem in SelectedItems) { - //if we get here we could find the value in the SelectedValue property, so lets search the SelectedItems for a match - foreach (object selectedItem in SelectedItems) + //a match was found so select it and get the hell out of here + if (item.Equals(selectedItem)) { - //a match was found so select it and get the hell out of here - if (value.Equals(GetItemValue(selectedItem))) - { - isSelected = true; - break; - } + selectorItem.SetValue(SelectorItem.IsSelectedProperty, true); + break; } } - - selectorItem.SetValue(SelectorItem.IsSelectedProperty, isSelected); } base.PrepareContainerForItemOverride(element, item); @@ -255,7 +242,7 @@ namespace Microsoft.Windows.Controls.Primitives { UpdateSelectedItem(item); UpdateSelectedItems(item, remove); - UpdateSelectedValue(item, remove); + UpdateSelectedValue(); } private void UpdateSelectedItem(object item) @@ -277,33 +264,7 @@ namespace Microsoft.Windows.Controls.Primitives } } - private void UpdateSelectedValue(object item, bool remove) - { - //make sure we have a selected value, or we will get an exception - if (SelectedValue == null) - UpdateSelectedValue(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; - } - - //if the SelectedValue is the same as the updated value then just ignore it - if (!SelectedValue.Equals(updateValue)) - UpdateSelectedValue(updateValue); - } - - private void UpdateSelectedValue(string value) + private void UpdateSelectedValue() { //get out of here if we don't want to set the SelectedValue if (_ignoreSetSelectedValue) @@ -311,7 +272,10 @@ namespace Microsoft.Windows.Controls.Primitives _surpressSelectedValueChanged = true; - SelectedValue = value; + string newValue = String.Join(Delimiter, SelectedItems.Cast().Select(x => GetItemValue(x))); + + if (String.IsNullOrEmpty(SelectedValue) || !SelectedValue.Equals(newValue)) + SelectedValue = newValue; _surpressSelectedValueChanged = false; } @@ -321,7 +285,7 @@ namespace Microsoft.Windows.Controls.Primitives _surpressSelectionChanged = true; //first we have to unselect everything - UnselectAll(); + ClearSelectedItems(); if (!String.IsNullOrEmpty(SelectedValue)) { @@ -329,11 +293,18 @@ namespace Microsoft.Windows.Controls.Primitives foreach (string value in values) { var item = ResolveItemByValue(value); - var selectorItem = ItemContainerGenerator.ContainerFromItem(item) as SelectorItem; - if (selectorItem != null) + + if (item != null) { - if (!selectorItem.IsSelected) - selectorItem.IsSelected = true; + SelectedItems.Add(item); + + //now try to select it in the list + var selectorItem = ItemContainerGenerator.ContainerFromItem(item) as SelectorItem; + if (selectorItem != null) + { + if (!selectorItem.IsSelected) + selectorItem.IsSelected = true; + } } } } @@ -341,7 +312,17 @@ namespace Microsoft.Windows.Controls.Primitives _surpressSelectionChanged = false; } - private void UnselectAll() + private void ClearSelectedItems() + { + if (SelectedItems != null) + SelectedItems.Clear(); + else + SelectedItems = new ObservableCollection(); + + UnselectAllInternal(); + } + + private void UnselectAllInternal() { _ignoreSetSelectedValue = true;