我为Behavior
构建了一个过滤CollectionViewSource
,它通常可以正常使用,并按照以下方式使用:
<CollectionViewSource Source="{Binding ListOfStuff}" x:Key="FilteredListOfStuff">
<i:Interaction.Behaviors>
<behaviors:FilterBehavior>
<behaviors:PropertyFilter Property="SomePropName">
<behaviors:TextFilter FilterText="filter text"/>
</behaviors:PropertyFilter>
</behaviors:FilterBehavior>
</i:Interaction.Behaviors>
</CollectionViewSource>
问题在于,正如我现在所知,我无法将过滤器属性绑定到UIElements,因为CollectionViewSource
是一个静态资源。
我想要的,现在不能做到的是:
<behaviors:TextFilter FilterText="{Binding ElementName=TheSearchTextBox, Path=Text}"/>
有解决方法吗?我的过滤行为是基于使用CollectionViewSource.Filter
事件,有没有一个好的,干净的方式来过滤没有&#39; CollectionViewSource&#39;?也就是说,直接向ItemsControl
(DataGrid,ListBox等)添加过滤器行为?
我可以通过将TheSearchTextBox.Text
和FilterText
绑定到同一个ViewModel属性来解决这个问题,但是这种类型会破坏MVVM,因为过滤是纯粹的&#34; View&#34;行动...
修改 添加过滤器行为代码:
[ContentPropertyAttribute("Filters")]
public class FilterBehavior : Behavior<CollectionViewSource>
{
private List<IFilter> _filters;
public List<IFilter> Filters
{
get
{
return _filters ??
(_filters = new List<IFilter>());
}
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Filter += CollectionViewSource_Filter;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Filter -= CollectionViewSource_Filter;
}
void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
if (Filters != null)
{
e.Accepted = Filters.All((f) => !f.IsEnabled || f.Filter(e.Item));
}
}
}
答案 0 :(得分:1)
我们需要在FilterText
类的behaviors:TextFilter
属性中提供用户提供的过滤字符串。
创建一个简单的类FilterPropertyElement:
public class FilterPropertyElement : FrameworkElement
{
public override string ToString()
{
return Tag.ToString();
}
}
声明资源
<Window.Resources>
<local:FilterPropertyElement x:Key="FilterPropertyKey" Tag="some filter key value"/>
</Window.Resources>
更改TextFilter定义以使用资源。 :
<behaviors:TextFilter FilterText="{Binding Path=Tag, Source={StaticResource FilterPropertyKey}}"/>
将绑定应用于TextBox,从哪里获取过滤条件
<TextBox Text="{Binding Path=Tag, Source={StaticResource FilterPropertyKey}, UpdateSourceTrigger=LostFocus}" />
答案 1 :(得分:0)
在AnjumSKhan的回答的启发下,我最终做的是将过滤器添加到rood Resources
集合并让TextBox
绑定到它:
<UserControl.Resources>
<b:TextFilter x:Key="SearchTextFilter" />
<CollectionViewSource Source="{Binding ListOfStuff}" x:Key="FilteredListOfStuff">
<i:Interaction.Behaviors>
<b:FilterBehavior>
<b:PropertyFilter Property="SomePropName">
<StaticResource ResourceKey="SearchTextFilter"/>
</b:PropertyFilter>
</b:FilterBehavior>
</i:Interaction.Behaviors>
</CollectionViewSource>
</UserControl.Resources>
.
.
.
<TextBox Text="{Binding Path=FilterText, Source={StaticResource SearchTextFilter}, Mode=OneWayToSource}"/>
这仍然不像我想的那么干净,但它是我能想到的最好的,如果有人有更好的解决方案,请告诉我。