2017-02-14 12 views
0

Я знаю, что мне действительно нужно начать читать книгу о XAML и WPF, потому что я думаю, что все мои проблемы связаны с недостатком понимания привязки данных (я использовал WinForms в течение многих лет):Как работает привязка данных между ContextMenuItems DataGridRow и самой DataGridRow к свойствам внутри инкапсулированной Viewmodel?

Мое приложение состоит из TreeView и DataGrid.

В TreeView я добавил ViewModels для каждого ParentNode, ChildNode и GrandChildNode.

Я использовал образец от Джоша Смита found here.

Чтобы быть коротким, он/я

<HierarchicalDataTemplate 
        DataType="{x:Type local:ViewModel.TreeViewChildNodeViewModel}" 
        ItemsSource="{Binding Children}"> 
</HierarchicalDataTemplate.Resources> 

связать ChildNode к ChildNodeViewModel и к соответствующей модели.

Я добавил, чем - в конструкторе TreeViewChildNodeViewModel:

ContextMenuItems = new List<MenuItem>(); 
ContextMenuItems.Add(new MenuItem() { 
          Header = "Click", 
          Command = _cmdDoSmth 
          ToolTip = new ToolTip() { Content = "blabla" } 
            } 
); 

, который подвергается воздействию View с этим свойством:

private readonly List<MenuItem> ContextMenuItems; 
public List<MenuItem> ContextMenu { 
    get { return ContextMenuItems; } 
} 

Обратите внимание, что, у меня есть несколько конструкторов. Я добавляю разные ContextMenuItems в список ContextMenu в зависимости от того, с какой моделью я хочу работать ViewModel. «Корневой» ChildNode состоит из:

<TextBlock 
    Text="{Binding ChildNodeDisplayItem}"> 
    <TextBlock.ContextMenu> 
     <ContextMenu 
      ItemsSource="{Binding ContextMenu}"></ContextMenu> 
    </TextBlock.ContextMenu> 
</TextBlock> 

Это работает как должно. Теперь мои проблемы начинаются с попытки сделать что-то подобное с datagrid.

Что мне нужно достичь, это:

Я хотел бы показать строки в DataGrid. Каждая строка имеет свою собственную Viewmodel с открытым списком ContextMenuItem (как и модель, конечно). Я хотел бы иметь возможность определять счетчик, заголовок и команду каждого контекстного объекта в зависимости от выбранной модели представления.

То, что я сделал до сих пор:

В моей MainWindow.xaml:

<Controls:MetroWindow.Resources> 
    <ContextMenu x:Key="DataRowContextMenu" ItemsSource="{Binding Path=ActionReactionDataGridViewModel/ContextMenu, RelativeSource={RelativeSource AncestorType=DataGrid, Mode=FindAncestor}}"/> 
</Controls:MetroWindow.Resources> 

<DataGrid 
    AutoGenerateColumns="True" 
    AutoGeneratingColumn="OnAutoGeneratingColumn" 
    HorizontalAlignment="Stretch" 
    VerticalAlignment="Stretch" 
    BorderThickness="1,1,1,1" 
    Margin="0,0,0,0" 
    ItemsSource="{Binding Path=ActionReactionDataGridViewModel/DataGridSource}" 
    SelectedItem="{Binding Path=ActionReactionDataGridViewModel/SelectedDataGridItem}" 
    BorderBrush="#FF020202"> 
    <DataGrid.RowStyle> 
     <Style TargetType="{x:Type DataGridRow}"> 
      <Setter Property="ContextMenu" Value="{StaticResource RowMenu}" />    </Style> 
    <DataGrid.RowStyle> 
</DataGrid> 

В моей MainWindowViewModel:

public MainWindowViewModel() // Constructor 
    { 
     actionReactionDataGrid = new ObservableCollection<ActionReactionDataGridViewModel>(); 
     actionReactionDataGrid.Add(new ActionReactionDataGridViewModel()); 

    } 

    private ObservableCollection<ActionReactionDataGridViewModel> actionReactionDataGrid; 
    public ObservableCollection<ActionReactionDataGridViewModel> ActionReactionDataGridViewModel 
    { 
     get { return actionReactionDataGrid; } 
    } 

Мой ActionReactionDataGridViewModel здесь:

public class ActionReactionDataGridViewModel : ViewModelBase 
{ 
    private readonly List<MenuItem> ContextMenuItems; 

    public ActionReactionDataGridViewModel() 
    { 

     ContextMenuItems = new List<MenuItem>(); 

     ContextMenuItems.Add(new MenuItem() 
          { 
           Header = "blubb" 
          }); 

     dataGridSource = new ObservableCollection<ActionReactionDataGridModel>(); 
     dataGridSource.Add(new ActionReactionDataGridModel("Status","Eventname","Eventtyp","ReaktionName","ReaktionTyp")); 
    } 

    public List<MenuItem> ContextMenu { 
     get { return ContextMenuItems; } 
    } 

    private ActionReactionDataGridModel selectedDataGridItem; 
    public ActionReactionDataGridModel SelectedDataGridItem { 
     get { return selectedDataGridItem; } 
     set {selectedDataGridItem = value; RaisePropertyChanged("SelectedDataGridItem"); } 
    } 

    private ObservableCollection<ActionReactionDataGridModel> dataGridSource; 
    public ObservableCollection<ActionReactionDataGridModel> DataGridSource { 
     get { return dataGridSource; } 
     set { dataGridSource = value; RaisePropertyChanged("DataGridSource"); } 
    } 


} 

Я думаю, что размещение содержимого модели не обязательно, потому что оно просто содержит заголовки столбцов и некоторые примеры строк. Я думаю, что недостатком iam является знание указания элемента управления DataGrid в представлении в MainWindow.xaml для привязки источника items к «DataGridSource» вместо «ActionReactionDataGridViewModel».

Я нашел другие сообщения о SO о добавлении контекстных меню в datagridrow. то, чего я отсутствовал, - это способность связывать счет, текст и команду с каждой моделью просмотра.

Любая помощь была бы принята с благодарностью.

спасибо.

// EDIT 1

Ok. выяснить, как передать свойство viewmodel изнутри коллекции viewmodels было легко.

я добавил

ItemsSource="{Binding Path=ActionReactionDataGridViewModel/DataGridSource} 

объяснение here

Теперь я "просто" нужно выяснить, как добавить элементы Контекстное друг ViewModel ...

ответ

0
<DataGrid.ContextMenu> 
       <ContextMenu> 
        <MenuItem Header="HeaderName"> 
        </MenuItem> 
       </ContextMenu> 
      </DataGrid.ContextMenu> 

в меню вы можете написать свой контроль.

+0

doenst this вызвать контекстное меню для отображения везде в элементе управления? Я хочу, чтобы он был набросок на «ActionReactionDataGridViewModel.ContextMenu» и на всю строку. – c3rebro

+0

где-нибудь внутри DataGrid будет показано –