-1

我正在尝试创建类似可扩展按钮 - 上面带有上下文菜单的按钮,该按钮将通过单击鼠标左键打开。唯一我仍然无法完成的是 items 属性,它可以在 WPF XAML 设计器中设置,例如用于ContextMenu控制。所以,据我所知,这意味着我需要ItemCollection为我的属性使用类型。好的。让我们看一下我的组件:

public partial class MenuButton : Button
{
    private readonly ContextMenu Menu;

    public static readonly DependencyProperty MenuItemsProperty =
        DependencyProperty.Register("MenuItems", typeof(ItemCollection), typeof(ContextMenu), new PropertyMetadata(default(ItemCollection), new PropertyChangedCallback(OnSomeMenuItemsPropertyChanged)));

    public ItemCollection MenuItems
    {
        get => (ItemCollection)GetValue(MenuItemsProperty);
        set => SetValue(MenuItemsProperty, value);
    }

    public MenuButton()
    {
        MenuItems = new DataGrid().Items; // I really need to do it - otherwise I'll get an error

        Menu = new ContextMenu
        {
            HasDropShadow = false,
            PlacementTarget = this,
            Placement = PlacementMode.Top,
        };

        InitializeComponent();
    }

    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        base.OnMouseLeftButtonDown(e);

        Menu.Width = ActualWidth;
        Menu.IsOpen = true;
    }

    private static void OnSomeMenuItemsPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
    {
        if (target is ContextMenu menu)
        {
            menu.ItemsSource = (ItemCollection)e.NewValue;
        }
    }
}

但我无法“捕捉” OnSomeMenuItemsPropertyChanged- 断点在这里不起作用。所以,这意味着这个机制是错误的。我该如何解决?我应该使用OnItemsChangedandOnItemsCollectionChanged事件(例如 for ObservableCollection)来处理属性的更改吗?或者也许是别的什么?

4

1 回答 1

0

所以,最后我找到了解决方案。我并没有声称这是最佳实践,但也许它对某人有用:

public partial class MenuButton : Button
{
    private readonly ContextMenu Menu;

    public static readonly DependencyProperty MenuItemsProperty =
        DependencyProperty.Register("MenuItems", typeof(ItemCollection), typeof(MenuButton), new PropertyMetadata(default(ItemCollection), new PropertyChangedCallback(OnSomeMenuItemsPropertyChanged)));

    public ItemCollection MenuItems
    {
        get => (ItemCollection)GetValue(MenuItemsProperty);
        set => SetValue(MenuItemsProperty, value);
    }

    public MenuButton()
    {
        Menu = new ContextMenu
        {
            HasDropShadow = false,
            PlacementTarget = this,
            Placement = PlacementMode.Top,
        };
        MenuItems = new DataGrid().Items;

        InitializeComponent();
    }

    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        base.OnMouseLeftButtonDown(e);

        Menu.Width = ActualWidth;
        Menu.IsOpen = true;
    }

    private static void OnSomeMenuItemsPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
    {
        var menuButton = target as MenuButton;
        menuButton.Menu.ItemsSource = (ItemCollection)e.NewValue;
    }
}
于 2022-01-16T12:33:17.670 回答