Я знаю, что этот вопрос закрыт и старый.но для кого-то вроде меня, ищущего динамическую фильтрацию, можно обратиться к следующей ссылке
https://github.com/lokeshlal/WPFDynamicFilters
. В приведенном выше примере создаются фильтры для каждой сущности на основе атрибута, определенного в свойстве модели сущности.
Например:
Определить атрибут для фильтров
public class FilterAttribute : Attribute
{
public FilterAttribute() { }
public string FilterLabel { get; set; }
public object FilterValue { get; set; }
public string FilterKey { get; set; }
public Type FilterDataType { get; set; }
public bool IsDropDown { get; set; }
public string DropDownList { get; set; }
public List<object> ObjectDropDownList { get; set; }
}
Применить указанный выше атрибут в свойствах модели
public class GridModel
{
[Filter(FilterLabel = "Id",
FilterKey = "Id",
IsDropDown = false,
FilterDataType = typeof(int))]
public int Id { get; set; }
[Filter(FilterLabel = "Name",
FilterKey = "Name",
IsDropDown = false,
FilterDataType = typeof(string))]
public string Name { get; set; }
[Filter(FilterLabel = "Country",
FilterKey = "Country",
IsDropDown = true,
FilterDataType = typeof(int),
DropDownList = "Country")]
public string Country { get; set; }
[Filter(FilterLabel = "Address",
FilterKey = "Address",
IsDropDown = false,
FilterDataType = typeof(string))]
public string Address { get; set; }
}
Определите модель, которая будет привязана к раскрывающемуся типу
public class Country
{
public int Id { get; set; } // id will be used for value
public string Name { get; set; } // Name will be used for display value
}
ViewModel фактического вида
public class FilterViewModel
{
public ICommand CheckFiltersCommand { get; set; }
public FilterViewModel()
{
CheckFiltersCommand = new DelegateCommand(GetFilters);
GridSource = new List<GridModel>();
GridSource.Add(new GridModel() { Id = 1, Name = "Name1", Country = "Denmark" });
GridSource.Add(new GridModel() { Id = 2, Name = "Name2", Country = "India" });
GridSource.Add(new GridModel() { Id = 3, Name = "Name3", Country = "Australia" });
GridSource.Add(new GridModel() { Id = 4, Name = "Name4", Country = "India" });
GridSource.Add(new GridModel() { Id = 5, Name = "Name5", Country = "Australia" });
GridSource.Add(new GridModel() { Id = 6, Name = "Name6", Country = "Hongkong" });
FilterControlViewModel = new FilterControlViewModel();
FilterControlViewModel.FilterDetails = new List<FilterAttribute>();
foreach (var property in typeof(GridModel).GetProperties())
{
if (property.GetCustomAttributes(true).Where(attr => attr.GetType() == typeof(FilterAttribute)).Any())
{
var attribute = (FilterAttribute)property.GetCustomAttributes(true).Where(attr => attr.GetType() == typeof(FilterAttribute)).First();
FilterControlViewModel.FilterDetails.Add(attribute);
}
}
}
private void GetFilters()
{
FilterCollection = new Dictionary<string, object>();
foreach (var filter in FilterControlViewModel.FilterDetails)
{
if (filter.IsDropDown)
{
if (filter.FilterValue != null)
FilterCollection.Add(filter.FilterKey, filter.FilterValue.GetType().GetProperty("Id").GetValue(filter.FilterValue));
}
else
{
FilterCollection.Add(filter.FilterKey, filter.FilterValue);
}
}
MessageBox.Show(string.Join(", ", FilterCollection.Select(m => m.Key + ":" + Convert.ToString(m.Value)).ToArray()));
}
public List<GridModel> GridSource { get; set; }
public Dictionary<string, object> FilterCollection { get; set; }
public FilterControlViewModel FilterControlViewModel { get; set; }
}
В вышеприведенном представлении свойство 'FilterControlViewModel' будет перебирать все свойства модели и собирать информацию фильтра свойств.Это же свойство будет назначено пользовательскому элементу управления, как описано в файле xaml ниже
<Window x:Class="WPFDynamicFilters.GridWithFilters"
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:local="clr-namespace:WPFDynamicFilters"
mc:Ignorable="d"
Title="gridwithfilters" Height="481.239" Width="858.171">
<Grid>
<Grid HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" x:Name="FilterGrid" Height="209" Width="830">
<Border BorderThickness="1" BorderBrush="Gold"/>
<local:Filter DataContext="{Binding FilterControlViewModel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,10" />
</Grid>
<DataGrid x:Name="DataGrid" ItemsSource="{Binding GridSource}" HorizontalAlignment="Left" Margin="10,294,0,0" VerticalAlignment="Top" Height="146" Width="830"/>
<Button x:Name="button" Content="Check Filters" HorizontalAlignment="Left" Margin="10,245,0,0" VerticalAlignment="Top" Width="110" Command="{Binding CheckFiltersCommand}"/>
</Grid>
</Window>
Элемент управления фильтра будет принимать все атрибуты и отображать элемент управления с помощью itemscontrol
<UserControl x:Class="WPFDynamicFilters.Filter"
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:local="clr-namespace:WPFDynamicFilters"
mc:Ignorable="d"
d:DesignHeight="40"
>
<UserControl.Resources>
<DataTemplate x:Key="TStringTemplate">
<StackPanel FlowDirection="LeftToRight">
<TextBlock Text="{Binding FilterKey}" />
<TextBox x:Name="TxtFieldValue"
Text="{Binding FilterValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
RenderTransformOrigin="-9.3,0.5" Width="200" FontSize="16" TextAlignment="Left" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="TIntegerTemplate">
<StackPanel FlowDirection="LeftToRight">
<TextBlock Text="{Binding FilterKey}" />
<TextBox x:Name="IntFieldValue"
Text="{Binding FilterValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
RenderTransformOrigin="-9.3,0.5" Width="200" FontSize="16" TextAlignment="Left" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="TDropDownTemplate">
<StackPanel FlowDirection="LeftToRight">
<TextBlock Text="{Binding FilterKey}" />
<ComboBox
SelectedItem="{Binding FilterValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedIndex="{Binding FilterValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding ObjectDropDownList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Name"
RenderTransformOrigin="-9.3,0.5" Width="200" FontSize="16" />
</StackPanel>
</DataTemplate>
<local:FilterTemplateSelector x:Key="FilterTemplateSelector"
StringTemplate="{StaticResource TStringTemplate}"
IntegerTemplate="{StaticResource TIntegerTemplate}"
DropDownTemplate="{StaticResource TDropDownTemplate}"
/>
</UserControl.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding FilterDetails}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="3" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl
Content="{Binding}"
HorizontalAlignment="Left"
ContentTemplateSelector="{StaticResource FilterTemplateSelector}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
Наконец, определитеселектор шаблонов
public class FilterTemplateSelector : DataTemplateSelector
{
public DataTemplate StringTemplate { get; set; }
public DataTemplate IntegerTemplate { get; set; }
public DataTemplate DropDownTemplate { get; set; }
public override DataTemplate SelectTemplate(object item,
DependencyObject container)
{
var filter = (item as FilterAttribute);
if (filter == null) return StringTemplate;
if (!filter.IsDropDown)
{
switch (filter.FilterDataType.Name.ToLower())
{
case "int32":
case "int64":
return IntegerTemplate;
case "string":
return StringTemplate;
}
}
else
{
// display drop down
switch (filter.DropDownList)
{
case "Country":
filter.ObjectDropDownList = GetDropDown.GetCountries().ToList<object>();
break;
}
return DropDownTemplate;
}
return StringTemplate;
}
}