C# 如何从MVVM中的ViewModel中选择datagrid中的行?

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中的用户输入,我这样做的方式如下:

一) 允许用户添加行

二) 允许用户填充某些单元格

三) 当EndEdit()事件发生时,我会更新我的模型

四) 如果模型无法更新(例如,当用户未提供 NotNull值),将引发错误

五) 这里是棘手的部分!我想停留在datagrid的错误行上,但尽管我已正确设置SelectedIndex和SelectedValue,但高亮显示的行仍将更改

这是我的XAML:

<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
不起作用(我不知道为什么),但正如您所提到的,正确的方法是使用事件,因此我实现了事件和相应的处理程序,效果很好。谢谢:)