Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ContextMenu Binding from a TreeView

Tags:

c#

wpf

I have a simple task to bind a context menu to items in a TreeView. If I define the context menu statically no problem. But if I want to bind the context menu to my "root" data context things start to break. So far I was not able to find a correct way to bind my Context menu to the original DataContext the TreeView uses. What binding magic is need to get this working? This Binding does not work:

  <MenuItem Name="Name" Header="{Binding Path=DataContext.ContextMenuName, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeView}}}" />

Below is the full sample:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:ui="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TreeView ItemsSource="{Binding Path=Persons, Mode=OneTime}" Name="cTree">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate>
                    <TextBox Text="{Binding Mode=OneWay}">
                        <TextBox.ContextMenu>
                            <ContextMenu>
                                <MenuItem Name="Name" Header="{Binding Path=DataContext.ContextMenuName, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeView}}}" />
                            </ContextMenu>
                        </TextBox.ContextMenu>
                    </TextBox>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>
</Window>



public partial class MainWindow : Window
{
    public string[] Persons
    {
        get { return new string[] { "Alois", "Kraus", "Joe", "xxxx" }; }
    }

    public string ContextMenuName
    {
        get;
        set;
    }

    public MainWindow()
    {
        ContextMenuName = "This is the data bound menu name";
        InitializeComponent();
        this.DataContext = this;
    }
}

Basically I want to bind the property ContextMenuName (actually a command in my ViewModel) of the main form. Since the TreeView is rebinding its childs to the Persons (strings to keep it simple) I cannot get the root DataContext out of it. So far I was never able to find any Ancestor (TreeView or MainWindow) which should solve the issue? What am I doing wrong here?

like image 576
Alois Kraus Avatar asked Jun 26 '26 23:06

Alois Kraus


1 Answers

ContextMenu doesn't lie in same visual tree as that of control on which it is applied. So FindAncestor won't be able to get to TreeView since it is not ancestor of ContextMenu.

Also ElementName won't work here since it also need two controls to be in same Visual tree.

You can use x:Reference which allows to bind even if they don't lie in same visual tree:

<MenuItem Name="Name" 
          Header="{Binding Path=DataContext.ContextMenuName,
                           Source={x:Reference cTree}}" />
like image 97
Rohit Vats Avatar answered Jun 28 '26 11:06

Rohit Vats



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!