我一直在与WPF
和ObservableCollection
作战很长一段时间,现在我需要一些帮助。如何在使用ObservableCollection时停止DataGrid闪烁?
这是
- 使用的MongoDB为依托数据库
- 在数据库中存储的日志数据的海量他们插入到数据库中(实时ish)
- UI DataGrid绑定到
ObservableCollection
- UI DataGrid由于内存使用并且具有数百万条记录,所以是并且必须被分页
- 查看日志时,如果创建并显示新条目,则必须删除一条;这仅仅是因为寻呼和具有一组页面大小(50个日志条目将永远只能在同一时间显示)
- 使用ActiveMQ的时候一个新的日志条目已创建
所以基本上这是信号滚动日志视图,一个入口进入,一个入口出去。我必须保持所选项目并实时显示更新(这就是为什么我使用ObservableCollection
)。日志可以被过滤并且页面可以被导航,所以我认为当有新的日志条目并且显示它时最容易获取整个页面;这也可以让我得到以前可能错过的参赛作品。
我遇到过很多问题,包括在后台线程上更新集合时遇到的问题,最近创建新条目时出现DataGrid
“闪烁”问题。我假设闪烁是由于每次刷新整个集合而引起的,但替代方法(手动添加和删除项目)要复杂得多,并且由于筛选和分页的复杂性,我宁愿不去该路由。
有没有什么好的模式或建议来阻止这种“闪烁”,或者更好的方式来实现实时更新的可过滤日志视图?
的XAML
<DataGrid ItemsSource="{Binding Entries, IsAsync=True}"
AutoGenerateColumns="False" IsReadOnly="True"
CanUserSortColumns="False"
EnableColumnVirtualization="True" EnableRowVirtualization="True"
VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling">
<DataGrid.Columns>
<DataGridTextColumn Header="Timestamp" Binding="{Binding Timestamp}" />
<DataGridTextColumn Header="From" Binding="{Binding MessageFrom}" />
<DataGridTextColumn Header="To" Binding="{Binding MessageTo}" />
<DataGridTextColumn Header="Type" Binding="{Binding MessageType}" />
</DataGrid.Columns>
</DataGrid>
的结合,我已经当我想起更多的事情我已经试过用
//option 1
public ViewModel() { this.Entries = new ObservableCollection<Model>(); }
public void UpdateData()
{
this.Entries.Clear();
foreach (Model m in FetchModels())
this.Entries.Add(m);
}
public ObversableCollection<Model> Entries { get; private set; }
//option 2
private List<Model> m_Entries = new List<Model>();
public void UpdateData()
{
this.m_Entries.Clear();
this.m_Entries.AddRange(FetchModels());
this.NotifyPropertyChanged(() => this.Entries);
}
public ObversableCollection<Model> Entries { get { return new ObservableCollection<Model>(this.m_Entries); } }
//option 3
public ViewModel() { this.Entries = new ObservableCollection<Model>(); }
public void UpdateData()
{
var tmp = this.Entries;
this.Entries = null;
tmp.Clear();
foreach (Model m in FetchModels())
tmp.Add(m);
this.Entries = tmp;
this.NotifyPropertyChanged(() => this.Entries);
}
public ObversableCollection<Model> Entries { get; private set; }
视图模型的代码,我将它张贴。
顺便说一句,因为内置的UI虚拟化,在WPF中可能没有必要使用分页或其他任何非常冒险的技术。 2 - 如果重新绑定整个系列,无论如何都会造成性能损失,请改用单个项目。 – 2014-10-10 20:13:22
@HighCore这是不正确的。如果我从数据库中获取所有600万条记录而不使用查询来限制返回到50条记录的数量,那么客户端的内存用得非常快。即使WPF具有虚拟化功能,它仍然拥有内存中的600万条记录列表;它只是没有在同一时间显示。 – vane 2014-10-10 20:22:07
是的,但是这与UI没有任何关系......如果在控制台应用程序中从数据库中获取6m记录,则会出现同样的问题。我的建议仍然是你应该操纵单个项目,而不是一直重新绑定整个系列。 – 2014-10-10 20:25:09