سؤال

I created a small User Control, that contains a ICollectionView and a ObservableCollection.

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

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

The variables are set in the constructor of the 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
}

A ListView in the UserControl is bound to the Log

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

Below the ListView, there is a Checkbox that is bound to a Boolean value, indicating if a certain row should be filtered.

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

Upon checking the Checkbox, the Filter is added properly to the ICollectionView, however the contents of the Listbox are not filtered. The filterServer(object o) function is not called. Is there an issue with this code? I stepped through the code with the debugger and it seems like Log.Refresh() has no effect.

Additional information

The PropertyChanged Event is defined as

public event PropertyChangedEventHandler PropertyChanged;

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

The LogMessage and the MessageType are defined as

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
}
هل كانت مفيدة؟

المحلول

I don't know if this is what's causing the problem, but the documentation of the CollectionView class says:

You should not create objects of this class in your code

Instead, a possible solution is to obtain a ICollectionView using CollectionViewSource.GetDefaultView:

log = CollectionViewSource.GetDefaultView(messages);

Note that you don't need to expose Log and bind to it; you can bind to Messages, because behind the scene, WPF will use the default view for the collection, which is the same that is returned by CollectionViewSource.GetDefaultView.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top