我正在使用MVVM模式处理WPF桌面应用程序.
我试图ListView根据输入的文本过滤一些项目TextBox.我希望在ListView更改文本时过滤项目.
我想知道在过滤器文本更改时如何触发过滤器.
在ListView绑定到CollectionViewSource,它绑定到ObservableCollection我的视图模型.该TextBox用于过滤文字结合在视图模型的字符串,UpdateSourceTrigger=PropertyChanged,因为它应该是.
<CollectionViewSource x:Key="ProjectsCollection"
Source="{Binding Path=AllProjects}"
Filter="CollectionViewSource_Filter" />
<TextBox Text="{Binding Path=FilterText, UpdateSourceTrigger=PropertyChanged}" />
<ListView DataContext="{StaticResource ProjectsCollection}"
ItemsSource="{Binding}" />
Run Code Online (Sandbox Code Playgroud)
Filter="CollectionViewSource_Filter"指向后面代码中的事件处理程序的链接,它只是在ViewModel上调用过滤器方法.
当FilterText的值发生更改时进行过滤 - FilterText属性的setter调用FilterList方法,该方法迭代ObservableCollection我的ViewModel并boolean在每个项目ViewModel上设置FilteredOut属性.
我知道过滤器文本更改时FilteredOut属性会更新,但List不会刷新.该CollectionViewSource当我切换远离它,并再次重新加载用户控件过滤事件仅触发.
我OnPropertyChanged("AllProjects")在更新过滤器信息后尝试过调用,但它没有解决我的问题.("AllProjects"是ObservableCollection我绑定到的ViewModel上的属性CollectionViewSource.)
CollectionViewSource当FilterText的值TextBox发生变化时,如何让自己重新过滤?
非常感谢
我正在使用一个ObservableCollection带有两个ICollectionView不同的过滤器.
一种用于按某种类型过滤消息,一种用于计算已检查的消息.正如您所看到的,消息过滤器和消息计数工作正常,但是当我取消检查时,消息将从列表中消失(计数仍然有效).
对于这篇长篇文章,我很抱歉,我想包括所有相关内容.
XAML代码:
<!-- Messages List -->
<DockPanel Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="3"
Height="500">
<ListBox Name="listBoxZone"
ItemsSource="{Binding filteredMessageList}"
Background="Transparent"
BorderThickness="0">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Name="CheckBoxZone"
Content="{Binding text}"
Tag="{Binding id}"
Unchecked="CheckBoxZone_Unchecked"
Foreground="WhiteSmoke"
Margin="0,5,0,0"
IsChecked="{Binding isChecked}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
<Button Content="Test Add New"
Grid.Column="2"
Height="25"
HorizontalAlignment="Left"
Margin="34,2,0,0"
Click="button1_Click" />
<Label Content="{Binding checkedMessageList.Count}"
Grid.Column="2"
Height="25"
Margin="147,2,373,0"
Width="20"
Foreground="white" />
Run Code Online (Sandbox Code Playgroud)
截图:

码:
/* ViewModel Class */
public class MainViewModel : INotifyPropertyChanged
{
// Constructor
public MainViewModel()
{
#region …Run Code Online (Sandbox Code Playgroud) c# wpf observablecollection collectionviewsource icollectionview
我使用Drag和Drop将Data Source对象(一个DB模型)绑定到DataGrid(基本上遵循WPF实体框架数据绑定中的这个示例).
这个实现一切正常.
<Window.Resources>
<CollectionViewSource x:Key="categoryViewSource"
d:DesignSource="{d:DesignInstance {x:Type local:Category}, CreateList=True}"/>
</Window.Resources>
<Grid DataContext="{StaticResource categoryViewSource}">
..
Run Code Online (Sandbox Code Playgroud)
private void Window_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Data.CollectionViewSource categoryViewSource =
((System.Windows.Data.CollectionViewSource)(this.FindResource("categoryViewSource")));
_context.Categories.Load();
categoryViewSource.Source = _context.Categories.Local;
}
Run Code Online (Sandbox Code Playgroud)
public MainWindow()
{
InitializeComponent();
this.DataContext = new MyViewModel();
}
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试在ViewModel中使用相同的代码时,它不起作用(FindResource不可用),此外,我不认为这是正确的方法(即x:Key在MVVM中使用).
我真的很感激任何帮助点我是什么来实现的正确途径CollectionViewSource,并DataBinding用DataGrid.
我有一个ListView,它包含两种类型的对象,单个和多个.单个是普通的TextBlock,而倍数是带有项目的ComboBox.
我正在尝试将ComboBox中的项目分组而没有成功.可能吗?或者我应该采取不同的方法?
我想要实现的目标:
[ComboBox v]
[Header ]
[ Item]
[ Item]
[Header ]
[ Item]
Run Code Online (Sandbox Code Playgroud) 我正在寻找一种方式来重新梳理我DataGrid当基础数据已经改变.
(设置非常标准:DataGrid的ItemSource属性绑定到ObservableCollection;列是DataGridTextColumns; DataGrid内的数据对ObservableCollection内部的更改做出正确反应;使用鼠标单击时排序工作正常)
有任何想法吗 ?
我正在尝试对CollectionViewSource进行基本使用,我必须遗漏一些东西,因为它不起作用.这是我的XAML:
<Window.Resources>
<CollectionViewSource Source="{Binding loc:MainVM.Instance.MapItems}" x:Key="MapCV">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="SourceProject" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)
<ListBox ItemsSource="{StaticResource MapCV}" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding SourceType, Converter={StaticResource WorkItemTypeToStringConverter}}"/>
<ComboBox Grid.Column="1" SelectedItem="{Binding DestType}" ItemsSource="{Binding WorkItemTypesForCurrentDestProject, Source={x:Static loc:MainMediator.Instance}, diagnostics:PresentationTraceSources.TraceLevel=High}" DisplayMemberPath="Name" />
<Button Grid.Column="2" Content="{Binding PercentMapped}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Run Code Online (Sandbox Code Playgroud)
这编译很好,但是当我运行应用程序时,我收到此错误:
Cannot convert the value in attribute 'ItemsSource' to object of type 'System.Collections.IEnumerable'. 'System.Windows.Data.CollectionViewSource' is not a valid value for property 'ItemsSource'. Error at object …
我正在使用绑定到CollectionViewSource(播放器)的DataGrid ,它本身绑定到ListBox(级别)的当前所选项目,每个项目包含要在DataGrid中排序/显示的集合:
<ListBox Name="lstLevel"
DisplayMemberPath="Name"
IsSynchronizedWithCurrentItem="True" />
Run Code Online (Sandbox Code Playgroud)
...
<!-- DataGrid source, as a CollectionViewSource to allow for sorting and/or filtering -->
<CollectionViewSource x:Key="Players"
Source="{Binding ElementName=lstLevel,
Path=SelectedItem.Players}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Name" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
Run Code Online (Sandbox Code Playgroud)
...
<DataGrid Name="lstPlayers" AutoGenerateColumns="False"
CanUserSortColumns="False"
ItemsSource="{Binding Source={StaticResource Players}}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name"
Binding="{Binding Path=Name, Mode=TwoWay}"
Width="*" />
<DataGridTextColumn Header="Age"
Binding="{Binding Path=Age, Mode=TwoWay}"
Width="80">
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)
(整个C#代码在这里,XAML代码在这里,整个测试项目在这里 - 除了DataGrid我已经为玩家添加了一个简单的ListBox,以确保它不是DataGrid问题)
问题是玩家在第一次显示时进行排序,但是一旦我从ListBox中选择另一个级别,他们就不再排序了.此外,在第一次显示玩家时修改名称将根据更改对其进行排序,但是一旦更改了级别,就不再对其进行排序.
所以看起来改变CollectionViewSource的源代码会以某种方式破坏排序功能,但我不知道为什么,也不知道如何修复它.有谁知道我做错了什么?
(我用过滤器进行了测试,但是那个按预期工作了)
该框架是.NET 4.
我已经编写了带有搜索扩展名的自定义WPF控件,让我们为它命名MyControl.控制是一个ItemsControl 阶级的后代.
所以我像这样将数据源提供给它:
控件本身使用
protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue)
{
if (newValue != null)
{
ICollectionView view = CollectionViewSource.GetDefaultView(newValue);
view.Filter += this.FilterPredicate;
}
if (oldValue != null)
{
ICollectionView view = CollectionViewSource.GetDefaultView(oldValue);
view.Filter -= this.FilterPredicate;
}
base.OnItemsSourceChanged(oldValue, newValue);
}
Run Code Online (Sandbox Code Playgroud)
过滤源集合的视图(从而在内部ListBox中显示它).
现在假设我们在XAML中定义了10个具有相同DynamicSource的MyControl.问题是如果其中一个在源集合上应用Filter,它也会影响所有其他实例.
如何更改控件以避免此行为?
我有一个viewmodel的datatemplate,其中itemscontrol绑定到CollectionViewSource(以启用xaml中的排序).
<DataTemplate x:Key="equipmentDataTemplate">
<Viewbox>
<Viewbox.Resources>
<CollectionViewSource x:Key="viewSource" Source="{Binding Modules}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="ID" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Viewbox.Resources>
<ItemsControl ItemsSource="{Binding Source={StaticResource viewSource}}"
Height="{DynamicResource equipmentHeight}"
ItemTemplate="{StaticResource moduleDataTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Viewbox>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
我还设置了UserControl,其中所有这些都被定义为提供设计时数据
d:DataContext="{x:Static vm:DesignTimeHelper.Equipment}">
Run Code Online (Sandbox Code Playgroud)
这基本上是一个静态属性,它给我一个EquipmentViewModel,它有一个ModuleViewModel(Equipment.Modules)列表.现在,只要我绑定到CollectionViewSource,设计时数据就不会出现在混合3中.当我直接绑定到ViewModel集合时
<ItemsControl ItemsSource="{Binding Modules}"
Run Code Online (Sandbox Code Playgroud)
我可以看到设计时数据.知道我能做什么吗?
假设我们有一个简单的VM类
public class PersonViewModel : Observable
{
private Person m_Person= new Person("Mike", "Smith");
private readonly ObservableCollection<Person> m_AvailablePersons =
new ObservableCollection<Person>( new List<Person> {
new Person("Mike", "Smith"),
new Person("Jake", "Jackson"),
});
public ObservableCollection<Person> AvailablePersons
{
get { return m_AvailablePersons; }
}
public Person CurrentPerson
{
get { return m_Person; }
set
{
m_Person = value;
NotifyPropertyChanged("CurrentPerson");
}
}
}
Run Code Online (Sandbox Code Playgroud)
成功数据绑定到ComboBox就足够了,例如:
<ComboBox ItemsSource="{Binding AvailablePersons}"
SelectedValue="{Binding Path=CurrentPerson, Mode=TwoWay}" />
Run Code Online (Sandbox Code Playgroud)
请注意,Person已经Equals过载,当我在ViewModel中设置CurrentPerson值时,它会导致组合框当前项显示新值.
现在假设我想在我的视图中添加排序功能 CollectionViewSource
<UserControl.Resources>
<CollectionViewSource x:Key="PersonsViewSource" Source="{Binding AvailablePersons}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Surname" Direction="Ascending" …Run Code Online (Sandbox Code Playgroud)