C# 如何从MVVM中的ViewModel中选择datagrid中的行?
我正在尝试验证datagrid中的用户输入,我这样做的方式如下: 一) 允许用户添加行 二) 允许用户填充某些单元格 三) 当EndEdit()事件发生时,我会更新我的模型 四) 如果模型无法更新(例如,当用户未提供 NotNull值),将引发错误 五) 这里是棘手的部分!我想停留在datagrid的错误行上,但尽管我已正确设置SelectedIndex和SelectedValue,但高亮显示的行仍将更改 这是我的XAML:C# 如何从MVVM中的ViewModel中选择datagrid中的行?,c#,wpf,xaml,mvvm,datagrid,C#,Wpf,Xaml,Mvvm,Datagrid,我正在尝试验证datagrid中的用户输入,我这样做的方式如下: 一) 允许用户添加行 二) 允许用户填充某些单元格 三) 当EndEdit()事件发生时,我会更新我的模型 四) 如果模型无法更新(例如,当用户未提供 NotNull值),将引发错误 五) 这里是棘手的部分!我想停留在datagrid的错误行上,但尽管我已正确设置SelectedIndex和SelectedValue,但高亮显示的行仍将更改 这是我的XAML: <DataGrid x:Name="gd_Contacts" S
<DataGrid x:Name="gd_Contacts" SelectedItem="{Binding SelectedContact,Converter={StaticResource NewPlaceConverter}}"
SelectedIndex="{Binding SelectedItemIndex}"
Margin="0,5,1,0" ItemsSource="{Binding ContactCollection, Mode=TwoWay}"
CanUserAddRows="True" CanUserDeleteRows="False" AutoGenerateColumns="False" Grid.Column="1">
这是我的ViewModel:
private ObservableCollection<ActionEnabledContacts> FContactCollection;
//....
public ActionEnabledContacts SelectedContact //THE PROPERTY FOR SELECTEDITEM
{
get { return FSelectedContact; }
set
{
//
List <ActionEnabledContacts> InvalidList=ContactCollection.Where<ActionEnabledContacts>(p => p.cnt_Key == 0).ToList();
if (InvalidList != null && InvalidList.Count > 0)
{
//now find index of that bastard
List<ActionEnabledContacts> AllContacts = ContactCollection.ToList();
int BastardIndex = 0;
foreach (ActionEnabledContacts AContact in AllContacts)
{
if (AContact.cnt_Key == 0)
{
FSelectedContact = InvalidList[0];
NotifyPropertyChanged();
SelectedItemIndex = BastardIndex;
//^^^^ THIS LINE DO UPDATE SELECTEDINDEX AND CALL NotifyPropertyChanged()
}
BastardIndex++;
}
}
else
{
//
FSelectedContact = value;
NotifyPropertyChanged();
}
}
}
private observeCollection FContactCollection;
//....
公共操作启用的联系人SelectedContact//SELECTEDITEM的属性
{
获取{return FSelectedContact;}
设置
{
//
List InvalidList=ContactCollection.Where(p=>p.cnt_Key==0.ToList();
if(InvalidList!=null&&InvalidList.Count>0)
{
//现在找到那个混蛋的索引
List AllContacts=ContactCollection.ToList();
int-BastardIndex=0;
foreach(ActionEnabledContacts在所有联系人中的联系人)
{
if(AContact.cnt_Key==0)
{
FSelectedContact=无效列表[0];
NotifyPropertyChanged();
SelectedItemIndex=BastardIndex;
//^^^^此行不更新SELECTEDINDEX并调用NotifyPropertyChanged()
}
BastardIndex++;
}
}
其他的
{
//
FSelectedContact=值;
NotifyPropertyChanged();
}
}
}
选择正在更改时,无法更改选择。。。如果这有意义的话:P
如果选择刚刚更改,则必须等待,直到可以再次以编程方式更改它。通常可以使用Dispatcher.BeginInvoke
将您的呼叫添加到Dispatcher队列,这样它会在处理当前选择后执行
if (AContact.cnt_Key == 0)
{
FSelectedContact = InvalidList[0];
NotifyPropertyChanged();
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
SelectedItemIndex = BastardIndex));
}
BastardIndex++;
在viewmodel中执行此操作并不是最好的解决方案,尽管在MVVM方面或在多UI线程场景中。您只需在该行中引发一个事件(传递
EventArgs
内的索引),让视图订阅该事件,并从事件处理程序(使用this.Dispatcher
而不是Application.Current.Dispatcher
)触发Dispatcher调用即可,我已经在ViewModel中实现了一个事件,并在View中实现了相应的处理程序,它就像一个符咒,对于任何需要帮助的人来说,以下是步骤:
I)在ViewModel中添加如下事件:
public event EventHandler<EventArg<int>> DataGridRowSelectionChange;
((YourViewModelClass)DataContext).DataGridRowSelectionChange += CurrentViewModel_DataGridRowSelectionChange_EventHandler;
void CurrentViewModel_DataGridRowSelectionChange_EventHandler(object sender, EventArg<int> e)
{
Dispatcher.BeginInvoke(new Action(() => GRIDNAME.SelectedIndex = e.EventData));
}
IV),最后在视图中编写处理程序,如下所示:
public event EventHandler<EventArg<int>> DataGridRowSelectionChange;
((YourViewModelClass)DataContext).DataGridRowSelectionChange += CurrentViewModel_DataGridRowSelectionChange_EventHandler;
void CurrentViewModel_DataGridRowSelectionChange_EventHandler(object sender, EventArg<int> e)
{
Dispatcher.BeginInvoke(new Action(() => GRIDNAME.SelectedIndex = e.EventData));
}
void CurrentViewModel\u DataGridRowSelectionChange\u事件处理程序(对象发送方,事件参数e)
{
Dispatcher.BeginInvoke(新操作(()=>GRIDNAME.SelectedIndex=e.EventData));
}
仅此而已:)要实现此行为,请尝试通过以下链接设置Dispatcher.Invokego的SelectEditedIndex属性:
Application.Current.Daspatcher
不起作用(我不知道为什么),但正如您所提到的,正确的方法是使用事件,因此我实现了事件和相应的处理程序,效果很好。谢谢:)