2013-11-25 3 views
6

У меня есть следующая DataGridКак добавить новую строку в 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 и это прекрасно работает. У меня есть кнопка, которая добавляет новую строку, и это делается путем добавления нового ResourceViewModel в коллекцию Resources - отлично. Теперь я хочу, чтобы пользователь мог нажимать на пустую последнюю строку, и это автоматически создает новую запись в DataGrid.

Я убедился, что DataGrid имеет CanUserAddRows=True. Я убедился, что класс в коллекции Resources (ResourceViewModel), к которому я привязываюсь, имеет конструктор по умолчанию (без параметров), и я убедился, что тип коллекции не является readonly. Когда пользователь нажимает на последнюю строку пожары конструктора по умолчанию, но чтобы правильно создать экземпляр новые ResourceViewModel объекта в необходимости ссылки на любую сетку Resources коллекции ...

Я полагаю, я мог бы использовать и AttachedCommand на CellBeginEdit событии а затем добавить новый ResourceViewModel в наблюдаемую коллекцию там, есть стандартный способ сделать это?


Заметь, я прочитал следующие вопросы и это не поможет мне

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

Edit. Оказывается, у меня возникают проблемы с этим из-за ошибки в WPF DataGrid. См. Nigel Spencer's Blog. Однако его исправление сейчас не работает для меня ...

+0

+1 хороший вопрос. – Sheridan

+0

Обновленная ссылка на сообщение в блоге Nigel Spencer [Проблемы, связанные с SelectedValue с WPF DataGrid] (http://blogs.spencen.com/?p=611) – Tone

ответ

3

Насколько я понимаю, вы знаете, как правильно добавлять новые элементы в свою связанную с данными коллекцию, чтобы добавить новый элемент, добавляемый к DataGrid и ваш вопрос действительно связан с тем, как вы можете это сделать, когда пользователь нажимает на последнюю строку в DataGrid. Общий способ обработки некоторого события в модели представления - создать Attached Property (если его еще нет), который обрабатывает это событие для вас.

Например, вы можете создать Attached Property, который прикрепляет обработчик к соответствующему событию и другому типу ICommand, который вы можете выполнить при вызове обработчика события. Затем вы можете написать функциональность этого 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}"/> 

Не забудьте указать цель команды.

Смежные вопросы