[英]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
事件中進行此操作。 我們將定義兩個自定義控件。 在其中一個中,我們將通過Style
的EventSetter
設置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.