[英]Using LinQ to filter ObservableCollection
I have a MVVM application and I am trying to make filtering through LinQ work on my ObservableCollection that is gotten from database based on Entity Framework. 我有一个MVVM应用程序,并且我试图通过LinQ对我的ObservableCollection进行过滤,该ObservableCollection是从基于Entity Framework的数据库中获得的。
In View Model I have this: 在视图模型中,我有这个:
public class MenuListViewModel : BaseViewModelCollection<Menu>
{
private string filterString;
public string FilterString
{
get { return filterString; }
set
{
if (Equals(value, filterString)) return;
filterString = value;
RaisePropertyChanged();
}
}
//TODO problems with notification, filter doesn't work
public ObservableCollection<Menu> FilteredItems
{
get
{
if (filterString == null) return Items; //Items is Observable Collection that contains every Item
var query = Items.Where(x => x.Time.ToString().StartsWith(filterString));
return new ObservableCollection<Menu>(query);
}
}
public MenuListViewModel(MenuService menuService)
{
base.Service = menuService; //Using IoC to get service
}
}
In Xaml I have the following Binding: 在Xaml中,我具有以下绑定:
<TextBox x:Name="RecipeFilterBox" Margin="5,5,0,0" TextWrapping="Wrap" Text="{Binding FilterString, NotifyOnTargetUpdated=True}" Grid.Column="1" Height="47.07" VerticalAlignment="Top"/>
The thing is that when I write anything in the TextBox, nothing changes. 问题是,当我在TextBox中编写任何内容时,没有任何变化。 I know that there is something wrong with the propertyChanged event, but I really can't figure out how to fix this.
我知道propertyChanged事件出了点问题,但是我真的不知道该如何解决。 If you need any more information about this app, just ask me.
如果您需要有关此应用的更多信息,请问我。
EDIT: The xaml for FilteredItems looks like this: 编辑:FilteredItems的xaml看起来像这样:
<ListBox x:Name="MenuItemsListView" ItemsSource="{Binding FilteredItems}" SelectedItem="{Binding DeletedItem, Mode=OneWayToSource}" Foreground="#FFFFEDD3" FontFamily="Segoe Print" FontWeight="Bold" FontSize="18.667" Grid.ColumnSpan="3" Grid.Row="1" ItemContainerStyle="{DynamicResource ListBoxItemStyle1}" Style="{DynamicResource ListBoxStyle1}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Recipe.Name}" Width="255"/>
<TextBlock Width="175" Text="{Binding Time, Converter={StaticResource EnumTimeToItsDescriptionValueConverter}, Mode=OneWay}" />
<TextBlock Text="{Binding Date, StringFormat=dd.MM.yyyy}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
you can achieve this using ICollectionView
. 您可以使用
ICollectionView
实现此目的。
use FilteredItems
as the underlying source of the ICollectionView
and expose ICollectionView
to your view instead of ObservableCollection<Menu>
使用
FilteredItems
作为的底层源ICollectionView
和暴露ICollectionView
到您的视图代替ObservableCollection<Menu>
Use the filter delegate to provide the filter logic 使用过滤器委托提供过滤器逻辑
FilteredItems.Filter = item =>
{
Menu m = item as Menu;
return m.Time.ToString().StartsWith(FilterString);
}
and when FilterString
changes invoke FilterItems.Refresh();
当
FilterString
更改时,调用FilterItems.Refresh();
Here is an example: 这是一个例子:
public class MenuListViewModel : BaseViewModelCollection<Menu>
{
public MenuListViewModel()
{
var data = new List<Menu> { some data ... }; // your real list of menus
// initialize the collection view
FilteredItems = CollectionViewSource.GetDefaultView(data);
// apply filtering delegate
FilteredItems.Filter = i =>
{
// This will be invoked for every item in the underlying collection
// every time Refresh is invoked
if (string.IsNullOrEmpty(FilterString)) return true;
Menu m = i as Menu;
return m.Time.ToString().StartsWith(FilterString);
};
}
private string filterString;
public string FilterString
{
get { return filterString; }
set
{
if (Equals(value, filterString)) return;
filterString = value;
FilteredItems.Refresh(); // tirggers filtering logic
RaisePropertyChanged("FilterString");
}
}
public ICollectionView FilteredItems { get; set; }
}
You would also have to change the UpdateSourceTrigger
on your filter TextBox
to make it update the FilterString
every time the user changes the text. 您还必须更改过滤器
TextBox
上的UpdateSourceTrigger
,以使其在用户每次更改文本时更新FilterString
。
Text="{Binding FilterString, UpdateSourceTrigger=PropertyChanged, ...}
Add RaisePropertyChanged("FilteredItems")
inside FilterString
setter. 在
FilterString
设置器中添加RaisePropertyChanged("FilteredItems")
。 FilteredItems
property changed is never raised so bindings doesn't work the way you expect. 永远不会引发已更改的
FilteredItems
属性,因此绑定无法按您期望的方式工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.