[英]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.