一个窗口有一个绑定到集合的MenuItem,MenuItem有ItemTemplate,它包含另一个带有附加属性的MenuItem:
<Menu Background="Transparent">
<MenuItem ItemsSource="{Binding SomeThings}" Header="Menu">
<MenuItem.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding MenuTitle}" WpfApplication30:MainWindow.KeyGesture="{Binding KeyGesture}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</Menu>
数据源和附加属性的声明:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
DataContext = new {
SomeThings = new[]
{
new { MenuTitle = "Title 1", KeyGesture = new KeyGesture(Key.A, ModifierKeys.Control) },
new { MenuTitle = "Title 2", KeyGesture = new KeyGesture(Key.B, ModifierKeys.Control) },
new { MenuTitle = "Title 3", KeyGesture = new KeyGesture(Key.C, ModifierKeys.Control) },
} };
}
public static string GetKeyGesture(MenuItem obj)
{
return (string)obj.GetValue(KeyGestureProperty);
}
public static void SetKeyGesture(MenuItem obj, string value)
{
obj.SetValue(KeyGestureProperty, value);
}
public static readonly DependencyProperty KeyGestureProperty =
DependencyProperty.RegisterAttached("KeyGesture", typeof(KeyGesture), typeof(MainWindow),
new PropertyMetadata(OnSetKeyGestureCallback));
private static void OnSetKeyGestureCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var window = GetWindow(dependencyObject);
var keyGesture = (KeyGesture)e.NewValue;
window.KeyDown += (sender, keyArgs) =>
{
if (keyArgs.Key == keyGesture.Key && keyArgs.KeyboardDevice.Modifiers == keyGesture.Modifiers)
{
window.Background = Brushes.AntiqueWhite;
}
};
}
调用OnSetKeyGestureCallback后,用户可以使用快捷方式执行操作。但只有在打开菜单后才会调用OnSetKeyGestureCallback。因此,在用户打开菜单之前,快捷方式不可用。如何在窗口或菜单加载后立即调用OnSetKeyGestureCallback?
答案 0 :(得分:0)
DataTemplate
MenuItem
的{{1}}包含MenuItem
。因此,您的视觉树中将有两个MenuItem
,一个是另一个的孩子。子项将正确设置属性,但父项不会。
如果您需要在MenuItem
上指定一个属性,则应使用ItemContainerStyle
:
<MenuItem ItemsSource="{Binding SomeThings}" Header="Menu">
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding MenuTitle}"/>
<Setter Property="MainWindow.KeyGesture" Value="{Binding KeyGesture}"/>
</Style>
</MenuItem>
</MenuItem>
至于为什么你的连接在Menu
打开之前没有运行,这是因为Menu
的子项是虚拟化的,直到必要时才创建(即直到父Menu
打开了)。您也可以覆盖用于托管子项的Panel
:
<MenuItem>
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding MenuTitle}"/>
<Setter Property="MainWindow.KeyGesture" Value="{Binding KeyGesture}"/>
</Style>
</MenuItem>
<MenuItem.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</MenuItem.ItemsPanel>
</MenuItem>
答案 1 :(得分:0)
不需要解决此问题的方法。为快捷方式做了不同的实现。