【问题标题】:FilterEventHandler delegate function not firingFilterEventHandler 委托函数未触发
【发布时间】:2018-11-27 01:48:50
【问题描述】:

WPF 和 MVVM 的新手。我正在尝试将带有 FilterEventHandler 的过滤器用于 CollectionViewSource。我正在尝试在属性更改 (p_sSelectedCreatedDate) 中添加过滤器。问题是当我将过滤器添加到 CollectionViewSource 对象时,FilterEventHandler 委托函数(FilterByCreatedDate)没有触发。当我调试时,我可以在代码中看到正在添加过滤器,如下行所示。

CVS.Filter += new FilterEventHandler(FilterByCreatedDate);

但是,代码返回而不执行 FilterByCreatedDate。 请注意,我只发布此问题所需的代码部分和继承自 INotifyPropertyChangedBaseViewModel

以下是必要的代码。

ScanBatchWindow.xaml

<Window x:Class="BatchManPOC.ScanBatchWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:BatchManPOC"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:cmdBehavior="clr-namespace:BatchManPOC.CmdBehavior"
    xmlns:video="clr-namespace:BatchManPOC.Video"
    xmlns:Custom="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    mc:Ignorable="d"
    Title="ScanBatchWindow" 
    Height="800"
    Width="800">
<Window.Resources>
    <CollectionViewSource Source="{Binding p_ListBatches}" x:Key="CVS"/>
</Window.Resources>
     <Grid>
         <Grid.RowDefinitions>
               <RowDefinition/>
         </Grid.RowDefinitions>
              <Custom:DataGrid ItemsSource="{Binding Source={StaticResource CVS}}" Margin="8" Grid.Row="0" AutoGenerateColumns="True"  IsReadOnly="True">
</Custom:DataGrid>
        </Grid>
</Window>

ScanBatchViewModel.cs

public class ScanBatchViewModel : BaseViewModel
{
    public ObservableCollection<Batch> p_ListBatches { get; set; }
    public CollectionViewSource CVS { get; set; }

    private string _p_sSelectedCreatedDate;
    public string p_sSelectedCreatedDate {
        get
        {
            return _p_sSelectedCreatedDate;
        }
        set
        {
            _p_sSelectedCreatedDate = value;
            ApplyFilter(!string.IsNullOrEmpty(_p_sSelectedCreatedDate) ? FilterField.CREATED_DATE : FilterField.NONE);
        }
    }

    public ScanBatchViewModel()
    {
        p_ListBatches = new ObservableCollection<Batch>();

        LoadBatches();
        CVS = new CollectionViewSource();
    }

    private void ApplyFilter(FilterField field)
    {
        switch (field)
        {
            case FilterField.CREATED_DATE:
                AddCreatedDateFilter();
                break;
            default:
                break;
        }
    }

    public void AddCreatedDateFilter()
    {
        // see Notes on Adding Filters:
        if (p_bCanRemoveCreatedDateFilter)
        {
            CVS.Filter -= new FilterEventHandler(FilterByCreatedDate);
            CVS.Filter += new FilterEventHandler(FilterByCreatedDate);
        }
        else
        {
            CVS.Filter += new FilterEventHandler(FilterByCreatedDate);
            p_bCanRemoveCreatedDateFilter = true;
        }
    }

    private void FilterByCreatedDate(object sender, FilterEventArgs e)
    {
        // see Notes on Filter Methods:
        var src = e.Item as Batch;
        if (src == null)
            e.Accepted = false;
        else if (string.Compare(p_sSelectedCreatedDate, src.Date) != 0)
            e.Accepted = false;   
    }
}

【问题讨论】:

    标签: wpf mvvm filter eventhandler collectionviewsource


    【解决方案1】:

    CollectionViewSource.Filter 是一个事件。当CollectionViewSource 需要过滤内容时,它将被触发。当CollectionViewSource 更新视图时会发生这种情况。

    为了更新视图,调用相应的方法:

    CVS.View.Refresh();
    

    请记住,您的方法AddCreatedDateFilter() 可以为Filter 事件添加多个事件处理程序。将为集合中的每个项目调用每个事件处理程序。这可能会导致性能问题。而且所有的事件处理程序都是一样的,所以这也没用。

    因此请确保您只为此事件添加一个事件处理程序。

    【讨论】:

    • 调用 CVS.View.Refresh();。 CVS.View 似乎为 null 并引发异常。但我可以在我的前端看到填充列表。
    • 当我设置 CVS.Source = p_ListBatches; 时,我能够触发过滤事件 FilterByCreatedDate(...)。现在我的问题是,在代码中我必须在哪里调用 CVS.View.Refresh();。由于我在“p_sSelectedCreatedDate”的属性更改上添加了一个过滤器,所以在代码序列中我可以在哪里调用 CVS.View.Refresh();?
    • 您有两个 CollectionViewSource 实例 - 一个在 XAML 创建的视图中,另一个在视图模型中。那是错的。你只需要一个实例。在视图模型或 XAML 中删除一个。 CVS.View.Refresh() 调用取决于 CVS 的存储位置。有关详细信息,请参阅this question。您还可以在此处找到显示如何应用自定义过滤器的答案。
    猜你喜欢
    • 2015-11-27
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2012-07-21
    • 1970-01-01
    相关资源
    最近更新 更多