创建动态可扩展工具箱

Creating a dynamic expandable toolbox

我正在尝试创建一个动态可扩展工具箱,如下图所示。

自定义控件将根据可用 space 在基本菜单和高级菜单中放置不同的项目。如果 space 足以显示基本菜单中的所有项目,则不会显示高级菜单。 我已经创建了这个控件,只要我在应用程序中只使用它一次,它就可以工作。如果我多次实例化它,我会得到下面的异常,我很难理解,因为我只是将一个元素添加到非静态列表中。

是否有人对如何以不同方式创建此控件以避免此问题有其他想法,或者知道是什么导致此异常?

Link 到解决方案:ButtonsItemsControl(要重现问题,只需取消注释 MainWindow.xaml

的第 15 行

感谢任何帮助

你的问题在于你的 ButtonsItemsControl class:

的依赖属性的声明
public ObservableCollection<FrameworkElement> BasedMenuItems
{
    get { return (ObservableCollection<FrameworkElement>)GetValue(BasedMenuItemsProperty); }
    set { SetValue(BasedMenuItemsProperty, value); }
}
public static readonly DependencyProperty BasedMenuItemsProperty =
        DependencyProperty.Register("BasedMenuItems", typeof(ObservableCollection<FrameworkElement>), typeof(ButtonsItemsControl),
        new PropertyMetadata(new ObservableCollection<FrameworkElement>()));

您为该依赖项 属性 设置了默认值,它是 ObservableCollection<FrameworkElement> 的一个实例。问题是,此实例是在执行此行时创建的,也就是当您的 class 加载到内存中并初始化静态字段时。因此,这意味着 ButtonsItemsControl 的每个 个实例将共享相同的集合对象,如果这些属性没有被覆盖的话。

您应该删除 PropertyMetadata 构造函数中的默认值,而是在您的控件实例化时在它自己的构造函数中设置一个新值:

public ButtonsItemsControl()
{
    BasedMenuItems = new ObservableCollection<FrameworkElement>();
    ...
}

这似乎违反直觉,但据我所知没有更好的方法(实际上框架在内部使用工厂对象创建 classes 的新实例以产生唯一的默认值,但无论出于何种原因它们没有在框架外公开那些工厂)。