【问题标题】:Can I filter a collection from xaml?我可以从 xaml 过滤集合吗?
【发布时间】:2011-06-22 21:01:16
【问题描述】:

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

我的视图模型中有一个可观察的集合

public ObservableCollection<BatchImportResultMessageDto> ImportMessageList { get; set; } 

“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.

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

【问题讨论】:

标签: c# wpf mvvm observablecollection


【解决方案1】:

您可以使用 CollectionViewSource 并使其成为您的视图模型的属性,然后直接从 XAML 绑定到它而不是您的 ImportMessageList 集合。将您的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;
}

【讨论】:

  • 如何在 CollectionViewSource 中过滤?
  • 所以..对于 lisbox 的我们可以传递“MessageListView”?
  • 是的,您可以绑定到您的视图属性而不是您的项目集合。
【解决方案2】:

您可以通过创建两个CollectionViewSource 对象并在每个对象上设置一个过滤器来做到这一点。

如何通过 VM 绑定 (Source) 在 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>

如何在后面的代码中过滤 CVS(如果您不想引用它,可以使用反射来查看模型的属性。Source):

<CollectionViewSource x:Key="MyCVS"
                              Source="{StaticResource CulturesProvider}"
                              Filter="MyCVS_Filter" />

带有(代码隐藏)

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

【讨论】:

  • 将这样的代码放在代码隐藏中并不总是违反 mvvm 模式。如果它纯粹与视图相关(仅过滤),那么使用代码隐藏就可以了。它可能不如绑定或 xaml 属性好,但 CollectionViewSource 不支持过滤器。
  • @user2153378 没关系,因为 WPF 和 XAML 也违反了 MVVM 模式。
  • 后面的代码也可以移到viewmodel中。
猜你喜欢
  • 2014-10-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-25
  • 1970-01-01
  • 2013-02-20
  • 2019-01-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多