Пункты меню контекстного меню связывают WPF с использованием MVVM - PullRequest
3 голосов
/ 01 октября 2010

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

Постановка проблемы: Я использую WPF DataGrid.Я добавил Контекстное меню , и у меня есть 3 варианта Вырезать, Копировать, Вставить.Я использую MVVM для разработки.Я хочу привязать эти параметры к командам в моей ViewModel.Но я не могу сделать то же самое.Опции контекстного меню вообще не привязываются к данным !!!

Это мой Grid-код в XAML:

<custom:DataGrid  
      x:Name="DataGrid_Standard"   
      Grid.Row="1" Grid.Column="1"   
      AutoGenerateColumns="False"                                                           
      IsSynchronizedWithCurrentItem="True"   
      Background="Transparent"
      ItemsSource="{Binding FullGridData}" 
      ItemContainerStyle="{StaticResource defaultRowStyle}"
      ColumnHeaderStyle="{StaticResource DefaultColumnHeaderStyle}"                         
      Grid.ColumnSpan="2">

Затем у меня есть ContextMenu и стиль для элемента заголовка

<ContextMenu x:Key="columnHeaderMenu">
   <MenuItem Command="{Binding CutCommand}"
             Header="Test" />
   <MenuItem Header="Copy"/>
   <MenuItem Header="Paste"/>
</ContextMenu>
<Style TargetType="{x:Type custom:DataGridColumnHeader}" x:Key="DefaultColumnHeaderStyle">
    <Setter Property="ContextMenu" Value="{DynamicResource columnHeaderMenu}" >
</Style>

Эта строка идет в моем конструкторе

public Window1()
{            
   this.DataContext = new AppData();
}

Этот код входит в мой класс AppData:

public class AppData  
{ 
    private IList<GridData> fullGridData = new ObservableCollection<GridData>();<br> 
    public IList<GridData> FullGridData
    {
        get { return fullGridData; }
        set { fullGridData = value; }
    }

    private DelegateCommand<object> cutCommand;
    public DelegateCommand<object> CutCommand
    {
        get
        {
            if (cutCommand == null)
            {
                cutCommand = new DelegateCommand<object>(CutColumn);
            }
            return cutCommand;
        }
    }

    private void CutColumn(object obj)
    {
        //some code goes here
    }   
}

** Я хочу точно знать, где я делаю неправильно ??Почему DataBinding не происходит?Пожалуйста, помогите мне в этом.Пожалуйста, предоставьте мне пример кода или модификации в моем настоящем коде, из которого я могу добиться этого.**

Ответы [ 5 ]

1 голос
/ 04 февраля 2017

Что-то в вашем коде (или используемой в то время версии WPF (?)) Слишком усложняет ситуацию. Я могу связать такие как

<DataGrid AutoGenerateColumns="True"
        Name="myGrid"
        ItemsSource="{Binding Orders}">
    <DataGrid.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Copy" Command="{Binding CopyItem}" />
            <MenuItem Header="Delete" Command="{Binding DeleteItem}" />
        </ContextMenu>
    </DataGrid.ContextMenu>
</DataGrid>

Где команда настроена так:

VM.DeleteItem 
     = new OperationCommand((o) => MessageBox.Show("Delete Me"),
                            (o) => (myGrid.SelectedItem as Order)?.InProgress == false );

enter image description here

1 голос
/ 29 июля 2015

У меня была такая же проблема.Привязки команд перестали работать, как только я переместил их в ViewModel из кода позади.И в модели представления мне пришлось изменить свой ICommand с RoutedCommand на DelegateCommand.Я смог заставить его работать следующим образом -

Добавить открытый обработчик событий в ваше контекстное меню -

<ContextMenu x:Key="columnHeaderMenu" Opened="ContextMenu_Opened">
    <MenuItem Command="{Binding CutCommand}" Header="Test" />
    <MenuItem Header="Copy"/>
    <MenuItem Header="Paste"/>
</ContextMenu>

В этом коде вы должны назначить вашу ViewModel для DataContext контекстного меню.-

private void ContextMenu_Opened(object sender, RoutedEventArgs e)
{
    ContextMenu menu = sender as ContextMenu;
    menu.DataContext = _vm;
}
1 голос
/ 01 ноября 2015

Я обычно создаю экземпляр моей модели представления как статический ресурс в моем представлении:

<UserControl x:Class="My.Namespace.MySampleView" ...> 
    <UserControl.Resources> 
        <viewModels:MySampleViewModel x:Key="ViewModel" /> 
    </UserControl.Resources> 

Тогда вы можете легко ссылаться на любое свойство вашей модели представления, даже если текущий контекст привязки не является моделью представления:

<ContextMenu x:Key="columnHeaderMenu">
    <MenuItem Command="{Binding MyCommand, Source={StaticResource ViewModel}}" />
</ContextMenu>

Для получения дополнительной информации ознакомьтесь с моей статьей Рекомендации и рекомендации по внедрению приложений MVVM и XAML / .NET .

0 голосов
/ 04 апреля 2016
<MenuItem Header="Cut" Command="{Binding Path=PlacementTarget.DataContext.CutCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
0 голосов
/ 01 октября 2010

У вас есть два варианта.
Примечание: примеры кода, которые я добавил сюда, похожи, но не совпадают с вашими примерами.

Переместите определение ContextMenu в определение DataGrid следующим образом:

<WpfToolkit:DataGrid
   x:Name="DataGrid_Standard"
   IsSynchronizedWithCurrentItem="True"
   Background="Transparent" 
   ItemsSource="{Binding FullGridData}" 
   ColumnHeaderStyle="{StaticResource DefaultColumnHeaderStyle}">
   <WpfToolkit:DataGrid.ContextMenu>
       <ContextMenu>
           <MenuItem Command="{Binding CutCommand}" Header="Test" />
           <MenuItem Header="Copy"/>
           <MenuItem Header="Paste"/>
       </ContextMenu>
   </WpfToolkit:DataGrid.ContextMenu>
</WpfToolkit:DataGrid>

Или лучше добавить CommandReference к своим ресурсам и установить команду в MenuItem для StaticResource следующим образом:

<Window.Resources>
    <c:CommandReference x:Key="MyCutCommandReference" Command="{Binding CutCommand}" />

    <ContextMenu x:Key="columnHeaderMenu">
        <MenuItem Command="{StaticResource MyCutCommandReference}" Header="Test" />
        <MenuItem Header="Copy"/>
        <MenuItem Header="Paste"/>
    </ContextMenu>

    <Style TargetType="{x:Type Primitives:DataGridColumnHeader}" x:Key="DefaultColumnHeaderStyle">
        <Setter Property="ContextMenu" Value="{DynamicResource columnHeaderMenu}" />
    </Style>

</Window.Resources>

<WpfToolkit:DataGrid
   x:Name="DataGrid_Standard"
   IsSynchronizedWithCurrentItem="True"
   Background="Transparent" 
   ItemsSource="{Binding FullGridData}" 
   ColumnHeaderStyle="{StaticResource DefaultColumnHeaderStyle}"/>
...