【发布时间】:2017-04-15 08:37:07
【问题描述】:
问题摘要:XAML 中是否有办法确保我的 DataGrid 组件在启动对 SelectedIndex 属性的绑定之前已完全加载?
我的 ViewModel 是这样设置的。我正在使用 MVVM-light 来通知视图的更改。每当它从服务器更新时,我都会将新模型传递给SetData()。
public class MyViewModel : ViewModelBase
{
public void SetData(DataModel model)
{
Data = model.Data; //Array of 75 DataObjects
DataIndex = model.Index; //int between 0 and 74
}
// Array to Bind to Datagrid ItemsSource
public DataObject[] Data
{
get { return _data; }
private set
{
if (_data!= value)
{
_data= value;
RaisePropertyChanged("Data");
}
}
}
private DataObject[] _data;
// Int to Bind to Datagrid SelectedIndex
public int DataIndex
{
get { return _index; }
private set
{
if (_index != value)
{
_index = value;
RaisePropertyChanged("DataIndex");
}
}
}
private int _index;
}
视图如下所示:
<Application.Resources>
<ResourceDictionary>
<core:ViewModelLocator x:Key="Locator" />
</ResourceDictionary>
</Application.Resources>
<DataGrid ItemsSource="{Binding MyViewModel.Data, Source={StaticResource Locator}}"
SelectedIndex="{Binding MyViewModel.DataIndex, Source={StaticResource Locator}, Mode=OneWay}"
AutoGenerateColumns="True"/>
我的问题是我的 DataGrid 上没有选择任何行。所有数据都正确显示在网格中,但未选择行。我检查了属性并确认数组长度为 75,DataIndex 是 0 到 74 之间的 int。
原因似乎是因为在设置绑定时 DataGrid 尚未完成加载。我可以通过在组件加载后初始化绑定来证明这一点。在这种情况下,一切都按预期工作,并且我选择的项目正确显示:
<DataGrid x:Name="MyDataGrid" Loaded="OnDataGridLoaded"
ItemsSource="{Binding MyViewModel.Data, Source={StaticResource Locator}}"
AutoGenerateColumns="True"/>
private void OnDataGridLoaded(object sender, RoutedEventArgs e)
{
Binding b = new Binding("DataIndex");
b.Source = Locator.MyViewModel.Data;
MyDataGrid.SetBinding(DataGrid.SelectedIndexProperty, b);
}
我不想这样做,因为,你知道,代码隐藏。那么有没有办法只使用 XAML 来解决这个问题?这是我迄今为止尝试过的(没有一个对我有用):
- 将 SelectedIndex 绑定到我的 ViewModel 上的
int属性(如上所示) - 将 SelectedItem 绑定到我的 ViewModel 上的
DataObject属性(结果相同) - 将 SelectedValue 和 SelectedPath 绑定到我的
DataObject的属性(这实际上有效,仅适用于第一个实例。问题是我有这个 Datagrid 组件的多个实例,出于某种原因,这只适用于第一个实例) - 绑定到 ObservableCollection 而不是 Array(使用 ObservableCollection 尝试了上述所有 3 种方法,并且每种方法都获得了相同的结果)
- 通过将更改通知包装在对
Dispatcher.Invoke的调用中来延迟更改通知。这无济于事,因为该组件并未立即显示在视图中。 - 在 XAML 中创建绑定,然后在 Loaded 函数中更新目标。
MyDataGrid.GetBindingExpression(DataGrid.SelectedIndexProperty).UpdateTarget();
【问题讨论】:
-
@Clemens 谢谢,注意到了。这段代码是我实际程序的浓缩摘要,其中 DataGrid 的源是一个单独的对象,而不是 UserControl 的 DataContext。但无论如何,所有优点。
-
你为什么不在
Window.Loaded事件上第一次打电话给setData。 -
@EdPlunkett 抱歉,我忘了在这段代码中包含它。但是,是的,我已将绑定设置为一种方式
-
@esiprogrammer 我不确定你的意思,但让我澄清一下。我有多个组件实例,默认情况下所有这些实例都不在视图中。一旦用户按下按钮,就会创建组件并用数据填充网格。换句话说,数据在显示在组件中之前就已经提前存储好了。
-
我猜问题可能出在视图的设置
DataContext上。这就是为什么你提供的代码隐藏工作。你在哪里设置DataContext?
标签: c# wpf xaml data-binding wpfdatagrid