【发布时间】:2018-02-19 22:21:37
【问题描述】:
SelectedItem 属性绑定未导致其 DataGrid 行在初始加载时突出显示。
我有一个与 SelectedItem 绑定的 DataGrid,直到我再次单击它才突出显示。我认为我有一个操作顺序问题 - 来自所有 ViewModel 代码在视图渲染之前运行的事实。一旦我点击一行(即使是已经在 SelectedAccount 属性中的同一行),它就可以正常工作,但我需要能够突出显示 VM 中的一行。
我可以轻松验证 SelectedAccount 属性不为空,因为还有其他 ViewModel 通过 PubSubEvents 显示它的值。
我已经尝试了几种解决方法,但到目前为止我能够让它工作的唯一方法就是感觉很脏:
using ApplicationName.UI.ViewModels;
public partial class AccountsView : UserControl
{
public AccountsView()
{
InitializeComponent();
Loaded += AccountsView_Loaded;
}
private void AccountsView_Loaded(object sender, RoutedEventArgs e)
{
AccountsViewModel viewModel = (AccountsViewModel)DataContext;
AccountsDataGrid.SelectedItem = viewModel.SelectedAccount;
AccountsDataGrid.Focus();
UpdateLayout();
}
}
我不喜欢这样,因为它会导致OnPropertyChanged 事件触发两次,一次是在视图加载之前,一次是在上述 hack 之后。这会触发 SQL 调用,所以我想避免这种情况。我还认为 MVVM 的目的是将视图与视图模型分离,但也许我并没有像我想象的那样理解这一点。
这是 DataGrid 的 XAML:
<ScrollViewer Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="3"
Margin="5,0">
<DataGrid Name="AccountsDataGrid"
ItemsSource="{Binding Accounts}"
SelectedItem="{Binding SelectedAccount}"
AutoGenerateColumns="False"
CanUserResizeColumns="True"
SelectionMode="Single"
SelectionUnit="FullRow">
<DataGrid.Columns>
<DataGridTextColumn Header="ClinicId"
TextBlock.TextAlignment="Center"
Width="75"
Binding="{Binding ClinicId}" />
<DataGridTextColumn Header="Account#"
Width="75"
Binding="{Binding AccountNumber}"/>
<DataGridTextColumn Header="LastName"
Width="1*"
Binding="{Binding LastName}" />
<DataGridTextColumn Header="FirstName"
Width="1*"
Binding="{Binding FirstName}" />
<DataGridTextColumn Header="Balance"
Width="Auto"
Binding="{Binding Balance}" />
<DataGridTextColumn Header="Follow Up"
Width="100"
Binding="{Binding FollowUpDate}"/>
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
以及 ViewModel 中的初始 Load 方法,这是我要设置突出显示的行的地方。
public void Load()
{
RefreshGrid();
SelectedAccount = Accounts.First();
_accountId = SelectedAccount.Id;
}
编辑
这个问题很微妙,但现在很有意义。
private Account _selectedAccount;
public Account SelectedAccount
{
get => _selectedAccount;
set => SetSelectedAccount(value);
}
private void SetSelectedAccount(Account value)
{
_selectedAccount = value;
OnPropertyChanged("_selectedAccount"); // <= whoops
if (_selectedAccount != null)
OnAccountSelected(
_selectedAccount.PrimaryKeyFields);
}
为私有属性引发此事件没有意义,因为视图无法看到它,并且绑定到 SelectedAccount。将其更改为 OnPropertyChanged("SelectedAccount") 就可以了。
【问题讨论】:
-
你确定只调用 .Focus 还不够吗?如果您的 viewModel 正确实现,则 SelectedItem 绑定应该可以工作。您确定不是“InactiveSelectionHighlight”扰乱了您对突出显示的感知。
-
@user6144226 你是对的。我的 ViewModel 中有一个错误。我为
_selectedAccount而不是SelectedAcount提出OnPropertyChanged。这不起作用的原因现在很明显。我能够从代码隐藏处理程序中删除除Focus()之外的所有内容。一切顺利!
标签: c# wpf mvvm data-binding