8 changed files with 742 additions and 4 deletions
@ -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
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,102 @@ |
|||||
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
|
xmlns:local="clr-namespace:Microsoft.Windows.Controls" |
||||
|
xmlns:chrome="clr-namespace:Microsoft.Windows.Controls.Chromes" |
||||
|
xmlns:primitives="clr-namespace:Microsoft.Windows.Controls.Primitives" > |
||||
|
|
||||
|
<Style x:Key="ComboBoxFocusVisual"> |
||||
|
<Setter Property="Control.Template"> |
||||
|
<Setter.Value> |
||||
|
<ControlTemplate> |
||||
|
<Rectangle Margin="4,4,21,4" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/> |
||||
|
</ControlTemplate> |
||||
|
</Setter.Value> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0"> |
||||
|
<GradientStop Color="#F3F3F3" Offset="0"/> |
||||
|
<GradientStop Color="#EBEBEB" Offset="0.5"/> |
||||
|
<GradientStop Color="#DDDDDD" Offset="0.5"/> |
||||
|
<GradientStop Color="#CDCDCD" Offset="1"/> |
||||
|
</LinearGradientBrush> |
||||
|
|
||||
|
<SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/> |
||||
|
|
||||
|
<Geometry x:Key="DownArrowGeometry">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</Geometry> |
||||
|
|
||||
|
<Style x:Key="ComboBoxReadonlyToggleButton" TargetType="{x:Type ToggleButton}"> |
||||
|
<Setter Property="OverridesDefaultStyle" Value="true"/> |
||||
|
<Setter Property="IsTabStop" Value="false"/> |
||||
|
<Setter Property="Focusable" Value="false"/> |
||||
|
<Setter Property="ClickMode" Value="Press"/> |
||||
|
<Setter Property="Template"> |
||||
|
<Setter.Value> |
||||
|
<ControlTemplate TargetType="{x:Type ToggleButton}"> |
||||
|
<chrome:ButtonChrome x:Name="Chrome" |
||||
|
BorderBrush="{TemplateBinding BorderBrush}" |
||||
|
Background="{TemplateBinding Background}" |
||||
|
RenderEnabled="{TemplateBinding IsEnabled}" |
||||
|
RenderMouseOver="{Binding IsMouseOver, ElementName=PART_DropDownButton}" |
||||
|
RenderPressed="{Binding IsPressed, ElementName=PART_DropDownButton}" |
||||
|
SnapsToDevicePixels="true" > |
||||
|
<Grid HorizontalAlignment="Right" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"> |
||||
|
<Path x:Name="Arrow" Data="{StaticResource DownArrowGeometry}" Fill="Black" HorizontalAlignment="Center" Margin="3,0,3,0" VerticalAlignment="Center"/> |
||||
|
</Grid> |
||||
|
</chrome:ButtonChrome> |
||||
|
<ControlTemplate.Triggers> |
||||
|
<Trigger Property="IsChecked" Value="true"> |
||||
|
<Setter Property="RenderPressed" TargetName="Chrome" Value="true"/> |
||||
|
</Trigger> |
||||
|
<Trigger Property="IsEnabled" Value="false"> |
||||
|
<Setter Property="Fill" TargetName="Arrow" Value="#AFAFAF"/> |
||||
|
</Trigger> |
||||
|
</ControlTemplate.Triggers> |
||||
|
</ControlTemplate> |
||||
|
</Setter.Value> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="{x:Type local:CheckComboBox}"> |
||||
|
<Setter Property="FocusVisualStyle" Value="{StaticResource ComboBoxFocusVisual}"/> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/> |
||||
|
<Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/> |
||||
|
<Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/> |
||||
|
<Setter Property="BorderThickness" Value="1"/> |
||||
|
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/> |
||||
|
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/> |
||||
|
<Setter Property="Padding" Value="4,3"/> |
||||
|
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/> |
||||
|
<Setter Property="ScrollViewer.PanningMode" Value="Both"/> |
||||
|
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/> |
||||
|
<Setter Property="Template"> |
||||
|
<Setter.Value> |
||||
|
<ControlTemplate TargetType="{x:Type local:CheckComboBox}"> |
||||
|
<Grid x:Name="MainGrid" SnapsToDevicePixels="true"> |
||||
|
<Grid.ColumnDefinitions> |
||||
|
<ColumnDefinition Width="*"/> |
||||
|
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/> |
||||
|
</Grid.ColumnDefinitions> |
||||
|
<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom"> |
||||
|
<Grid MinWidth="{Binding ActualWidth, ElementName=MainGrid}"> |
||||
|
<Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"> |
||||
|
<ScrollViewer x:Name="DropDownScrollViewer"> |
||||
|
<Grid RenderOptions.ClearTypeHint="Enabled"> |
||||
|
<Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0"> |
||||
|
<Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}" Height="{Binding ActualHeight, ElementName=DropDownBorder}" Width="{Binding ActualWidth, ElementName=DropDownBorder}"/> |
||||
|
</Canvas> |
||||
|
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> |
||||
|
</Grid> |
||||
|
</ScrollViewer> |
||||
|
</Border> |
||||
|
</Grid> |
||||
|
</Popup> |
||||
|
<ToggleButton x:Name="PART_DropDownButton" Grid.ColumnSpan="2" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxReadonlyToggleButton}" /> |
||||
|
<TextBlock Text="{TemplateBinding Text}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> |
||||
|
</Grid> |
||||
|
</ControlTemplate> |
||||
|
</Setter.Value> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
</ResourceDictionary> |
||||
@ -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<object>(); |
||||
|
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<object>() { item }, new List<object>()); |
||||
|
else |
||||
|
OnSelectionChanged(new List<object>(), new List<object>() { 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
|
||||
|
} |
||||
|
} |
||||
@ -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
|
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue