Я знаю, что мне действительно нужно начать читать книгу о 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 ...
doenst this вызвать контекстное меню для отображения везде в элементе управления? Я хочу, чтобы он был набросок на «ActionReactionDataGridViewModel.ContextMenu» и на всю строку. – c3rebro
где-нибудь внутри DataGrid будет показано –