Qutfullo Ochilov
Qutfullo Ochilov

Reputation: 303

Binding ContextMenu property to owner property

I have a problem with binding a context menu to textbox's attached property. So I have TextBox and it has a context menu on right click. So how to bind context menu's property to TextBox's attached property in WPF XAML? Here I trying bind to TextBox but it not helps

 <Style x:Key="DefaultTextBox" TargetType="{x:Type TextBox}">
        <Setter Property="BorderBrush" Value="{DynamicResource ThemeSecondary}"/>
        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="ContextMenu">
            <Setter.Value>
                <ContextMenu x:Name="uiContexMenu">
                    <ContextMenu.ItemsSource>
                        <CompositeCollection>
                            <MenuItem Command="Cut" Header="Cut">
                                <MenuItem.Icon>
                                    <Viewbox Width="16" Height="16">
                                        <TextBlock FontFamily="{DynamicResource IconFont}" Text=""/>
                                    </Viewbox>
                                </MenuItem.Icon>
                            </MenuItem>
                            <MenuItem Command="Copy" Header="Copy">
                                <MenuItem.Icon>
                                    <Viewbox Width="16" Height="16">
                                        <TextBlock FontFamily="{DynamicResource IconFont}" Text=""/>
                                    </Viewbox>
                                </MenuItem.Icon>
                            </MenuItem>
                            <MenuItem Command="Paste" Header="Paste">
                                <MenuItem.Icon>
                                    <Viewbox Width="16" Height="16">
                                        <TextBlock FontFamily="{DynamicResource IconFont}" Text=""/>
                                    </Viewbox>
                                </MenuItem.Icon>
                            </MenuItem>
                            <CollectionContainer Collection="{Binding  RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TextBox}, Path=Extensions.ExtendCommands}"/>
                        </CompositeCollection>
                    </ContextMenu.ItemsSource>
                </ContextMenu>
            </Setter.Value>
        </Setter>

My Attached property :

 #region ExtendCommands dependency property

        public static IEnumerable GetExtendCommands(DependencyObject obj)
        {
            return (IEnumerable)obj.GetValue(ExtendCommandsProperty);
        }

        public static void SetExtendCommands(DependencyObject obj, IEnumerable value)
        {
            obj.SetValue(ExtendCommandsProperty, value);
        }

        // Using a DependencyProperty as the backing store for ExtendCommands.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ExtendCommandsProperty =
            DependencyProperty.RegisterAttached("ExtendCommands", typeof(IEnumerable), typeof(Extensions), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));

        #endregion

Thanks

Upvotes: 7

Views: 1292

Answers (2)

Rekshino
Rekshino

Reputation: 7325

Bad news: CollectionContainer has no DataContext. In binding you can only use a Source={x:reference XXX}. XXX must be initialized outside your style/resource dictionary.

What you can do:

To bind something, that has DataContext to attached property of a TextBox is: Set TextBox as DataContext for ContextMenu. So you can use a PlacementTarget property, since your context menu hangs on your TextBox. Further you can normally bind.

<ContextMenu x:Name="uiContexMenu" DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">

<ComboBox ItemsSource="{Binding Path=(local:Extensions.ExtendCommands)}"/>
...
</ContextMenu>

And of course you have to set your attached property:

xmlns:sys="clr-namespace:System;assembly=mscorlib"
<TextBox Text="***" Style="{StaticResource DefaultTextBox}">
                <local:Extensions.ExtendCommands>
                    <x:Array Type="{x:Type sys:String}">
                        <sys:String>Text 1</sys:String>
                        <sys:String>Text 2</sys:String>
                        <sys:String>Text 3</sys:String>
                    </x:Array>
                </local:Extensions.ExtendCommands>
            </TextBox>

Upvotes: 1

lhildebrandt
lhildebrandt

Reputation: 334

It´s a general issue with ContextMenu since it does not always have the data context of a supposed parent. For further information read about inheritance context https://blogs.msdn.microsoft.com/nickkramer/2006/08/17/whats-an-inheritance-context/

As mentioned in the comments of said blog post, you probably need to explicitely set the data context of the context menu to the textbox.

Upvotes: 0

Related Questions