.net c#限制observablecollection中的条目数

时间:2018-05-01 18:10:18

标签: c# data-binding observablecollection

我有一个WPF应用程序,其中UI有一个列表框。列表框具有ObservableCollection的绑定。 Log类实现了INotifyPropertyChanged。

该列表将显示应用程序的连续日志记录。只要应用程序正在运行。 ObservableCollection大小不断增长。一段时间后,我得到Out of Memory异常。我想在列表控件中显示最新的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;
    }

}

4 个答案:

答案 0 :(得分:1)

您可以创建自己的大小有限的可观察集合类。这样的事情应该让你开始:

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

当然,您可能需要提供更多方法,但我希望您能够获得这个想法。

答案 1 :(得分: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");
        }
    }
}

答案 2 :(得分:0)

可以通过此类轻松完成:

try (Connection connection = DriverManager.getConnection(jdbcUrl, username, passwd)) {
    if (connection != null) {
        for (String sqlFile : sqlFiles) {
            Statement statement = connection.createStatement();
            List<String> sqls = readFile(sqlFile);
            for (String sql : sqls) {
                statement.executeUpdate(sql);
            }
        }
    }
} catch (SQLException ex) {
}

// readFile(String fileName) returns the list of queries separated by "/" for .plsql and ";" for .sql files


答案 3 :(得分:0)

我找到了另一种方法来限制集合中元素的数量,而无需添加“新”方法来破坏与父类的兼容性:

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