首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在MVVM的WPF DataGridColumn中添加ContextMenu?

如何在MVVM的WPF DataGridColumn中添加ContextMenu?
EN

Stack Overflow用户
提问于 2011-01-17 17:48:43
回答 4查看 5.7K关注 0票数 0

关于WPF DataGridColumn中的ContextMenu,我有一个棘手的问题。我不知道是否有人已经面临这个问题,但如果有人能帮助我,我将非常感激!

让我们从我的课程开始

代码语言:javascript
运行
复制
public class Person
{
    public string Type { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public int Age { get; set; }
}

public class Menu
{
    public string Name { get; set; }
    public int Code { get; set; }
    public ObservableCollection<Menu> listMenu { get; set; }
}

现在我的ViewModel

代码语言:javascript
运行
复制
 public class MyViewModel : INotifyPropertyChanged
{
    private ObservableCollection<Person> DataPersons = new ObservableCollection<Person>();
    private ObservableCollection<Menu> DataMenu = new ObservableCollection<Menu>();

    public ObservableCollection<Person> listDataPersons { get; set; }
    public ObservableCollection<Menu> listDataMenu { get; set; }

    public MyViewModel()
    {
        //initialization
        InitData();
    }

    private void InitData()
    {
        listDataPersons = new ObservableCollection<Person>();
        listDataMenu = new ObservableCollection<Menu>();

        DataPersons.Add(new Person() { Type = "Friend", Name = "Doe", Surname = "John", Age = 42});
        DataPersons.Add(new Person() { Type = "Friend", Name = "Smith", Surname = "Jack", Age = 42});

        DataMenu.Add(new Menu() { Name = "Principal", Code = 1});
        DataMenu.Add(new Menu() { Name = "Secondary", Code = 2});
        DataMenu.Add(new Menu() { Name = "Associated", Code = 3});

        DataMenu[2].listMenu = new ObservableCollection<Menu>();
        DataMenu[2].listMenu.Add(new Menu() { Name = "Associated 1", Code = 31 });

        listDataPersons = DataPersons;
        listDataMenu = DataMenu;
    }}

这是我的视图及其背后的代码

代码语言:javascript
运行
复制
<DataGrid ItemsSource="{Binding listDataPersons}" AutoGenerateColumns="False">
    <DataGrid.ContextMenu>
        <ContextMenu ItemsSource="{Binding listDataMenu}"/>
    </DataGrid.ContextMenu>
    <DataGrid.Columns>                
        <DataGridTemplateColumn IsReadOnly="True" Width="*">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}" Width="80" >
                    <TextBlock.ContextMenu>
                        <ContextMenu ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}}, Path=DataContext.listDataMenu}"/>
                    </TextBlock.ContextMenu>
                    </TextBlock>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

代码隐藏

代码语言:javascript
运行
复制
public partial class MyView : UserControl
{
    public MyView()
    {
        InitializeComponent();

        this.DataContext = new MyViewModel();
    }
}

我在这个例子中想要的是在DataGridColumn中有一个动态的ContextMenu。首先,我在整个DataGrid中放置了一个ContextMenu,它工作得很好。但是在我的例子中,我只需要在单元格中右键单击一个ContextMenu,而不是在整个DataGrid中。因此,我尝试使用具有ContextMenuTextBox来编辑DataGridColumnDataTemplate。不幸的是,当我在TextBox中右键单击时,它的ContextMenuItemsSource似乎为空。但是,当我在TextBox中的DataGrid外部右键单击时,D21的D22被正确绑定。

我想这可能是DataContext的问题,因为ContextMenuDataGrid没有相同的视觉树,所以我在ContextMenuItemsSource绑定中添加了RelativeSource,但没有结果!

有什么想法吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-01-20 17:39:10

首先,感谢Rick在这个问题上抽出时间指导我。

我已经在msdn论坛上发布了这个问题,我有一个解决它的答案

代码语言:javascript
运行
复制
<TextBlock Text="{Binding Name}" Width="80" Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}, Path=DataContext}">
<TextBlock.ContextMenu>                                                                                                
    <ContextMenu ItemsSource="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.Tag.listDataMenu}" ItemContainerStyle="{StaticResource ContextMenuItemStyle}"/>
</TextBlock.ContextMenu>                                

我想要做的是通过TextBox的标记将用户控件的DataContext传递给theContextMenu

对于那些想让它在我的代码中正常工作的人,你需要将UserControlRessoucre定义为:

代码语言:javascript
运行
复制
<UserControl.Resources>
    <HierarchicalDataTemplate DataType="{x:Type cmd:Menu}" ItemsSource="{Binding listMenu}">
        <TextBlock Text="{Binding Path=Name}"/>            
    </HierarchicalDataTemplate>

    <Style x:Key="ContextMenuItemStyle">
        <Setter Property="MenuItem.ItemsSource" Value="{Binding Path=listMenu}"/>             
    </Style>
</UserControl.Resources>

这是原始答案的msdn论坛链接:-->here<--

非常感谢谢尔顿·肖的回答

票数 1
EN

Stack Overflow用户

发布于 2011-01-18 08:59:07

你在正确的轨道上。您确实需要使用RelativeSource,但使用Self,然后使用PlacementTarget将视觉树交换到TextBox,您可以从中获得其DataContext,该use应该是从DataGridCell继承的,并且最终能够到达您的menu属性。

我所指的未经测试的例子:

代码语言:javascript
运行
复制
<ContextMenu ItemsSource="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.DataContext.listDataMenu}"/>
票数 0
EN

Stack Overflow用户

发布于 2011-01-19 18:57:33

尽管我在Datagrid中的每一行都需要相同的contextMenu,但我尝试了您的建议,但无法使其工作:(可能是我忘记了什么

听说我是这样修改我的类的:

代码语言:javascript
运行
复制
    public class Person
{
    public string Type { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public int Age { get; set; }
    public Column Column { get; set; }
}

public class Menu
{
    public string Name { get; set; }
    public int Code { get; set; }
    public ObservableCollection<Menu> listMenu { get; set; }
}
public class Column
{
    public ObservableCollection<Menu> listDatatMenu { get; set; }
}

然后,我在ViewModel中更改InitData函数,如下所示:

代码语言:javascript
运行
复制
private void InitData()
    {
        listDataPersons = new List<Person>();
        listDataMenu = new ObservableCollection<Menu>();

        DataPersons.Add(new Person() { Type = "Friend", Name = "Doe", Surname = "John", Age = 42});
        DataPersons.Add(new Person() { Type = "Friend", Name = "Smith", Surname = "Jack", Age = 42});

        DataMenu.Add(new Menu() { Name = "Principal", Code = 1});
        DataMenu.Add(new Menu() { Name = "Secondary", Code = 2});
        DataMenu.Add(new Menu() { Name = "Associated", Code = 3});

        DataMenu[2].listMenu = new ObservableCollection<Menu>();
        DataMenu[2].listMenu.Add(new Menu() { Name = "Associated 1", Code = 31 });

        DataPersons[0].Column = new Column();
        DataPersons[0].Column.listDatatMenu = DataMenu;

        DataPersons[1].Column = new Column();
        DataPersons[1].Column.listDatatMenu = DataMenu;

        listDataPersons = DataPersons;
        listDataMenu = DataMenu;
    }

最后是我视图中的ContextMenu

代码语言:javascript
运行
复制
<ContextMenu ItemsSource="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.DataContext.Column.listDataMenu}"/>  

如果我犯了一个新手错误,我很抱歉,但它确实起作用了

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4711802

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档