Caliburn.Micro: Как связать функцию с элементом контекстного меню в шаблоне RowDetails DataGrid? - PullRequest
0 голосов
/ 23 апреля 2020

У меня есть сетка данных Предметов, которая включает сетку данных Подэлементов для деталей строки. Для основной сетки данных «Элементы» есть контекстное меню с функциями добавления или удаления элементов, это работает нормально. Существует также контекстное меню для сетки данных деталей "SubItems" с похожими функциями, которые я не могу связать должным образом. В случае выполнения я получаю следующее исключение: «System.Exception:« Цель для метода AddSubItem не найдена. » Я ценю любое понимание. Ниже приведен мой тестовый код.

ShellViewModel:

using System;
using Caliburn.Micro;
using ContextMenuTest.Models;

namespace ContextMenuTest.ViewModels
{
    public class ShellViewModel : Screen
    {
        public static Random rnd = new Random();
        private BindableCollection<ItemModel> items = new BindableCollection<ItemModel>();
        public BindableCollection<ItemModel> Items
        {
            get { return items; }
            set
            {
                items = value;
                NotifyOfPropertyChange(() => Items);
            }
        }

        private ItemModel selectedItem = new ItemModel(rnd);
        public ItemModel SelectedItem
        {
            get { return selectedItem; }
            set
            {
                selectedItem = value;
                NotifyOfPropertyChange(() => SelectedItem);
            }
        }

        private SubItemModel selectedSubItem = new SubItemModel(rnd);
        public SubItemModel SelectedSubItem
        {
            get { return selectedSubItem; }
            set
            {
                selectedSubItem = value;
                NotifyOfPropertyChange(() => SelectedSubItem);
            }
        }

        public ShellViewModel()
        {
            for(int i = 0; i < 10; i++)
            {
                Items.Add(new ItemModel(rnd));
            }
        }

        public void AddItem()
        {
            Items.Add(new ItemModel(rnd));
        }

        public void RemoveItem()
        {
            Items.Remove(SelectedItem);
        }

        public void AddSubItem(object e)
        {
            var _item = e as ItemModel;
            _item.SubItems.Add(new SubItemModel(rnd));
        }

        public void RemoveSubItem(object e)
        {
            var _item = e as ItemModel;
            _item.SubItems.Remove(SelectedSubItem);
        }
    }
}

ShellView:

<Window x:Class="ContextMenuTest.Views.ShellView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ContextMenuTest.Views"
        xmlns:cal="http://www.caliburnproject.org"
        mc:Ignorable="d"
        Title="ShellView" Height="450" Width="800"
        >

    <Grid Grid.Row="1">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <DataGrid x:Name="Items" Grid.Row="0" AutoGenerateColumns="False" CanUserResizeColumns="True" CanUserAddRows="false"
                        VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto" MinHeight="100" SelectedItem="{Binding SelectedItem}">
            <DataGrid.ContextMenu>
                <ContextMenu cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
                    <MenuItem Header="Add Item" cal:Message.Attach="AddItem()"/>
                    <MenuItem Header="Remove Item" cal:Message.Attach="RemoveItem()"/>
                </ContextMenu>
            </DataGrid.ContextMenu>

            <DataGrid.Columns >
                <DataGridTextColumn Header="ID" Binding="{Binding Path=ID, UpdateSourceTrigger=PropertyChanged}" Width="*" IsReadOnly="True"/>
                <DataGridTextColumn Header="Name" Binding="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" Width="*"/>
            </DataGrid.Columns>

            <DataGrid.RowDetailsTemplate>
                <DataTemplate>
                    <DataGrid ItemsSource="{Binding Path=SubItems}"  AutoGenerateColumns="False" CanUserResizeColumns="True" CanUserAddRows="false"
                                VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto" MinHeight="100" 
                                  SelectedItem="{Binding Path=SelectedSubItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}}">
                        <DataGrid.ContextMenu>
                            <ContextMenu cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
                                <MenuItem Header="Add Sub Item" cal:Message.Attach="AddSubItem($dataContext)"/>
                                <MenuItem Header="Remove Sub Item" cal:Message.Attach="RemoveSubItem($dataContext)"/>
                            </ContextMenu>
                        </DataGrid.ContextMenu>
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="ID" Binding="{Binding Path=ID}" Width="auto" IsReadOnly="True"/>
                            <DataGridTextColumn Header="Name" Binding="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" Width="auto"/>
                            <DataGridTextColumn Header="Value" Binding="{Binding Path=Value, UpdateSourceTrigger=PropertyChanged}" Width="auto"/>
                        </DataGrid.Columns>
                    </DataGrid>
                </DataTemplate>
            </DataGrid.RowDetailsTemplate>
        </DataGrid>
    </Grid>
</Window>

ItemModel:

using Caliburn.Micro;
using System;

namespace ContextMenuTest.Models
{
    public class ItemModel
    {
        public Guid ID { get; set; }
        public string Name { get; set; }
        public BindableCollection<SubItemModel> SubItems { get; set; } = new BindableCollection<SubItemModel>();

        public ItemModel(Random rnd)
        {
            ID = Guid.NewGuid();
            Name = "Item " + ID.ToString().Substring(3, 5);

            for (int i = 0; i < 5; i++)
            {
                SubItems.Add(new SubItemModel(rnd));
            }
        }
    }
}

SubItemModel:

using System;

namespace ContextMenuTest.Models
{
    public class SubItemModel
    {
        public Guid ID { get; set; }
        public string Name { get; set; }
        public int Value { get; set; }

        public SubItemModel(Random rnd)
        {
            ID = Guid.NewGuid();
            Name = "SubItem " + ID.ToString().Substring(3,5);
            Value = rnd.Next();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...