Фильтр ICollectionView не вызывается

Я создал небольшой пользовательский элемент управления, содержащий 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
}

ListView в UserControl привязан к журналу

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

Ниже ListView находится флажок, привязанный к логическому значению, указывающий, следует ли фильтровать определенную строку.

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

person ChrisK    schedule 12.07.2013    source источник


Ответы (1)


Я не знаю, является ли это причиной проблемы, но в документации класса CollectionView говорится:

Вы не должны создавать объекты этого класса в своем коде

Вместо этого возможное решение — получить ICollectionView с помощью CollectionViewSource.GetDefaultView:

log = CollectionViewSource.GetDefaultView(messages);

Обратите внимание, что вам не нужно открывать Log и привязываться к нему; вы можете выполнить привязку к Messages, потому что за сценой WPF будет использовать для коллекции представление по умолчанию, то же самое, что и CollectionViewSource.GetDefaultView.

person Thomas Levesque    schedule 12.07.2013
comment
Потрясающе, спасибо за ответ. Он работает именно так, как вы сказали! - person ChrisK; 13.07.2013