簡體   English   中英

我可以為WPF CustomControl定義標准的ContextMenu嗎?

[英]Can i define a standard ContextMenu for WPF CustomControls?

因為我要制作一堆WPF CustomControl,並且想為這些控件使用標准的ContextMenu,所以我想知道是否可以將ContextMenu定義為資源。

以及如何定義這種ContextMenu的樣式? 如果有可能,我可以用類似以下的方法覆蓋控件的Contextmenu:

ContextMenu="{StaticResource standardcontextmenu}"

提前致謝!

在合並到App.xaml的XAML資源字典中定義它,因此在整個應用程序中都可用。 將上下文菜單定義為資源很容易,但是如果它是資源,則需要做一些額外的工作來讓它知道其上下文是什么。 對於大多數WPF控件,您需要進行RelativeSource AncestorType綁定,但是contextmenu不在VisualTree中,因此無法使用。

它說在這里,當菜單打開時,ContextMenu.PlacementTarget將被設置為上下文菜單的所有者 ,但是我桌面上的監視窗口說他們只是在開玩笑。 如果您定義這樣的上下文菜單,則其DataContext就是local:Bar以下實例:

<local:Bar >
    <local:Bar.ContextMenu>
        <ContextMenu>
            <MenuItem 
                Header="{Binding ArbitraryProperty}" 
                />
        </ContextMenu>
    </local:Bar.ContextMenu>
</local:Bar>

...但是當上下文菜單是資源時這不起作用。 在這種情況下,您需要自己設置DataContext 事實證明,這並不會太痛苦。 我們將在自定義控件的ContextMenuOpening事件中進行此操作。 我們將定義兩個自定義控件。 在其中一個中,我們將通過StyleEventSetter設置ContextMenuOpening ,在另一個中,我們將在構造ContextMenuOpening使用lambda處理ContextMenuOpening 我喜歡EventSetter版本,因為盡管它需要做更多的工作,但是您可以將它放置在任何可以放置Style東西上。 您也可以編寫一個附加的屬性/行為來設置類似的處理程序,這將更加易於使用。

主題/Generic.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SharedContextMenuTest"
    x:Class="SharedContextMenuTest.Themes.Generic"
    >
    <ContextMenu x:Key="SharedContextMenu">
        <MenuItem Header="{Binding ArbitraryProperty}" />
    </ContextMenu>

    <Style TargetType="{x:Type local:Foo}">
        <!-- IMPORTANT -->
        <Setter Property="ContextMenu" Value="{StaticResource SharedContextMenu}" />
        <EventSetter Event="ContextMenuOpening" Handler="FooBar_ContextMenuOpening" />
        <!-- !IMPORTANT -->

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:Foo}">
                    <Border
                        Background="GhostWhite" 
                        BorderBrush="DodgerBlue"
                        BorderThickness="1"
                        Margin="1"
                        >
                        <Label 
                            Content="{TemplateBinding ArbitraryProperty}"
                            Padding="20"
                            />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style TargetType="{x:Type local:Bar}">
        <!-- IMPORTANT -->
        <!-- Bar sets up the ContextMenuOpening handler in its constructor -->
        <Setter Property="ContextMenu" Value="{StaticResource SharedContextMenu}" />
        <!-- !IMPORTANT -->

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:Bar}">
                    <Border
                        Background="GhostWhite" 
                        BorderBrush="ForestGreen"
                        BorderThickness="1"
                        Margin="1"
                        >
                        <Label 
                            Content="{TemplateBinding ArbitraryProperty}"
                            Padding="20"
                            />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

主題/Generic.xaml.cs

namespace SharedContextMenuTest.Themes
{
    public partial class Generic
    {
        private void FooBar_ContextMenuOpening(object sender, ContextMenuEventArgs e)
        {
            (e.Source as FrameworkElement).ContextMenu.DataContext = e.Source;
        }
    }
}

MyCustomControls.cs

namespace SharedContextMenuTest
{
    public class Foo : Control
    {
        public static readonly DependencyProperty ArbitraryPropertyProperty =
            DependencyProperty.Register("ArbitraryProperty", typeof(String), typeof(Foo),
                new PropertyMetadata(nameof(Foo)));
    }

    public class Bar : Control
    {
        public Bar()
        {
            //  Foo has an EventSetter in its Style; here we illustrate a quicker way. 
            ContextMenuOpening += (s, e) => ContextMenu.DataContext = this;
        }

        public static readonly DependencyProperty ArbitraryPropertyProperty =
            DependencyProperty.Register("ArbitraryProperty", typeof(String), typeof(Bar),
                new PropertyMetadata(nameof(Bar)));
    }
}

MainWindow.xaml

<StackPanel Orientation="Vertical">
    <local:Foo />
    <local:Bar />
</StackPanel>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM