我们目前有DataGrid
绑定到DataTable
。它还有一个模板列,其中包含CheckBox
,我们以编程方式添加它。此列的目的是跟踪DataGrid
中的多个选择。
工厂用于为每行创建CheckBox
es。
有相当多的记录,因此行虚拟化设置为true,以便性能可以接受。然而,我们看到一个奇怪的问题,如果我们在前10行检查一些CheckBox
然后向下滚动大约50行(网格在任何时候都有大约10行可见),那么有一堆似乎随机检查的其他CheckBox
个。
如果我们禁用行虚拟化,则此问题不存在(但性能非常糟糕)。有没有办法解决?谁知道我们可能做错了什么?
答案 0 :(得分:25)
如果您正在寻找速度ListView Gridview要快得多(并且功能较少)。
尝试禁用容器回收。
<tk:DataGrid x:Name="dataGrid"
ItemsSource="{Binding Path=Bookings}"
AutoGenerateColumns="False"
EnableRowVirtualization="True"
EnableColumnVirtualization="True"
VirtualizingStackPanel.VirtualizationMode="Standard"
VirtualizingStackPanel.IsVirtualizing="True">
答案 1 :(得分:4)
如果您打开虚拟化因为数据网格加载时间很糟糕,那么,这是解决方案:
让我们假设/将您的datagrid项目源绑定称为“Rows”,
public IEnumerable<Row> Rows {get; set;}
在“Row”类IsVisible中添加一个属性,并在想要加载数据时切换它(不是在UI线程决定解析绑定并加载每个控件时)
这个工作的原因,是因为当你加载网格时,它检查绑定,所有行都是不可见的,所以UI线程不必旋转你所有的行*列来创建它们,它可以去接下来需要做的事情。另一方面,您可以检测何时是方便的时间将这些行转换为可见,当View.Visibility可见时,ViewModel从某处加载数据等等。因此您完全可以控制。下面我使用任务(在后台线程中)迭代我的项目源(行),但在UI线程上设置可见性。
private _isVisible = false;
/// <summary>
/// is false by default, for performance when loading first time.
/// </summary>
public bool IsVisible
{
get { return _isVisible; }
set
{
if (_isVisible == value)
return;
_isVisible = value;
RaisePropertyChanged(() => IsVisible);
}
}
在视图中,当加载数据网格时,不允许它通过将行的迭代放在后台线程中来占用UI线程,然后将“可见性”设置为true。即使您在后台线程上,IsVisible属性也会更改,但会触发您更新。
private void OnGridLoaded(object sender, RoutedEventArgs e)
{
//sample bool checks, you might not need them...
if (firstTimeLoad && !_isDataGridLoaded)
{
Task.Factory
.StartNew(() =>
{
/*first time loading performance tweak*/
foreach (var row in _viewModel.Rows)
ExeOnUi(() => { row.IsVisible = true; });
_firstTimeLoad = false;
})
}
忘了添加ExeOnUi代码(您可以使用其他东西检查访问权限,例如whateverControl.Dispatcher.CheckAccess,我只使用Microsoft.Practices.ServiceLocator):
static void ExeOnUi (Action action)
{
var srv= ServiceLocator.Current.GetInstance<IDispatchService> ();
if (srv.CheckAccess ())
action.Invoke ();
else
srv.Invoke (action);
}
答案 2 :(得分:1)
我遇到了类似的问题,并在将UpdateSourceTrigger=PropertyChanged
添加到绑定后解决了问题。
<DataGridTemplateColumn Header="Visible">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsShown,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>