c# - 使用LinQ过滤ObservableCollection

原文 标签 c# wpf linq mvvm observablecollection

我有一个MVVM应用程序,并且我试图通过LinQ对我的ObservableCollection进行过滤,该ObservableCollection是从基于Entity Framework的数据库中获得的。

在视图模型中,我有这个:

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
    }
}


在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"/>


问题是,当我在TextBox中编写任何内容时,没有任何变化。我知道propertyChanged事件出了点问题,但是我真的不知道该如何解决。如果您需要有关此应用的更多信息,请问我。

编辑:
用于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>

最佳答案

您可以使用ICollectionView来实现。

使用FilteredItems作为ICollectionView的基础源并将ICollectionView而不是ObservableCollection<Menu>暴露给您的视图

使用过滤器委托提供过滤器逻辑

FilteredItems.Filter = item =>
{
    Menu m = item as Menu;
    return m.Time.ToString().StartsWith(FilterString);
}


FilterString更改时调用FilterItems.Refresh();

这是一个例子:

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; }
}


您还必须更改过滤器UpdateSourceTrigger上的TextBox,以使其在用户每次更改文本时更新FilterString

Text="{Binding FilterString, UpdateSourceTrigger=PropertyChanged, ...}

相关文章:

linq - LINQ:选择<条件>或<条件>

c# - 当我发回到 Controller 时,我模型的所有值都为空

c# - 在上下文菜单中禁用多重检查

c# - Linq Select方法,其中一个方法作为带有两个参数的参数

c# - 没有事件的C#WPF序列化XAML

c# - WPF TreeView带有图标和文本

c# - 使用HTML Agility Pack和Linq解析html

c# - Microsoft Bot Framework示例致文本Bot的语音-clientid和clientSecret

c# - 禁用超时后,SqlBulkCopy到Azure的超时

c# - 如何使用JSON.Net转换新的Date(年,月,日)重载