簡體   English   中英

如何從MVVM中的ViewModel中選擇數據網格中的行?

[英]How to select a row in datagrid from ViewModel in MVVM?

我正在嘗試驗證數據網格中的用戶輸入,我這樣做的方式如下:

I)允許用戶添加一行

II)允許用戶填寫一些單元格

III)當EndEdit()事件發生時,我會更新我的模型

IV)如果模型無法更新(例如,當用戶未提供NotNull值時),則會引發錯誤。

V)這里是特技部分! 我想留在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();
            }
        }
    }

當選擇發生變化時,您無法更改選擇...如果有任何意義: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 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)每當您想要更改所選行時,在ViewModel中

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));
    }

就這樣 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM