【问题标题】:Binding a custom attached property and OnSetPropertyCallback绑定自定义附加属性和 OnSetPropertyCallback
【发布时间】:2010-07-17 13:11:07
【问题描述】:

一个窗口有一个 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?

【问题讨论】:

    标签: wpf binding


    【解决方案1】:

    这个问题不需要解决方案。为快捷方式做了不同的实现。

    【讨论】:

      【解决方案2】:

      您的DataTemplate MenuItem 包含MenuItem。因此,您的视觉树中将有两个MenuItems,一个是另一个的子级。子级将正确设置属性,但父级不会。

      如果你需要在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>
      

      【讨论】:

      • 感谢 ItemContainerStyle 的提示!我什至在 DataTemplate 中为 MenuItem 编写了 MenuItem.Style,以使其看起来没有嵌套在另一个中。现在我可以摆脱它了。但主要问题仍然存在。例如,如果我这样写:,在我打开菜单之前不会触发 Loaded 事件。
      猜你喜欢
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-02
      • 2011-02-07
      • 1970-01-01
      相关资源
      最近更新 更多