我可以从xaml过滤集合吗?

Rel*_*ity 9 c# wpf observablecollection mvvm

我有一个wpf-mvvm应用程序.

我的viewmodel中有一个可观察的集合

public ObservableCollection<BatchImportResultMessageDto> ImportMessageList { get; set; } 
Run Code Online (Sandbox Code Playgroud)

"BatchImportResultMessageDto"包含两个属性..

结果类型和消息.结果类型可以是成功或失败.

我需要在一个列表框中显示成功..而在另一个列表框中显示失败.

我可以这样做..在viewmodel中有2个可观察的集合来保存成功/失败.

public ObservableCollection<BatchImportResultMessageDto> ImportFailureMessageList { get; set; } // To hold the failure messages.
public ObservableCollection<BatchImportResultMessageDto> ImportSuccessMessageList { get; set; } // To hold the sucess messages.
Run Code Online (Sandbox Code Playgroud)

但还有其他更好的方法,以便我可以过滤它(没有新的两个集合)?

dev*_*tal 12

您可以使用CollectionViewSource并使其成为视图模型的属性,并ImportMessageList直接从XAML 绑定到该集合而不是您的集合.将您的ImportMessageList集合设置为的源CollectionViewSource,然后配置谓词以对其进行过滤CollectionViewSource.

就像是:

private ICollectionView messageListView;
public ICollectionView MessageListView
{
    get { return this.messageListView; }
    private set
    {
      if (value == this.messageListView)
      {
        return;
      }

      this.messageListView = value;
      this.NotifyOfPropertyChange(() => this.MessageListView);
    }
}

...


this.MessageListView = CollectionViewSource.GetDefaultView(this.ImportMessageList);
this.MessageListView.Filter = new Predicate<object>(this.FilterMessageList);

...

public bool FilterMessageList(object item)
{
  // inspect item as message here, and return true 
  // for that object instance to include it, false otherwise
  return true;
}
Run Code Online (Sandbox Code Playgroud)


Rag*_*ato 11

您可以通过创建两个CollectionViewSource对象并在每个对象上设置过滤器来完成此操作.

如何从VM绑定()在xaml中创建CVS :

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Window.Resources>
        <CollectionViewSource Source="{Binding}" x:Key="customerView">
           <CollectionViewSource.GroupDescriptions>
               <PropertyGroupDescription PropertyName="Country" />
           </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
    </Window.Resources>
    <ListBox ItemSource="{Binding Source={StaticResource customerView}}" />
</Window>
Run Code Online (Sandbox Code Playgroud)

如何在后面的代码中过滤CVS(如果您不想对其进行引用,可以使用反射来查看模型的属性.来源):

<CollectionViewSource x:Key="MyCVS"
                              Source="{StaticResource CulturesProvider}"
                              Filter="MyCVS_Filter" />
Run Code Online (Sandbox Code Playgroud)

用(代码背后)

void MyCVS_Filter(object sender, FilterEventArgs e)
{
    CultureInfo item = e.Item as CultureInfo;
    if (item.IetfLanguageTag.StartsWith("en-"))
    {
        e.Accepted = true;
    }
    else
    {
        e.Accepted = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 它并不总是违反mvvm模式将这些代码放在代码隐藏中.如果它纯粹与视图相关(仅过滤),则可以使用代码隐藏.它可能不如绑定或xaml属性好,但CollectionViewSource不支持过滤器. (10认同)
  • 后面的代码违反了MVVM模式。 (2认同)