【问题标题】:ICollectionView filter not being called未调用 ICollectionView 过滤器
【发布时间】:2013-07-12 21:26:32
【问题描述】:

我创建了一个小的用户控件,其中包含一个 ICollectionView 和一个 ObservableCollection。

ObservableCollection<LogMessage> messages;
public ObservableCollection<LogMessage> Messages
{
    get { return messages; }
}

ICollectionView log;
public ICollectionView Log
{
    get { return log; }
}

变量在UserControl的构造函数中设置

public LogFilter()
{
    messages = new ObservableCollection<LogMessage>();
    log = new CollectionView(messages);

    InitializeComponent();

#if DEBUG

    messages.Add(new LogMessage("This is a general Message", MessageType.General));
    messages.Add(new LogMessage("This is a server Message", MessageType.Server));
    messages.Add(new LogMessage("This is an info", MessageType.Info));
    messages.Add(new LogMessage("This is an error", MessageType.Error));
    messages.Add(new LogMessage("This is a warning", MessageType.Warning));

#endif
}

UserControl 中的 ListView 绑定到 Log

<ListView x:Name="LogView" Grid.Row="0" ItemContainerStyle="{StaticResource LogMessageStyle}" ItemsSource="{Binding Log, ElementName=LogControl}" >

在ListView下方,有一个Checkbox,绑定了一个布尔值,表示是否应该过滤某一行。

<CheckBox IsChecked="{Binding HideServer, ElementName=LogControl}" VerticalAlignment="Center" Width="75">



public bool filterServer(object o)
{
    LogMessage m = o as LogMessage;
    if ((m.MessageType == MessageType.Server) && (hideServer == true))
        return false;
    return true;
}

public bool HideServer
{
    get
    {
        return hideServer;
    }
    set
    {
        hideServer = value;

        if (hideServer)
            Log.Filter = new Predicate<object>(filterServer);
        else
            Log.Filter = null;

        notifyPropertyChanged();
        log.Refresh();
    }
}

选中复选框后,过滤器会正确添加到 ICollectionView,但不会过滤列表框的内容。未调用 filterServer(object o) 函数。这段代码有问题吗?我用调试器单步调试了代​​码,看起来 Log.Refresh() 没有任何效果。

附加信息

PropertyChanged 事件定义为

public event PropertyChangedEventHandler PropertyChanged;

private void notifyPropertyChanged([CallerMemberName] string propertyName = "")
{
    if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

LogMessage 和 MessageType 定义为

public class LogMessage
{
    public DateTime Timestamp { get; private set; }
    public LogFilter.MessageType MessageType { get; private set; }
    public string Message { get; private set; }

    public LogMessage(string Message)
    {
        initalize(DateTime.Now, LogFilter.MessageType.General, Message);
    }

    public LogMessage(string Message, DateTime Timestamp)
    {
        initalize(Timestamp, LogFilter.MessageType.General, Message);
    }

    public LogMessage(string Message, LogFilter.MessageType MessageType)
    {
        initalize(DateTime.Now, MessageType, Message);
    }

    public LogMessage(string Message, DateTime Timestamp, LogFilter.MessageType MessageType)
    {
        initalize(Timestamp, MessageType, Message);
    }

    private void initalize(DateTime timestamp, LogFilter.MessageType messageType, string message)
    {
        Timestamp = timestamp;
        MessageType = messageType;
        Message = message;
    }
}

public enum MessageType
{
    Server,
    Info,
    Warning,
    Error,
    General
}

【问题讨论】:

    标签: c# observablecollection icollectionview


    【解决方案1】:

    我不知道这是否是导致问题的原因,但 CollectionView 类的文档说:

    你不应该在你的代码中创建这个类的对象

    相反,一种可能的解决方案是使用CollectionViewSource.GetDefaultView 获取ICollectionView

    log = CollectionViewSource.GetDefaultView(messages);
    

    注意你不需要暴露Log并绑定到它;您可以绑定到Messages,因为在后台,WPF 将使用集合的默认视图,这与CollectionViewSource.GetDefaultView 返回的相同。

    【讨论】:

    • 太棒了,感谢您的回答。它的工作原理与您所说的完全一样!
    猜你喜欢
    • 2016-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 2013-07-18
    • 2019-07-12
    • 2011-08-07
    • 1970-01-01
    相关资源
    最近更新 更多