Пустое ContextMenu, если используется общий ItemsSource из ресурсов - решено - PullRequest
0 голосов
/ 27 февраля 2020

У меня возникла проблема при совместном использовании одного и того же MenuItem набора между 2 ContextMenu экземплярами, подключенными к различным DataGrid элементам управления. Целью является использование ContextMenu с одинаковыми элементами в нескольких DataGrids. Экземпляр ContextMenu должен быть присоединен к DataGridRow.

  1. Когда я открываю ContextMenu сначала DataGrid, все работает, все в порядке с привязками команд, DataContext и т. Д. c.
  2. Затем я открываю его на секунду DataGrid: все тоже хорошо.
  3. Но когда я возвращаюсь к первому DataGrid, ContextMenu становится пустым . И он остается пустым только для первого DataGrid и работает для второго.

Предполагаю, что ItemsSource отсоединяется, но я понятия не имею, почему и как это исправить, избегая клонированных наборов MenuItems.

Вот демонстрация проекта с нулевым кодом, где я отбросил все, что не затрагивало проблему ItemsSource.

MainWindow.xaml

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApp1"
        Title="MainWindow" Height="300" Width="600">
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Window.Resources>
        <x:Array x:Key="ContextMenuItems" Type="MenuItem">
            <MenuItem Header="Add"/>
            <MenuItem Header="Remove"/>
        </x:Array>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding GridItems}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Data1" Width="*" Binding="{Binding Value}"/>
            </DataGrid.Columns>
            <DataGrid.Resources>
                <ContextMenu x:Key="GridMenu1" ItemsSource="{StaticResource ContextMenuItems}"/>
            </DataGrid.Resources>
            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow">
                    <Setter Property="ContextMenu" Value="{StaticResource GridMenu1}"/>
                </Style>
            </DataGrid.RowStyle>
        </DataGrid>
        <DataGrid Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding GridItems}">
            <DataGrid.Columns >
                <DataGridTextColumn Header="Data2" Width="*" Binding="{Binding Value}"/>
            </DataGrid.Columns>
            <DataGrid.Resources>
                <ContextMenu x:Key="GridMenu2" ItemsSource="{StaticResource ContextMenuItems}"/>
            </DataGrid.Resources>
            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow">
                    <Setter Property="ContextMenu" Value="{StaticResource GridMenu2}"/>
                </Style>
            </DataGrid.RowStyle>
        </DataGrid>
    </Grid>
</Window>

MainViewModel.cs

public class MainViewModel : INotifyPropertyChanged
{
    public ObservableCollection<DataItem> GridItems { get; set; } = new ObservableCollection<DataItem>();
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class DataItem : INotifyPropertyChanged
{
    private string _value;
    public string Value
    {
        get => _value;
        set
        {
            _value = value;
            OnPropertyChanged(nameof(Value));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

То, что я пробовал:

  • DataGrid Binding не имеет значения
  • ContextMenu DataContext не имеет значения
  • Та же проблема, если я присоединяю ContextMenu непосредственно к DataGrid

a screenshot

Наконец, почему два ContextMenu с с общим MenuItem установленным? Потому что у каждого DataGrid есть свой экземпляр DataContext. И мне нужно прикрепить DataGrid DataContext к меню, но меню должно быть прикреплено к DataGridRow.

1 Ответ

0 голосов
/ 27 февраля 2020

РЕШЕНИЕ

Это было просто

  1. Обтекание Array в ResourceDictionary явно
  2. Добавить x:Shared="False" атрибут

Ссылка, которая мне помогла: Почему элемент x: Array заставляет любой атрибут x: Shared, следующий за ним, игнорироваться?

<Window.Resources>
    <ResourceDictionary>
        <x:Array x:Key="ContextMenuItems" Type="MenuItem" x:Shared="False">
            <MenuItem Header="Add"/>
            <MenuItem Header="Remove"/>
        </x:Array>
    </ResourceDictionary>
</Window.Resources>

Это работает для я, но я до сих пор не знаю, что это такое и как это работает.

...