Привязать команду ListIItem ContextMenu MenuItem к ViewModel элемента ListSourceSource - PullRequest
1 голос
/ 31 марта 2020

У меня есть ListView из Expander с. Каждый Expander (представляющий таблицу базы данных) будет иметь элементы под ним, в другом ListView. Я хочу щелкнуть правой кнопкой мыши и выбрать опцию «Изменить» для самых внутренних элементов, которые представляют записи в соответствующей таблице базы данных.

В моем MainEditorViewModel есть ICommand с именем 'Edit'. Текст Datacontext, в котором находится эта команда, такой же, как у самого внешнего ListView с именем "TestGroupsListView"

Вот разметка XAML для ListView Expanders. Самый внешний ListView, который я назвал для ссылки в привязке через ElementName для MenuItem s Binding:

        <ListView Name="TestGroupsListView" ItemsSource="{Binding TestGroups}" Grid.Row="1">
            <ListView.ItemTemplate>
                <DataTemplate>


                    <Expander Style="{StaticResource MaterialDesignExpander}"  >
                        <Expander.Header>
                            <Grid MaxHeight="50">
                                <TextBlock Text="{Binding Name}"/>
                                <Grid.ContextMenu>

                                    <ContextMenu>
                                        <MenuItem Header="Add..." Command="{Binding Add}"/>
                                    </ContextMenu>
                                </Grid.ContextMenu>
                            </Grid>

                        </Expander.Header>

                        <ListView ItemsSource="{Binding Records}" Style="{StaticResource MaterialDesignListView}" Margin="30 0 0 0">
                            <ListView.ItemTemplate>
                                <DataTemplate>
                                    <Grid>
                                        <Grid.ContextMenu>
                                            <ContextMenu>
                                                <MenuItem Header="Edit" 
                                                          Command="{Binding ElementName=TestGroupsListView, Path=DataContext.Edit}"
                                                          CommandParameter="{Binding }"/>
                                            </ContextMenu>
                                        </Grid.ContextMenu>

                                        <Button Content="{Binding RecordName}" Command="{Binding ElementName=TestGroupsListView, Path=DataContext.Edit}"/>
                                        <!--<TextBlock Text="{Binding RecordName}" AllowDrop="True"/>-->
                                    </Grid>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>
                    </Expander>
                </DataTemplate>
            </ListView.ItemTemplate>

        </ListView>

Я могу привязать кнопку в шаблоне данных к «Редактировать» успешно, но когда я пытаюсь связать MenuItem 'Command с «Редактировать», ничего не происходит. Почему это может быть связано с тем, что привязка команды кнопки работает с использованием ElementName, а такая же привязка в ContextMenu - нет?

1 Ответ

1 голос
/ 01 апреля 2020

Я думаю, что будет лучше использовать контекстное меню глобально для ListView и глобально для каждого дочернего ListView. Хорошо, вот мое решение:

<ListBox ItemsSource="{Binding Groups}">
    <ListBox.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Add..." Command="{Binding Add}"/>
        </ContextMenu>
    </ListBox.ContextMenu>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Expander Header="{Binding Name}">
                <ListView ItemsSource="{Binding Records}" SelectedItem="{Binding SelectedRecord}">
                    <ListView.ContextMenu>
                        <ContextMenu>
                            <MenuItem Header="Edit" Command="{Binding Edit}" IsEnabled="{Binding CanEdit}"/>
                        </ContextMenu>
                    </ListView.ContextMenu>
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Name}"/>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </Expander>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

И для лучшего понимания кода:

public class GroupsVM : ViewModelBase
{
    public ICommand Add
    {
        get => null; //Command implementation
    }

    public ObservableCollection<GroupVM> Groups { get; set; } = new ObservableCollection<GroupVM>()
    {
        new GroupVM { Name = "First" },
        new GroupVM { Name = "Second" },
        new GroupVM { Name = "Third" }
    };
}

public class GroupVM : ViewModelBase
{
    private string _name;

    public string Name
    {
        get => _name;
        set { _name = value; OnPropertyChanged(); }
    }

    public ICommand Edit
    {
        get => null; //Command implementation
    }

    public bool CanEdit => SelectedRecord != null;

    public ObservableCollection<RecordVM> Records { get; set; } = new ObservableCollection<RecordVM>()
    {
        new RecordVM { Name="Record1" },
        new RecordVM { Name="Record2" },
        new RecordVM { Name="Record3" }
    };

    private RecordVM _selectedRecord = null;

    public RecordVM SelectedRecord
    {
        get => _selectedRecord;
        set
        {
            _selectedRecord = value;
            OnPropertyChanged();
            OnPropertyChanged("CanEdit");
        }
    }
}

public class RecordVM : ViewModelBase
{
    private string _name;

    public string Name
    {
        get => _name;
        set { _name = value; OnPropertyChanged(); }
    }
}
...