WPF 简单实现下拉筛选控件
框架使用.NET40
;
Visual Studio 2022
;
使用 ICollectionView[2] 实现筛选功能,还支持其他如下:
- 使集合具有当前记录管理
- 自定义排序
- 筛选和分组功能
实现代码
1)CheckedSearch.cs
代码如下:
SearchText
用来记录输入的筛选内容Text
用来记录展示的所选内容^
拼接ItemsSource
数据源ContainsFilter
筛选数据,如果从数据源中找到则返回True
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using WpfCustomControlLibrary1.Datas;
namespace WpfCustomControlLibrary1
{
public class CheckedSearch : Control
{
private ICollectionView _filteredCollection;
public ICollectionView FilteredCollection { get { return _filteredCollection; } }
private string _searchText = string.Empty;
public string SearchText
{
get { return _searchText; }
set
{
if (_searchText != value)
{
_searchText = value;
_filteredCollection.Refresh();
}
}
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(CheckedSearch), new PropertyMetadata(string.Empty));
public ObservableCollection<CheckedSearchItem> ItemsSource
{
get { return (ObservableCollection<CheckedSearchItem>)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(ObservableCollection<CheckedSearchItem>), typeof(CheckedSearch), new PropertyMetadata(null, OnItemsSourceChanged));
private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var choseSearch = (CheckedSearch)d;
if (choseSearch == null) return;
if (choseSearch._filteredCollection == null && choseSearch.ItemsSource.Count > 0)
{
foreach (var item in choseSearch.ItemsSource)
{
item.PropertyChanged -= choseSearch.Item_PropertyChanged;
item.PropertyChanged += choseSearch.Item_PropertyChanged;
}
choseSearch._filteredCollection = CollectionViewSource.GetDefaultView(choseSearch.ItemsSource);
choseSearch._filteredCollection.Filter = choseSearch.ContainsFilter;
}
}
string GetItems()
{
var list = ItemsSource.Where(x=>x.IsChecked).Select(x=>x.Name).ToList();
var visibleItems = string.Join("^",list);
return visibleItems;
}
static CheckedSearch()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckedSearch), new FrameworkPropertyMetadata(typeof(CheckedSearch)));
}
private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "IsChecked")
Text = GetItems();
}
private bool ContainsFilter(object item)
{
var model = item as CheckedSearchItem;
if (model == null)
return false;
if (string.IsNullOrEmpty(SearchText))
return true;
if (model.Name.ToUpperInvariant().Contains(SearchText.ToUpperInvariant()))
return true;
return false;
}
}
}
2)CheckedSearchItem.cs
代码如下:
IsChecked
记录是否选中Name
展示的名称
using System.ComponentModel;
namespace WpfCustomControlLibrary1.Datas
{
public class CheckedSearchItem
{
public string Name { get; set; }
private bool _isChecked;
public bool IsChecked
{
get { return _isChecked; }
set
{
_isChecked = value;
OnPropertyChanged("IsChecked");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
3)CheckedSearch.xaml
代码如下:
<Style TargetType="{x:Type local:CheckedSearch}">
<Setter Property="Height" Value="40"/>
<Setter Property="Width" Value="200"/>
<Setter Property="BorderBrush" Value="DodgerBlue"/>
<Setter Property="Background" Value="White"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CheckedSearch}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
x:Name="PART_Border">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Text,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Foreground="Black"
VerticalAlignment="Center"
Margin="2,0"/>
<ToggleButton x:Name="PART_ToggleButton"
Focusable="False"
Width="30"
Style="{x:Null}"
Grid.Column="1"
ClickMode="Release">
<Path Stretch="Fill"
Height="6" Width="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M998 352c0 -8 -4 -17 -10 -23l-50 -50c-6 -6 -14 -10 -23 -10c-8 0 -17 4 -23 10l-393 393l-393 -393c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-50 50c-6 6 -10 15 -10 23s4 17 10 23l466 466c6 6 15 10 23 10s17 -4 23 -10l466 -466c6 -6 10 -15 10 -23z"
Fill="Black">
</Path>
</ToggleButton>
<Popup IsOpen="{Binding ElementName=PART_ToggleButton,Path=IsChecked}"
x:Name="PART_Popup"
VerticalOffset="2"
AllowsTransparency="True"
PlacementTarget="{Binding ElementName=PART_Border}"
Placement="Bottom" StaysOpen="False">
<Border Width="{TemplateBinding Width}"
Padding="2,4"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel>
<TextBox Text="{Binding SearchText,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Height="40" VerticalContentAlignment="Center"
Margin="0,0,0,2"/>
<ListBox ItemsSource="{TemplateBinding ItemsSource}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}"
IsChecked="{Binding IsChecked}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Border>
</Popup>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
4)CheckedSearchExample.xaml
示例代码如下:
<wd:Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
xmlns:custom="clr-namespace:WpfCustomControlLibrary1;assembly=WpfCustomControlLibrary1"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="WPFDevelopers - 搜索多选控件" Height="450" Width="800">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WpfApp1;component/CheckedSearch.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<!--公众号:WPF开发者-->
<Grid>
<custom:CheckedSearch
ItemsSource="{Binding ItemsSource,RelativeSource={RelativeSource AncestorType=Window}}"
VerticalAlignment="Top" Margin="0,10"/>
</Grid>
</wd:Window>
5)CheckedSearchExample.xaml
数据源示例代码如下:
using System.Collections.ObjectModel;
using System.Windows;
using WpfCustomControlLibrary1.Datas;
namespace WpfApp1
{
public partial class MainWindow
{
public ObservableCollection<CheckedSearchItem> ItemsSource
{
get { return (ObservableCollection<CheckedSearchItem>)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(ObservableCollection<CheckedSearchItem>), typeof(MainWindow), new PropertyMetadata(null));
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
ItemsSource = new ObservableCollection<CheckedSearchItem>();
var items = new ObservableCollection<CheckedSearchItem>();
items.Add(new CheckedSearchItem { Name = "Winform" });
items.Add(new CheckedSearchItem { Name = "WPF" });
items.Add(new CheckedSearchItem { Name = "WinUI 3" });
items.Add(new CheckedSearchItem { Name = "MAUI" });
items.Add(new CheckedSearchItem { Name = "Avalonia UI" });
ItemsSource = items;
}
}
}
到此这篇关于基于WPF实现简单的下拉筛选控件的文章就介绍到这了,更多相关WPF下拉筛选控件内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!