2013-11-25 35 views
6

新行添加到數據網格,我有以下DataGrid如何MVVM友好的方式

<DataGrid CanUserDeleteRows="True" 
      CanUserAddRows="True" 
      SelectedItem="{Binding SelectedResource, Mode=TwoWay}" 
      ItemsSource="{Binding Path=Resources, Mode=TwoWay, 
           UpdateSourceTrigger=PropertyChanged, 
           IsAsync=True}"> ... </<DataGrid> 

我使用MVVM模式綁定到ObservableCollection<ResourceViewModel> Resources來完成這項工程。我有一個按鈕添加了一個新的行,這是通過在Resources集合中添加一個新的ResourceViewModel完成的 - 很好。現在,我希望用戶能夠點擊空的最後一行,並自動在DataGrid中創建新記錄。

我已確認DataGridCanUserAddRows=True。我已經確定我綁定的集合ResourcesResourceViewModel)中的類具有默認構造函數(無參數),並且確保集合類型不是隻讀的。當用戶點擊最後一行默認的構造函數的火災,但正確實例化需要新的ResourceViewModel對象的Resources收集的任何電網的參考...

我想我可以使用和AttachedCommandCellBeginEdit事件然後在那裏添加新的ResourceViewModel到可觀察的集合,有沒有這樣做的標準方法?


注意,我已經閱讀了以下問題,這些都無助於我

  1. WPF DataGrid - Event for New Rows?
  2. How to add rows with a DataGrid and MVVM

編輯。事實證明,由於WPF DataGrid中的一個錯誤,我遇到了問題。請參閱Nigel Spencer's Blog。然而,他的修復程序目前不適用於我...

+0

+1好問題。 – Sheridan

+0

Nigel Spencer博客文章的更新鏈接是[使用WPF DataGrid綁定到SelectedValue的問題](http://blogs.spencen.com/?p=611) – Tone

回答

3

據我所知,您知道如何正確添加新項目到您的數據綁定集合中,以導致將新項目添加到DataGrid以及您的問題實際上與您在用戶點擊DataGrid中的最後一行時如何執行此操作有關。在視圖模型中處理某個事件的一般方法是創建一個Attached Property(如果尚不存在的話)爲您處理該事件。

例如,您可以創建一個將處理程序附加到相關事件的Attached Property,以及在調用事件處理程序時可以執行的另一個類型ICommand。然後你可以在你的視圖模型中寫入ICommand的功能(在其中你添加一個新項目到你的數據綁定集合),並且數據綁定你的Attached ICommand Property實現。

因爲我相當確定您知道如何定義Attached Property s,我不會通過向您顯示來侮辱您。如果我誤解了你,或者沒有明確表示,請告訴我。

+1

感謝您的回覆。問題是我設置了一個附加的命令來觸發'InitializingNewItem'事件。當我將DataGrid的最後一行放入編輯模式時,以及在網格嘗試創建新項目之前,這會觸發。在這裏,我可以添加新項目,但DataGrid繼續嘗試使用默認構造函數實例化項目本身。我不能停止網格自動執行此操作,因爲我可以使用該命令和事件來執行我想要的操作... – MoonKnight

+0

因此,我想這個問題變成了,做到這一點的最佳方式是什麼; A.添加新行後取消事件(如何,我不知道)。 B.讓網格自己做這件事 - 但那麼如何讓對象在默認ctor中正確初始化?有沒有這樣做的標準方式? – MoonKnight

+0

我很少使用這些控件,所以不幸的是,我並沒有真正有能力提供關於它們的高級建議。祝你的問題好運。 – Sheridan

1

這裏有一個附加屬性,對於添加行(假定源集合包含泛型類型參數)註冊了一個命令:

public static readonly DependencyProperty RegisterAddCommandProperty = DependencyProperty.RegisterAttached("RegisterAddCommand", typeof(bool), typeof(DataGridExtensions), new PropertyMetadata(false, OnRegisterAddCommandChanged)); 
public static bool GetRegisterAddCommand(DependencyObject obj) 
{ 
    return (bool)obj.GetValue(RegisterAddCommandProperty); 
} 
public static void SetRegisterAddCommand(DependencyObject obj, bool value) 
{ 
    obj.SetValue(RegisterAddCommandProperty, value); 
} 
static void OnRegisterAddCommandChanged(object sender, DependencyPropertyChangedEventArgs e) 
{ 
    if (sender is DataGrid) 
    { 
     var DataGrid = sender as DataGrid; 
     if ((bool)e.NewValue) 
      DataGrid.CommandBindings.Add(new CommandBinding(AddCommand, AddCommand_Executed, AddCommand_CanExecute)); 
    } 
} 

public static readonly RoutedUICommand AddCommand = new RoutedUICommand("AddCommand", "AddCommand", typeof(DataGridExtensions)); 
static void AddCommand_Executed(object sender, ExecutedRoutedEventArgs e) 
{ 
    var DataGrid = sender as DataGrid; 

    var ItemsSourceType = DataGrid.ItemsSource.GetType(); 
    var ItemType = ItemsSourceType.GetGenericArguments().Single(); 

    DataGrid.Items.Add(Activator.CreateInstance(ItemType)); 
} 
static void AddCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
{ 
    e.CanExecute = (sender as DataGrid).CanUserAddRows; 
} 

然後你就可以某處申請命令按鈕這樣的:

<Button Command="{x:Static Extensions:DataGridExtensions.AddCommand}"/> 

不要忘記指定命令目標。

相關問題