如何在MVVM中从ViewModel中选择数据网格中的一行
本文关键字:网格 一行 数据网 数据 MVVM 中从 选择 ViewModel | 更新日期: 2023-09-27 18:05:25
我正在尝试验证数据网格中的用户输入,我这样做的方式是:
I)允许用户添加行
II)允许用户填充一些单元格
当EndEdit()事件发生时,我将更新我的模型IV)如果模型无法更新(例如当用户没有提供时)
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();
}
}
}
当选择正在改变时你不能改变选择…如果有意义的话: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
中传递索引),让视图订阅该事件,并从事件处理程序中触发Dispatcher调用(使用this.Dispatcher
而不是Application.Current.Dispatcher
)。
多亏了@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),当你想改变选定的行:
if (DataGridRowSelectionChange != null)
DataGridRowSelectionChange(this, new EventArg<int>(DesiredIndex));
III)在View构造函数中添加事件处理程序,如下所示:
((YourViewModelClass)DataContext).DataGridRowSelectionChange += CurrentViewModel_DataGridRowSelectionChange_EventHandler;
IV),最后在View中编写处理程序,如下所示:
void CurrentViewModel_DataGridRowSelectionChange_EventHandler(object sender, EventArg<int> e)
{
Dispatcher.BeginInvoke(new Action(() => GRIDNAME.SelectedIndex = e.EventData));
}
就这些了:)