我在 WPF 中使用用户控件时遇到问题。
我有一个窗口,在这个窗口中我有一个自定义菜单(用户控件)。在这个菜单中,我有三个自定义按钮。在窗口中,我还有一个 ContentControl,用于显示我正在使用的其他用户控件,如页面。这些按钮用于选择要显示的页面。
法典:
<Local:CustomMenu x:Name="mainMenu" Margin="10,42,0,0" Height="39" VerticalAlignment="Top">
<Local:CustomMenu.Items>
<Local:CustomButton Text="Home" TextColor="Black" Click="cbHome_Click" />
<Local:CustomButton Text="Users" TextColor="Black" Click="cbUsers_Click" />
<Local:CustomButton Text="Options" TextColor="Black" Click="cbOptions_Click" />
</Local:CustomMenu.Items>
</Local:CustomMenu >
<ContentControl x:Name="cControl" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Margin="0,81,0,0" />
点击示例:
private void cbOptions_Click(CustomButton arg1, RoutedEventArgs arg2)
{
cControl.Content = new Options();
}
进入"选项"页面,我有另一个自定义菜单,还有四个自定义按钮,还有一个内容控件,就像一个子页面选择。
问题从这里开始。当我选择"选项"页面时,当我将自定义菜单的项放在 WrapPanel 中以显示它时.cs在 CustomMenu.xaml 中引发异常。
法典:
foreach (FrameworkElement item in Items)
{
myWrapPanel.Children.Add(item); // Exception here
}
例外情况是:"指定的元素已经是另一个元素的逻辑子元素。先断开它。
所以我调试了它,令我惊讶的是,选项页面内的 CustomMenu 有 7 个项目,而不是预期的 4 个。
但是,如果我只添加四个项目怎么办?这三个额外的项目是对主窗口前三个按钮的引用,这就是引发此异常的原因。
怎么可能?对不起,如果不清楚。
"选项代码"页:
<Local:CustomMenu x:Name="optionsMenu" Margin="10,42,0,0" Height="39" VerticalAlignment="Top">
<Local:CustomMenu.Items>
<Local:CustomButton Text="test" TextColor="Black" />
<Local:CustomButton Text="test" TextColor="Black" />
<Local:CustomButton Text="test" TextColor="Black" />
<Local:CustomButton Text="test" TextColor="Black" />
</Local:CustomMenu.Items>
</Local:CustomMenu >
<ContentControl x:Name="cControl" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Margin="0,81,0,0" />
编辑
使用以下代码强制将按钮放入自定义菜单中,只会导致更奇怪的行为:
foreach (FrameworkElement item in Items)
{
try
{
myWrapPanel.Children.Add(item);
}
catch { }
}
结果是:主窗口的自定义菜单为 0 个 itens(所有 itens 都消失了),选项页面中的自定义菜单的正确 4 个 itens(至少)。
编辑 2
这是 CustomMenu.xaml.cs 中我的项目属性的定义:
public ObservableCollection<UIElement> Items
{
get { return (ObservableCollection<UIElement>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register("Items", typeof(ObservableCollection<UIElement>),
typeof(CustomMenu), new PropertyMetadata(new ObservableCollection<UIElement>()));
我不能说为什么你在CustomMenu
中看到七个项目,而不是你提供的信息中的四个项目。这一切听起来很奇怪。但是,您的问题是由以下代码引起的...:
foreach (FrameworkElement item in Items)
{
myWrapPanel.Children.Add(item); // Exception here
}
。之所以导致,是因为,如错误所述,指定元素已经是另一个元素的逻辑子元素。在 WPF 中,UI 元素只能在标记中出现一次,因此该错误意味着无法将 Items
集合中的 UI 项添加到另一个 UI 容器控件中。更简单地说,您不能同时在多个位置显示这些相同的项目。我无法确切地说出来,因为我们还没有看到您的CustomMenu
控件的定义。
您可以将它们从一个容器移动到另一个容器,但我不明白您为什么要这样做。在 WPF 中,我们通常操作数据,而不是 UI。因此,WPF "复制 UI 元素"的方式是提供一个DataTemplate
来定义 UI,然后复制数据对象或仅使用 Binding
。
如果我误解了你,很抱歉,但如果我误解了,也许你可以进一步解释(在你的问题的编辑中)上面的代码是做什么的。您不需要使用这样的代码,而是能够直接从控件内部Bind
到 Items
属性。