限制ObservableCollection中条目的数量的.NET C#方法

7
我有一个WPF应用程序,其中UI有一个列表框。列表框具有ObservableCollection的绑定。Log类实现了INotifyPropertyChanged。
这个列表将显示应用程序的连续日志记录。只要应用程序运行,ObservableCollection的大小就会不断增长。过一段时间后,我会收到内存溢出异常。我想在列表控件中显示最新的1000条条目。对此的任何建议都将非常有帮助!
XAML:
                    <DataGrid AutoGenerateColumns="False" SelectedValue="{Binding SelectedLog}" SelectionUnit="FullRow" SelectionMode="Single" Name="dataGridLogs" 
                      ItemsSource="{Binding Path=LogList}"  CanUserReorderColumns="True" CanUserResizeRows="True" CanUserDeleteRows="False"  IsReadOnly="True"
                      CanUserAddRows="False" EnableColumnVirtualization="True" EnableRowVirtualization="True" SelectionChanged="grid_SelectionChanged"> 
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Time Stamp" Binding="{Binding StrTimeStamp, Mode=OneWay}" Width="Auto"/>
                    <DataGridTextColumn Header="Action" Binding="{Binding Action, Mode=OneWay}" Width="Auto"/>

            </DataGrid>

视图模型:

    public ObservableCollection<LogData> LogList
    {
        get
        {
            if (logList == null)
            {
                logList = new ObservableCollection<LogData>();
            }
            return logList;
        }
        set
        {
            logList = value;
            OnPropertyChanged("LogList");
        }
    }

模型:

     public class LogData : INotifyPropertyChanged
{
    public LogData()
    {
    }
    private String timestamp = string.Empty;
    public String StrTimestamp
    {
        get
        {
            if (timestamp == null)
                return string.Empty;
            return timestamp ;
        }
        set
        {

            timestamp = value;
        }
    }
    public string Action
    {
       get;set;
    }

}


可能会绑定到“CollectionChanged”事件并丢弃除最近的1000个之外的任何项。 - BurnsBA
4个回答

3
您可以创建自己的大小受限的可观察集合类。以下代码可以帮助您入门:
```

您可以创建自己的大小受限的可观察集合类。以下代码可以帮助您入门:

```
public class LimitedSizeObservableCollection<T> : INotifyCollectionChanged
{        
    private ObservableCollection<T> _collection;
    private bool _ignoreChange;

    public LimitedSizeObservableCollection(int capacity)
    {
        Capacity = capacity;
        _ignoreChange = false;
        _collection = new ObservableCollection<T>();
        _collection.CollectionChanged += _collection_CollectionChanged;
    }

    public event NotifyCollectionChangedEventHandler CollectionChanged;

    public int Capacity {get;}

    public void Add(T item)
    {
        if(_collection.Count = Capacity)
        {
            _ignoreChange = true;
            _collection.RemoveAt(0);
            _ignoreChange = false;
        }
        _collection.Add(item);

    }

    private void _collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if(!_ignoreChange)
        {
            CollectionChanged?.Invoke(this, e);
        }
    }
}

当然,您可能需要暴露更多的方法,但我希望这足以让您了解其中的思想。

经过轻微的修改,我成功让它工作了!感谢您的建议。 - user1097482
很高兴能帮忙 :-) - Zohar Peled

3

使用这个类可以轻松完成:

public class LimitedSizeObservableCollection<T> : ObservableCollection<T>
{
    public int Capacity { get; }

    public LimitedSizeObservableCollection(int capacity)
    {
        Capacity = capacity;
    }

    public new void Add(T item)
    {
        if (Count >= Capacity)
        {
            this.RemoveAt(0);
        }
        base.Add(item);
    }
}

这不符合预期 - 尝试在已满的此类型集合上使用“插入”方法,你就会知道原因。实际上,这应该是“InsertItem”方法的重写(无论如何,“Add”内部都会调用它)。我试图将其放入编辑中,但显然拥有实际实现其预期功能的类并不是您帖子的原始意图? - IAmJersh

1
我找到了另一种限制集合中元素数量的方法,而不需要添加一个“新的”方法来破坏与父类的兼容性:
public class LimitedSizeObservableCollection<T> : ObservableCollection<T>
{
    public int Capacity { get; set; } = 0;

    protected override void InsertItem(int index, T item)
    {
        if (this.Capacity > 0 && this.Count >= this.Capacity)
        {
            throw new Exception(string.Format("The maximum number of items in the list  ({0}) has been reached, unable to add further items", this.Capacity));
        }
        else
        {
            base.InsertItem(index, item);
        }
    }
}

0
如果您想让它不要添加到集合中超过1000个,可以这样做。
public ObservableCollection<LogData> LogList
{
    get
    {
        if (logList == null)
        {
            logList = new ObservableCollection<LogData>();
        }
        return logList;
    }
    set
    {
        if(LogList.Count < 1001)
        {
          logList = value;
          OnPropertyChanged("LogList");
        }
    }
}

或者当添加新的超过1000个时,您可以删除旧条目

public ObservableCollection<LogData> LogList
{
    get
    {
        if (logList == null)
        {
            logList = new ObservableCollection<LogData>();
        }
        return logList;
    }
    set
    {
        if(LogList.Count < 1001)
        {
          logList = value;
          OnPropertyChanged("LogList");
        }
        else 
        {
           LogList.RemoveAt(0);
           logList = value;
           OnPropertyChanged("LogList");
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接