有很多项目,都有数据筛选的操作。下面提供一个案例,给大家做参考。
左侧是数据源,搜索框加TreeView控件,右侧是ListBox控件。在左侧数据列点击添加数据,然后点击确定,得到所筛选的数据。
下面直接看代码吧,比较好理解~
筛选控件做成用户控件,当然也可以直接放在主界面,如果不复用的话。数据源都是固定的,实际用的话,新建个ViewModel将数据源绑定就行了。
1、筛选控件界面:
<UserControl x:Class="WpfApplication17.SelectControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:wpfApplication17="clr-namespace:WpfApplication17" mc:Ignorable="d" d:DesignHeight="400" d:DesignWidth="412" Background="LightSkyBlue"> <UserControl.Resources> <ImageBrush x:Key="ImageBrushAddBlue" ImageSource="AddGreen.png"></ImageBrush> <ImageBrush x:Key="ImageBrushAddGray" ImageSource="AddGray.png"></ImageBrush> <Style x:Key="ScrollBarPageButton" TargetType="{x:Type RepeatButton}"> <Setter Property="SnapsToDevicePixels" Value="True" /> <Setter Property="OverridesDefaultStyle" Value="true" /> <Setter Property="IsTabStop" Value="false" /> <Setter Property="Focusable" Value="false" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type RepeatButton}"> <Border Background="Transparent" /> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="ScrollBarThumb" TargetType="{x:Type Thumb}"> <Setter Property="SnapsToDevicePixels" Value="True" /> <Setter Property="OverridesDefaultStyle" Value="true" /> <Setter Property="IsTabStop" Value="false" /> <Setter Property="Focusable" Value="false" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Thumb}"> <Border CornerRadius="2" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" /> </ControlTemplate> </Setter.Value> </Setter> </Style> <ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}"> <Grid> <Border CornerRadius="2" Width="0.5" Background="#FF046BFF" /> <Track x:Name="PART_Track" IsDirectionReversed="true"> <Track.DecreaseRepeatButton> <RepeatButton Style="{StaticResource ScrollBarPageButton}" Command="ScrollBar.PageUpCommand" /> </Track.DecreaseRepeatButton> <Track.Thumb> <Thumb Style="{StaticResource ScrollBarThumb}" Margin="4,0,4,0" Background="DodgerBlue"></Thumb> </Track.Thumb> <Track.IncreaseRepeatButton> <RepeatButton Style="{StaticResource ScrollBarPageButton}" Command="ScrollBar.PageDownCommand" /> </Track.IncreaseRepeatButton> </Track> </Grid> </ControlTemplate> <ControlTemplate x:Key="ScrollViewerControlTemplate1" TargetType="{x:Type ScrollViewer}"> <Grid x:Name="Grid" Background="{TemplateBinding Background}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Rectangle x:Name="Corner" Grid.Column="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Grid.Row="1"/> <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" Margin="{TemplateBinding Padding}" Grid.Row="0"/> <ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}" Template="{StaticResource VerticalScrollBar}"/> <ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/> </Grid> </ControlTemplate> <!--对象树子模板--> <DataTemplate x:Key="TreeItemTemplate" DataType="TreeViewItem"> <Grid Margin="50,0,0,0" Height="28"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="30"></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Text="{Binding Name}" Foreground="White" FontSize="15" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0"/> <Button x:Name="BtnAdd" Grid.Column="1" Background="Transparent" VerticalAlignment="Center" HorizontalAlignment="Center" Click="BtnAdd_OnClick"> <Button.Template> <ControlTemplate TargetType="Button"> <Grid> <Rectangle x:Name="BtnRetangle" Height="20" Width="20" Stroke="Transparent" StrokeThickness="1" VerticalAlignment="Center" HorizontalAlignment="Center"> </Rectangle> <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Content="{TemplateBinding Content}"></ContentPresenter> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="BtnRetangle" Property="Height" Value="22"></Setter> <Setter TargetName="BtnRetangle" Property="Width" Value="22"></Setter> </Trigger> <DataTrigger Binding="{Binding IsChecked}" Value="true"> <Setter TargetName="BtnRetangle" Property="Fill" Value="{StaticResource ImageBrushAddGray}"></Setter> <Setter Property="ToolTip" Value="已添加"></Setter> </DataTrigger> <DataTrigger Binding="{Binding IsChecked}" Value="false"> <Setter TargetName="BtnRetangle" Property="Fill" Value="{StaticResource ImageBrushAddBlue}"></Setter> <Setter Property="ToolTip" Value="添加"></Setter> </DataTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Button.Template> </Button> </Grid> </DataTemplate> <Style TargetType="TreeViewItem"> <Setter Property="Background" Value="Transparent" /> <Setter Property="IsExpanded" Value="True"></Setter> <Setter Property="HeaderTemplate"> <Setter.Value> <HierarchicalDataTemplate ItemsSource="{Binding TreeViewItems,Mode=TwoWay}" ItemTemplate="{StaticResource TreeItemTemplate}"> <StackPanel Orientation="Horizontal" Height="28" VerticalAlignment="Center" HorizontalAlignment="Left"> <Image Source="folder.png" VerticalAlignment="Center" Height="17" Margin="10,0"/> <TextBlock Text="{Binding Name}" Margin="5,0,0,0" FontSize="15" VerticalAlignment="Center" Foreground="White"/> </StackPanel> </HierarchicalDataTemplate> </Setter.Value> </Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TreeViewItem}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="SelectionStates"> <VisualState x:Name="Selected"> <Storyboard> <ColorAnimationUsingKeyFrames Storyboard.TargetName="Bd" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" > <EasingColorKeyFrame KeyTime="0" Value="Transparent" /> </ColorAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Unselected" /> <VisualState x:Name="SelectedInactive"> <Storyboard> <ColorAnimationUsingKeyFrames Storyboard.TargetName="Bd" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"> <EasingColorKeyFrame KeyTime="0" Value="Transparent" /> </ColorAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="ExpansionStates"> <VisualState x:Name="Expanded"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ItemsHost"> <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Collapsed" /> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Border x:Name="Bd" Grid.Column="0" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"> <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/> </Border> <ItemsPresenter x:Name="ItemsHost" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Visibility="Collapsed" /> </Grid> <ControlTemplate.Triggers> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="HasHeader" Value="false" /> <Condition Property="Width" Value="Auto" /> </MultiTrigger.Conditions> <Setter TargetName="PART_Header" Property="MinWidth" Value="75" /> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="HasHeader" Value="false" /> <Condition Property="Height" Value="Auto" /> </MultiTrigger.Conditions> <Setter TargetName="PART_Header" Property="MinHeight" Value="19" /> </MultiTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="ItemContainer" TargetType="{x:Type ListBoxItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <Border x:Name="IconBorder" Background="Transparent" CornerRadius="4" BorderThickness="0"> <ContentPresenter /> </Border> <ControlTemplate.Triggers> <Trigger Property="IsSelected" Value="true"> <Setter TargetName="IconBorder" Property="BitmapEffect"> <Setter.Value> <OuterGlowBitmapEffect GlowColor="Transparent" GlowSize="5" /> </Setter.Value> </Setter> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </UserControl.Resources> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <!--待选择列表--> <Grid> <Grid.RowDefinitions> <RowDefinition Height="40"></RowDefinition> <RowDefinition ></RowDefinition> </Grid.RowDefinitions> <wpfApplication17:SearchControl x:Name="BtnSearch" Margin="30,0,10,0" VerticalAlignment="Center" HorizontalAlignment="Left" OnSearch="BtnSearch_OnOnSearch"></wpfApplication17:SearchControl> <ScrollViewer Grid.Row="1" Margin="20,0,0,0" Template="{StaticResource ScrollViewerControlTemplate1}" CanContentScroll="True"> <TreeView x:Name="MyTreeView" ScrollViewer.VerticalScrollBarVisibility="Disabled" HorizontalAlignment="Stretch" Background="Transparent" BorderBrush="Transparent"></TreeView> </ScrollViewer> </Grid> <!--已选择列表--> <Grid Grid.Column="1"> <Grid.RowDefinitions> <RowDefinition Height="40"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <TextBlock Text="已选择列表" Foreground="White" FontSize="15" VerticalAlignment="Center" Margin="10"></TextBlock> <ListBox x:Name="RightListBox" Grid.Row="1" HorizontalAlignment="Right" Margin="50,0" Background="Transparent" ItemContainerStyle="{StaticResource ItemContainer}" FocusVisualStyle="{x:Null}"> <ListBox.Template> <ControlTemplate> <StackPanel Background="Transparent" IsItemsHost="True"></StackPanel> </ControlTemplate> </ListBox.Template> <ListBox.ItemTemplate> <DataTemplate> <Grid Height="28"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="40"></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Text="{Binding Name}" Foreground="White" FontSize="15" VerticalAlignment="Center" HorizontalAlignment="Center"/> <Button x:Name="BtnDelete" Grid.Column="1" Background="Transparent" ToolTip="移除" VerticalAlignment="Center" HorizontalAlignment="Center" Click="BtnRemove_OnClick"> <Button.Template> <ControlTemplate TargetType="Button"> <Grid> <Rectangle x:Name="BtnRetangle" Height="17" Width="17" Stroke="Transparent" StrokeThickness="1" VerticalAlignment="Center" HorizontalAlignment="Center"> <Rectangle.Fill> <ImageBrush ImageSource="Delete.png"></ImageBrush> </Rectangle.Fill> </Rectangle> <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Content="{TemplateBinding Content}"></ContentPresenter> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="BtnRetangle" Property="Height" Value="19"></Setter> <Setter TargetName="BtnRetangle" Property="Width" Value="19"></Setter> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Button.Template> </Button> </Grid> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Grid> </UserControl>
2、后台:
public partial class SelectControl : UserControl { private List<TreeViewModel> ItemSoure { get; set; } public SelectControl() { InitializeComponent(); ItemSoure = new List<TreeViewModel>() { new TreeViewModel() { Name = "前端设计", TreeViewItems = new List<TreeViewModel>() { new TreeViewModel(){Name = "Html/Css/Js"}, new TreeViewModel(){Name = "WPF"}, new TreeViewModel(){Name = "Winform"}, new TreeViewModel(){Name = "Webform"}, new TreeViewModel(){Name = "U3D"}, } }, new TreeViewModel() { Name = "后台语言", TreeViewItems = new List<TreeViewModel>() { new TreeViewModel(){Name = "C#"}, new TreeViewModel(){Name = "VB.Net"}, new TreeViewModel(){Name = "Java"}, new TreeViewModel(){Name = "PHP"}, new TreeViewModel(){Name = "C"}, new TreeViewModel(){Name = "Python"}, new TreeViewModel(){Name = "C++"}, new TreeViewModel(){Name = "Ruby"}, } },new TreeViewModel() { Name = "数据库", TreeViewItems = new List<TreeViewModel>() { new TreeViewModel(){Name = "SqlServer"}, new TreeViewModel(){Name = "MySql"}, new TreeViewModel(){Name = "Oracle"}, new TreeViewModel(){Name = "SqlLite"}, new TreeViewModel(){Name = "MongoDB"}, new TreeViewModel(){Name = "PLSql"}, } } }; MyTreeView.ItemsSource = ItemSoure; RightListBox.ItemsSource = null; RightListBox.ItemsSource = new List<TreeViewModel>(); } /// <summary> /// 选择 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnAdd_OnClick(object sender, RoutedEventArgs e) { Button button = sender as Button; var viewModel = button.DataContext as TreeViewModel; if (!viewModel.IsChecked) { viewModel.IsChecked = true; var selectList = RightListBox.ItemsSource as List<TreeViewModel>; selectList.Add(viewModel); RightListBox.ItemsSource = null; RightListBox.ItemsSource = selectList; } } /// <summary> /// 移除 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnRemove_OnClick(object sender, RoutedEventArgs e) { Button button = sender as Button; var viewModel = button.DataContext as TreeViewModel; viewModel.IsChecked = false; var selectList = RightListBox.ItemsSource as List<TreeViewModel>; selectList.Remove(viewModel); RightListBox.ItemsSource = null; RightListBox.ItemsSource = selectList; } /// <summary> /// 搜索 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnSearch_OnOnSearch(object sender, SearchEventArgs e) { string serachText=e.SearchText; var items=new List<TreeViewModel>(); if (string.IsNullOrWhiteSpace(serachText)) { MyTreeView.ItemsSource = ItemSoure; return; } foreach (var item in ItemSoure) { var childrenItems=item.TreeViewItems.Where(o => o.Name.Contains(serachText)).ToList(); if (childrenItems.Count>0) { var parentItem=new TreeViewModel(){Name = item.Name}; parentItem.TreeViewItems = childrenItems; items.Add(parentItem); } } MyTreeView.ItemsSource = items; } } public class TreeViewModel : INotifyPropertyChanged { public string Name { get; set; } private bool _isChecked = false; public bool IsChecked { get { return _isChecked; } set { _isChecked = value; if (this.PropertyChanged != null) { this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("IsChecked")); } } } public List<TreeViewModel> TreeViewItems { get; set; } public event PropertyChangedEventHandler PropertyChanged; [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } }
GitHub下载此案例Demo:https://github.com/Kybs0/DataSelectControlDemo
TreeViewItem添加MouseOver/Hover效果:
当有HierarchicalDataTemplate时,下级Item的MouseOver状态Trigger设置,可以通过里面的元素直接设置。
<Trigger SourceName="Bd" Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource Brush.Highlight}"/>
</Trigger>
因为TreeViewItem的MouseOver关联的是整个TreeViewItem和其下级的状态。。