创建动态可扩展工具箱
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 的新实例以产生唯一的默认值,但无论出于何种原因它们没有在框架外公开那些工厂)。
我正在尝试创建一个动态可扩展工具箱,如下图所示。
自定义控件将根据可用 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 的新实例以产生唯一的默认值,但无论出于何种原因它们没有在框架外公开那些工厂)。