CustomMultipleDropDownBox
cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Collections; using System.Windows.Data; using System.Reflection; using System.Collections.ObjectModel; using System.Windows.Controls.Primitives; using System.ComponentModel; namespace GEMS.Windows.Controls.CustomControls { public class CustomMultipleDropDownBox : ComboBox { #region Property protected ListBox MyListBox { get { return base.GetTemplateChild("MyListBox") as ListBox; } } protected ListBox MySelectedListBox { get { return base.GetTemplateChild("MySelectedListBox") as ListBox; } } public IList SelectedItems { get { return (IList)GetValue(SelectedItemsProperty); } set { SetValue(SelectedItemsProperty, value); } } // Using a DependencyProperty as the backing store for SelectedItems1. This enables animation, styling, binding, etc... public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register("SelectedItems", typeof(IList), typeof(CustomMultipleDropDownBox), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectedItemsChanged))); public ListSortDirection Sort { get { return (ListSortDirection)GetValue(SortProperty); } set { SetValue(SortProperty, value); } } // Using a DependencyProperty as the backing store for Sort. This enables animation, styling, binding, etc... public static readonly DependencyProperty SortProperty = DependencyProperty.Register("Sort", typeof(ListSortDirection), typeof(CustomMultipleDropDownBox), new PropertyMetadata(ListSortDirection.Ascending)); public string SortMemberPath { get { return (string)GetValue(SortMemberPathProperty); } set { SetValue(SortMemberPathProperty, value); } } // Using a DependencyProperty as the backing store for SortMemberPath. This enables animation, styling, binding, etc... public static readonly DependencyProperty SortMemberPathProperty = DependencyProperty.Register("SortMemberPath", typeof(string), typeof(CustomMultipleDropDownBox), new PropertyMetadata(null)); #endregion #region construtor static CustomMultipleDropDownBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomMultipleDropDownBox), new FrameworkPropertyMetadata(typeof(CustomMultipleDropDownBox))); } public CustomMultipleDropDownBox() { this.Loaded += CustomMultipleDropDownBox_Loaded; // this.SelectedItems.CollectionChanged += SelectedItems_CollectionChanged; } void SelectedItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { } void CustomMultipleDropDownBox_Loaded(object sender, RoutedEventArgs e) { //if (this.SelectedItems == null) //{ // Type type = this.SelectedItems.GetType(); // ConstructorInfo constructor = type.GetConstructor(new Type[0]); // //使用构造器对象来创建对象 // object obj = constructor.Invoke(new Object[0]); // // this.SelectedItems = constructor.Invoke(new Object[0]); //} } public override void OnApplyTemplate() { base.OnApplyTemplate(); //load the text box control if (this.MyListBox != null) { //this.MyListBox.SelectionChanged += MyListBox_SelectionChanged; //DataTemplate dt1 = new DataTemplate(); //FrameworkElementFactory fef1 = new FrameworkElementFactory(typeof(CheckBox)); //Binding binding1 = new Binding(); //binding1.Path = new PropertyPath("Tag"); //binding1.Mode = BindingMode.TwoWay; //binding1.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; //binding1.RelativeSource = RelativeSource.Self; //Binding binding2 = new Binding(); //binding2.Path = new PropertyPath(this.DisplayMemberPath); //binding2.Mode = BindingMode.TwoWay; //binding2.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; //fef1.SetBinding(CheckBox.IsCheckedProperty, binding1); //fef1.SetBinding(CheckBox.ContentProperty, binding2); //fef1.SetValue(CheckBox.WidthProperty, this.Width); //fef1.SetValue(CheckBox.TagProperty, false); ////fef1.SetValue(CheckBox.NameProperty, "cBoxSelected"); //fef1.AddHandler(CheckBox.UncheckedEvent, (RoutedEventHandler)cBoxSelected_Unchecked, true); //fef1.AddHandler(CheckBox.CheckedEvent, (RoutedEventHandler)cBoxSelected_Checked, true); //dt1.VisualTree = fef1; //this.MyListBox.ItemTemplate = dt1; } if (this.MySelectedListBox != null) { this.MySelectedListBox.Items.SortDescriptions.Add(new SortDescription(string.IsNullOrWhiteSpace(this.SortMemberPath) ? this.DisplayMemberPath : this.SortMemberPath, this.Sort)); } } protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue) { this.Items.SortDescriptions.Add(new SortDescription(string.IsNullOrWhiteSpace(this.SortMemberPath) ? this.DisplayMemberPath : this.SortMemberPath, this.Sort)); base.OnItemsSourceChanged(oldValue, newValue); if (newValue!=null) { foreach (var item in this.Items) { // string DisplayName = item.GetType().GetProperty(this.DisplayName).GetValue(item, null).ToString(); Binding binding = new Binding(this.DisplayMemberPath) { Source = item }; Binding binding1 = new Binding(); binding1.Path = new PropertyPath("Tag"); binding1.Mode = BindingMode.TwoWay; binding1.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; binding1.RelativeSource = RelativeSource.Self; CheckBox cb = new CheckBox(); cb.Width = this.Width; if (this.SelectedItems!=null&&this.SelectedItems.Contains(item)) { cb.Tag = true; } else { cb.Tag = false; } cb.SetBinding(CheckBox.ContentProperty, binding); cb.SetBinding(CheckBox.IsCheckedProperty, binding1); cb.DataContext = item; //cb.Content = DisplayName; cb.Checked += cBoxSelected_Checked; cb.Unchecked += cBoxSelected_Unchecked; this.MyListBox.Items.Add(cb); } } //this.SelectedItems = Activator.CreateInstance(newValue.GetType()); //Type type = this.SelectedItems.GetType(); //ConstructorInfo constructor = type.GetConstructor(new Type[0]); ////使用构造器对象来创建对象 //object obj = constructor.Invoke(new Object[0]); //this.SelectedItems = constructor.Invoke(new Object[0]); } private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { //CustomMultipleDropDownBox cmd = d as CustomMultipleDropDownBox; //cmd.SelectedDisplayNames = new List<DisplayName>(); //foreach (var item in cmd.SelectedItems) //{ // cmd.SelectedDisplayNames.Add(new DisplayName() { Name = item.GetType().GetProperty(cmd.DisplayMemberPath).GetValue(item, null).ToString() }); //} ////if (e.NewValue!=null&&cmd.ItemsSource!=null) ////{ ////} //cmd.SelectedDisplayNames = cmd.SelectedDisplayNames.OrderBy(p=>p.Name).ToList(); } #endregion #region Event void MyListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { // this.MySelectedListBox.ItemsSource = this.MyListBox.SelectedItems; } private void cBoxSelected_Unchecked(object sender, RoutedEventArgs e) { if (this.SelectedItems == null) { this.SelectedItems = new ObservableCollection<object>(); } CheckBox cb = sender as CheckBox; //cb.Tag = false; this.SelectedItems.Remove(cb.DataContext); } private void cBoxSelected_Checked(object sender, RoutedEventArgs e) { if (this.SelectedItems == null) { this.SelectedItems = new ObservableCollection<object>(); } CheckBox cb = sender as CheckBox; //cb.Tag = true; this.SelectedItems.Add(cb.DataContext); } #endregion } }
style
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:GEMS.Windows.Controls.CustomControls" xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" > <Style TargetType="{x:Type local:CustomMultipleDropDownBox}"> <!--<Setter Property="FocusVisualStyle"> <Setter.Value> <Style> <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> </Setter.Value> </Setter>--> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/> <Setter Property="Background"> <Setter.Value> <LinearGradientBrush EndPoint="0,1" StartPoint="0,0"> <GradientStop Color="#FFF3F3F3" Offset="0"/> <GradientStop Color="#FFEBEBEB" Offset="0.5"/> <GradientStop Color="#FFDDDDDD" Offset="0.5"/> <GradientStop Color="#FFCDCDCD" Offset="1"/> </LinearGradientBrush> </Setter.Value> </Setter> <Setter Property="BorderBrush" Value="#FF707070"/> <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:CustomMultipleDropDownBox}"> <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"> <Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" 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" > <StackPanel Orientation="Vertical"> <ListBox x:Name="MyListBox" SelectionMode="Multiple" Height="125" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.DirectionalNavigation="Contained" > <!--<ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <ListBoxItem IsSelected="{Binding IsSelected,Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True, ValidatesOnDataErrors=True, UpdateSourceTrigger =PropertyChanged}"> <CheckBox FontFamily="Arial" Width="{Binding ActualWidth,ElementName=MultiSelectComboBox}" Content="{Binding DisplayMemberPath,RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" IsChecked="{Binding IsSelected,Mode=TwoWay, RelativeSource={RelativeSource AncestorType= ListBoxItem}}" > </CheckBox> </ListBoxItem> </StackPanel> </DataTemplate> </ListBox.ItemTemplate>--> </ListBox> <ListBox FontFamily="Arial" Height="125" x:Name="MySelectedListBox" SelectionMode="Single" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.DirectionalNavigation="Contained" DisplayMemberPath="{TemplateBinding DisplayMemberPath}" ItemsSource="{TemplateBinding SelectedItems}" > </ListBox> </StackPanel> </ScrollViewer> </Border> </Themes:SystemDropShadowChrome> </Popup> <ToggleButton BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"> <ToggleButton.Style> <Style 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="Background" Value="Transparent"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" SnapsToDevicePixels="True"> <Grid HorizontalAlignment="Right" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"> <Path x:Name="Arrow" Data="M0,0L3.5,4 7,0z" Fill="Black" HorizontalAlignment="Center" Margin="3,1,0,0" VerticalAlignment="Center"/> </Grid> </Themes: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="#FFAFAFAF"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ToggleButton.Style> </ToggleButton> <ContentPresenter ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="False" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="True"> <Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/> <Setter Property="Color" TargetName="Shdw" Value="#71000000"/> </Trigger> <Trigger Property="HasItems" Value="False"> <Setter Property="Height" TargetName="DropDownBorder" Value="95"/> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> <Setter Property="Background" Value="#FFF4F4F4"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsGrouping" Value="True"/> <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="False"/> </MultiTrigger.Conditions> <Setter Property="ScrollViewer.CanContentScroll" Value="False"/> </MultiTrigger> <!--<Trigger Property="CanContentScroll" SourceName="DropDownScrollViewer" Value="False"> <Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/> <Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/> </Trigger>--> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <!--<Trigger Property="IsEditable" Value="True"> <Setter Property="BorderBrush"> <Setter.Value> <LinearGradientBrush EndPoint="0,20" MappingMode="Absolute" StartPoint="0,0"> <GradientStop Color="#FFABADB3" Offset="0.05"/> <GradientStop Color="#FFE2E3EA" Offset="0.07"/> <GradientStop Color="#FFE3E9EF" Offset="1"/> </LinearGradientBrush> </Setter.Value> </Setter> <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/> <Setter Property="IsTabStop" Value="False"/> <Setter Property="Padding" Value="3"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:CustomMultipleDropDownBox}"> <Grid x:Name="Placement" SnapsToDevicePixels="True"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Popup x:Name="PART_Popup" AllowsTransparency="True" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom"> <Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=Placement}"> <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> </Themes:SystemDropShadowChrome> </Popup> <Themes:ListBoxChrome x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}"/> <TextBox x:Name="PART_EditableTextBox" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}" Margin="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"> <TextBox.Style> <Style TargetType="{x:Type TextBox}"> <Setter Property="OverridesDefaultStyle" Value="True"/> <Setter Property="AllowDrop" Value="True"/> <Setter Property="MinWidth" Value="0"/> <Setter Property="MinHeight" Value="0"/> <Setter Property="FocusVisualStyle" Value="{x:Null}"/> <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/> <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TextBox}"> <ScrollViewer x:Name="PART_ContentHost" Background="Transparent" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/> </ControlTemplate> </Setter.Value> </Setter> </Style> </TextBox.Style> </TextBox> <ToggleButton Grid.Column="1" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"> <ToggleButton.Style> <Style 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="Background" Value="Transparent"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RoundCorners="False" SnapsToDevicePixels="True" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"> <Path x:Name="Arrow" Data="M0,0L3.5,4 7,0z" Fill="Black" HorizontalAlignment="Center" Margin="0,1,0,0" VerticalAlignment="Center"/> </Themes: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="#FFAFAFAF"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ToggleButton.Style> </ToggleButton> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsKeyboardFocusWithin" Value="True"> <Setter Property="Foreground" Value="Black"/> </Trigger> <Trigger Property="IsDropDownOpen" Value="True"> <Setter Property="RenderFocused" TargetName="Border" Value="True"/> </Trigger> <Trigger Property="HasItems" Value="False"> <Setter Property="Height" TargetName="DropDownBorder" Value="95"/> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> <Setter Property="Background" Value="#FFF4F4F4"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsGrouping" Value="True"/> <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="False"/> </MultiTrigger.Conditions> <Setter Property="ScrollViewer.CanContentScroll" Value="False"/> </MultiTrigger> <Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="True"> <Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/> <Setter Property="Color" TargetName="Shdw" Value="#71000000"/> </Trigger> <Trigger Property="CanContentScroll" SourceName="DropDownScrollViewer" Value="False"> <Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/> <Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Trigger>--> </Style.Triggers> </Style> </ResourceDictionary>