【问题标题】:How to select a row in datagrid from ViewModel in MVVM?如何从 MVVM 中的 ViewModel 中选择数据网格中的一行?
【发布时间】:2015-07-30 07:34:26
【问题描述】:

我正在尝试验证数据网格中的用户输入,我这样做的方式是:

I) 允许用户添加一行

II) 允许用户填充一些单元格

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

IV) 如果模型无法更新(例如当用户没有提供 NotNull 值),则会引发错误。

V) 这是棘手的部分!我想留在数据网格的错误行上,但是尽管我已经正确设置了 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();
            }
        }
    }

【问题讨论】:

标签: c# wpf xaml mvvm datagrid


【解决方案1】:

在选择更改时无法更改选择......如果有任何意义:p

如果选择刚刚更改,您必须等到可以再次以编程方式更改它。这通常使用Dispatcher.BeginInvoke 将您的调用添加到 Dispatcher 队列来完成,因此它会在处理当前选择后执行。

if (AContact.cnt_Key == 0)
{
    FSelectedContact = InvalidList[0];
    NotifyPropertyChanged();

    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
        SelectedItemIndex = BastardIndex));
}
BastardIndex++;

在您的视图模型中执行此操作并不是最好的解决方案 - MVVM 方面或在多个 UI 线程场景中。您可以简单地在该行中引发一个事件(在EventArgs 中传递索引),让您的视图订阅该事件,然后从事件处理程序中触发调度程序调用(使用this.Dispatcher 而不是Application.Current.Dispatcher)。

【讨论】:

  • Application.Current.Daspatcher 不起作用(我不知道为什么),但由于正确的方法,正如你提到的,是使用事件,我实现了事件和相应的处理程序,它工作正常。谢谢:)
【解决方案2】:

感谢@almulo,我在 ViewModel 中实现了一个事件,并在 View 中实现了相应的处理程序,它就像一个魅力,对于任何可能需要帮助的人来说,这些是步骤:

I) 在 ViewModel 中添加一个事件,如下所示:

public event EventHandler<EventArg<int>> DataGridRowSelectionChange;

*请注意,EventArg 只是一个简单的类,它可以保存 T 类型的值,如下所示:

    public class EventArg<T> : EventArgs
{
    private T FEventData;

    public EventArg(T Param)
    {
        // TODO: Complete member initialization
        FEventData = Param;
    }

    public T EventData
    {
        get { return FEventData; }
        set { FEventData = value; }
    }
}

II) 在 ViewModel 中随时更改所选行

if (DataGridRowSelectionChange != null)
     DataGridRowSelectionChange(this, new EventArg<int>(DesiredIndex));

III) 在 View 构造函数中添加事件处理程序,如下所示:

((YourViewModelClass)DataContext).DataGridRowSelectionChange += CurrentViewModel_DataGridRowSelectionChange_EventHandler;

IV) 最后在视图中编写处理程序,如下所示:

void CurrentViewModel_DataGridRowSelectionChange_EventHandler(object sender, EventArg<int> e)
    {
       Dispatcher.BeginInvoke(new Action(() => GRIDNAME.SelectedIndex = e.EventData));
    }

仅此而已:)

【讨论】:

    猜你喜欢
    • 2023-03-16
    • 2015-04-12
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 2012-10-08
    • 1970-01-01
    相关资源
    最近更新 更多