2013-09-24 2 views
1

Мой предыдущий пост о обнаружения изменений свойств в VM не был в глубине достаточно, поэтому я отправляю этоWPF DataGrid с DataGrid в RowDetailsTemplate

У меня есть сетка рабочих мест. Каждая работа может иметь одного или нескольких сотрудников.

В RowDetailsTemplate DataGrid содержится еще одна сетка для отображения сотрудников. Таким образом, родительская сетка привязана к списку заданий. Внутренняя сетка привязана к списку сотрудников, которые находятся на модели задания.

Модель Работа:

public class Job : _Base 
{ 
    private string _JobName = string.Empty; 
    public string JobName 
    { 
     get { return _JobName; } 
     set 
     { 
      if (_JobName != value) 
      { 
       _JobName = value; 
       RaisePropertyChanged("JobName"); 
      } 
     } 
    } 

    private string _JobNumber = string.Empty; 
    public string JobNumber 
    { 
     get { return _JobNumber; } 
     set 
     { 
      if (_JobNumber != value) 
      { 
       _JobNumber = value; 
       RaisePropertyChanged("JobNumber"); 
      } 
     } 
    } 

    private ObservableCollection<Employee> _Employees; 
    public ObservableCollection<Employee> Employees 
    { 
     get { return _Employees; } 
     set 
     { 
      if (_Employees != value) 
      { 
       if (_Employees != value) 
       { 
        _Employees = value; 
        RaisePropertyChanged("Employees"); 
       } 
      } 
     } 
    } 

    private Employee _SelectedEmployee; 
    public Employee SelectedEmployee 
    { 
     get { return _SelectedEmployee; } 
     set 
     { 
      if (_SelectedEmployee != value) 
      { 
       if (_SelectedEmployee != value) 
       { 
        _SelectedEmployee = value; 
        RaisePropertyChanged("SelectedEmployee"); 
       } 
      } 
     } 
    } 

    public Job() 
    { 
     Employees = new ObservableCollection<Employee>(); 
    } 
} 

Модель Сотрудник

public class Employee : _Base 
{ 
    private string _EmployeeName = string.Empty; 
    public string EmployeeName 
    { 
     get { return _EmployeeName; } 
     set 
     { 
      if (_EmployeeName != value) 
      { 
       _EmployeeName = value; 
       RaisePropertyChanged("EmployeeName"); 
      } 
     } 
    } 

    private bool _IsChecked = false; 
    public bool IsChecked 
    { 
     get { return _IsChecked; } 
     set 
     { 
      if (_IsChecked != value) 
      { 
       _IsChecked = value; 
       RaisePropertyChanged("IsChecked"); 
      } 
     } 
    } 
}   

Часть XAML

<DataGrid ItemsSource="{Binding Jobs}" 
      SelectedItem="{Binding SelectedJob}" 
      AutoGenerateColumns="False"> 

    <DataGrid.Columns> 
     <DataGridTextColumn Header="Job Name" Binding="{Binding JobName}" /> 
     <DataGridTextColumn Header="Job Number" Binding="{Binding JobNumber}" /> 
    </DataGrid.Columns> 

    <DataGrid.RowDetailsTemplate> 
     <DataTemplate> 

      <StackPanel Orientation="Vertical"> 

       <DataGrid ItemsSource="{Binding Employees}" 
          SelectedItem="{Binding SelectedEmployee}" 
          AutoGenerateColumns="False"> 

        <DataGrid.Columns> 
         <DataGridCheckBoxColumn Binding="{Binding IsChecked}"/> 
         <DataGridTextColumn Binding="{Binding EmployeeName}"/> 
        </DataGrid.Columns> 

       </DataGrid> 

       <Button Margin="5" 
         Height="23" 
         Width="75" 
         HorizontalAlignment="Left" 
         Content="Remove"/> 

      </StackPanel> 


     </DataTemplate> 
    </DataGrid.RowDetailsTemplate> 

</DataGrid> 

MainWindowViewModel

public class MainWindowViewModel : _Base 
{ 
    private ObservableCollection<Job> _Jobs; 
    public ObservableCollection<Job> Jobs 
    { 
     get { return _Jobs; } 
     set 
     { 
      if (_Jobs != value) 
      { 
       if (_Jobs != value) 
       { 
        _Jobs = value; 
        RaisePropertyChanged("Jobs"); 
       } 
      } 
     } 
    } 

    private Job _SelectedJob; 
    public Job SelectedJob 
    { 
     get { return _SelectedJob; } 
     set 
     { 
      if (_SelectedJob != value) 
      { 
       if (_SelectedJob != value) 
       { 
        _SelectedJob = value; 
        RaisePropertyChanged("SelectedJob"); 
       } 
      } 
     } 
    } 

    public MainWindowViewModel() 
    { 
     this.PropertyChanged += new PropertyChangedEventHandler(MainWindowViewModel_PropertyChanged); 
    } 

    void MainWindowViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName.Trim().ToLower() == "ischecked") 
     { 
      int x = 1; 
     } 
    } 
} 

У меня есть пара вопросов:

1) Свойство SelectedEmployee на модели Job не срабатывает, когда я нажимаю на сотрудника во внутренней сетке.

2) MainWindowViewModel_PropertyChanged не срабатывает при выборе сотрудника.

3) Обратите внимание на кнопку под внутренней сеткой. Как связать свою команду с MainWindowVM?

+0

Какова цель этих «выбранных» объектов?Я серьезно пересмотрел бы помещение свойства 'isChecked' внутри' Employee' или 'SelectedEmployee' внутри' Job'. Они представляют состояния представления, и это связывает логику представления с модельной областью. – Shoe

+0

Пользователь может проверить/удалить любое количество сотрудников и нажать «Удалить». Вот цель – CoderForHire

ответ

1
  1. Как есть DataGrid inside DataGrid's row, поэтому выше DataGrid как-то eating up the selectionchange for the inner DataGrid. Чтобы решить эту проблему, вам необходимо будет принудительно обновить источник привязки для дочернего DataGrid. Для этого захватите событие SelectionChanged для внутреннего DataGrid и в обработчике выполните следующее.

    private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
         DataGrid grid = e.OriginalSource as DataGrid; 
         var expression = grid.GetBindingExpression(DataGrid.SelectedItemProperty); 
         expression.UpdateSource(); 
    
        } 
    
  2. MainwindowVM не имеет IsChecked Thats собственности, почему его PropertyChanged для этого свойства не стреляют.

  3. Чтобы решить эту проблему, вам нужно сделать пару вещей. Проблема состоит в том, что ячейка DataGrid и строки не наследуют DataContext, поскольку они не попадают под его визуальное дерево. Таким образом, чтобы решить эту проблему, вам придется использовать BindingProxy взять окна DataContext к кнопке в rowdetails из DataGrid

Определение Binding класса Proxy, как показано ниже:

public class MyBindingProxy : Freezable 
    { 
     public static readonly DependencyProperty BindingDataProperty = 
      DependencyProperty.Register("BindingData", typeof(object), 
      typeof(MyBindingProxy), new UIPropertyMetadata(null)); 

     protected override Freezable CreateInstanceCore() 
     { 
      return new MyBindingProxy(); 
     } 

     public object BindingData 
     { 
      get { return (object)GetValue(BindingDataProperty); } 
      set { SetValue(BindingDataProperty, value); } 
     } 

    } 

В настоящее время в ресурсах вашего окно (где DataGrid есть) создать экземпляр прокси-сервер и установить BindingData к DataContext в окне, т.е. MainWindowViewModel как:

<Window.Resources> 
    <local:MyBindingProxy x:Key="myproxy" BindingData="{Binding}" /> 
</Window.Resources> 

Теперь просто набор команды как указано ниже на кнопке:

<Button Margin="5" 
    Height="23" 
    Width="75" 
    HorizontalAlignment="Left" 
    Content="Remove" 
    Command="{Binding BindingData.MyCommand, Source={StaticResource myproxy}}"/> 
+0

Я смотрел на это с тех пор, как вы отправили, и мне очень жаль, но все это выглядело как хак. Я не могу поверить, что для этого требуется простая настройка для многих сетей. Кроме того, вы говорите о подключении к событиям. На самом деле это не MVVM. Связывание должно быть возможным без событий. – CoderForHire

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