我无法得到DataGrid分组的错误。
我有一个像这样的最小应用程序:
<Window x:Class="dggrouping_test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:dggrouping_test"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid x:Name="dataGrid">
<DataGrid.GroupStyle>
<x:Static Member="GroupStyle.Default"/>
</DataGrid.GroupStyle>
</DataGrid>
</Grid>
和XAML吧:
<div id="particles-js"></div>
<div class="text">
<h1>Particles Background</h1>
</div>
当我编译并运行它时,应用程序在3000行上消耗大约550 MB的内存(!!!)。加载需要几秒钟。如果我只是评论dataView.GroupDescriptions.Add(...)并再次运行 - 内存使用量下降到85 MB。因此,在最小的示例中,每3000行消耗450 MB。我做错了什么?
答案 0 :(得分:1)
还有一个答案。
<强>设计强>
3000行不少量。我的拇指是100个字段/信息的东西是你应该向用户显示的限制。每行需要的字段越多,你应该显示的行数就越少(低至5-10)他甚至无法处理的任何内容。
在查询期间尽可能多地进行过滤。如果您的DBMS支持分页,也可以使用它。检索所有内容是常见的错误,然后在GUI中进行过滤。 3000看起来很明显。
UI Virtualsiation
XAML在设计时考虑了很多UI Virtualsition Support。问题是,只有当它被打开并且你暴露正确的东西才能工作
绑定垃圾邮件
UI更新成本很高。如果每个用户触发的事件只执行一次,则不会产生任何影响。但如果它是从任何形式的循环运行它会成为一个问题。我为这个问题写了一些示例代码:
using System;
using System.Windows.Forms;
namespace UIWriteOverhead
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int[] getNumbers(int upperLimit)
{
int[] ReturnValue = new int[upperLimit];
for (int i = 0; i < ReturnValue.Length; i++)
ReturnValue[i] = i;
return ReturnValue;
}
void printWithBuffer(int[] Values)
{
textBox1.Text = "";
string buffer = "";
foreach (int Number in Values)
buffer += Number.ToString() + Environment.NewLine;
textBox1.Text = buffer;
}
void printDirectly(int[] Values){
textBox1.Text = "";
foreach (int Number in Values)
textBox1.Text += Number.ToString() + Environment.NewLine;
}
private void btnPrintBuffer_Click(object sender, EventArgs e)
{
MessageBox.Show("Generating Numbers");
int[] temp = getNumbers(10000);
MessageBox.Show("Printing with buffer");
printWithBuffer(temp);
MessageBox.Show("Printing done");
}
private void btnPrintDirect_Click(object sender, EventArgs e)
{
MessageBox.Show("Generating Numbers");
int[] temp = getNumbers(1000);
MessageBox.Show("Printing directly");
printDirectly(temp);
MessageBox.Show("Printing done");
}
}
}
现在很少有东西会导致UI更新和过多的更改通知一样多。在完成这样的处理工作时,为UI移除一个Collection可能是有益的,一旦完成就重新绑定它。
一般模式
XAML和WPF / UWP的设计考虑了MVVM模式。虽然您可以使用其他方法,但您错过了大约90%的功率,并且每隔一步就会遇到问题。您的代码对我来说看起来不像是一个合适的MVVM模式(Window中的初始化代码将其丢弃;因为缺少使用CollectionView进行排序/过滤部分)。
如果您遵循该模式,那么您所遇到的问题将永远不会存在。无论哪种情况,如果您打算在XAML中做任何认真的工作,都值得学习。几年前我写了MVVM介绍:https://social.msdn.microsoft.com/Forums/vstudio/en-US/b1a8bf14-4acd-4d77-9df8-bdb95b02dbe2/lets-talk-about-mvvm?forum=wpf
内存问题?
虽然速度问题是真实的,但内存问题并非毫无疑问。 mix up the measurement很容易。
很多人都误解了垃圾收集器在设计上非常懒惰。如果它只在应用程序关闭时收集一次,那么这是理想的情况。因此,存储器使用可以在没有任何问题的情况下增加。您可以通过调用GC.Collect()进行测试来检查是否存在内存泄漏。但是在生命应用程序中它不应该出现(选择适当的GC策略)。 https://social.msdn.microsoft.com/Forums/en-US/286d8c7f-87ca-46b9-9608-2b559d7dc79f/garbage-collection-pros-and-limits?forum=csharpgeneral
答案 1 :(得分:1)
解决了VirtualizingPanel.IsVirtualizingWhenGrouping附加财产的问题。它适用于.NET 4.5及更高版本。
<DataGrid x:Name="dataGrid" VirtualizingPanel.IsVirtualizingWhenGrouping="True">
<!-...-->
</DataGrid>