Tat*_*ead 8 wpf code-reuse xaml menuitem visual-studio-2013
以下简单代码尝试在两个单独的菜单上重用Window.Resources中定义的MenuItem.
<Window x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<collections:ArrayList x:Key="menuItemValues">
<MenuItem Header="First"/>
<MenuItem Header="Second"/>
<MenuItem Header="Third"/>
</collections:ArrayList>
<MenuItem x:Key="menuItem" x:Shared="False"
ItemsSource="{StaticResource menuItemValues}"
Header="Shared menu item"/>
</Window.Resources>
<StackPanel>
<Menu HorizontalAlignment="Left" VerticalAlignment="Top">
<StaticResource ResourceKey="menuItem"/>
<StaticResource ResourceKey="menuItem"/>
</Menu>
</StackPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)
这开始很棒,当你第一次选择菜单时,一切看起来都很好.第一个菜单有所需的MenuItems,
第二个也是如此:
但是当您导航回第一个菜单时,MenuItems会消失:
有人可以解释为什么菜单消失,并有办法让这个工作?
这是在调查另一个异常的SO问题时发现的.我尝试使用在另一个SO问题上讨论的策略,它似乎解决了问题,直到你第二次导航回菜单并且它消失了.
我在2台不同的机器上重现了这个问题:
发生这种情况是因为,虽然顶层MenuItem
是x:Shared="False"
,但MenuItem
集合中的对象却不是.它们在ArrayList
集合中声明为一次,然后在menuItem
创建的对象的每个实例中重用.
要使代码生效,您需要强制WPF创建新实例.一种选择是将其应用于x:Shared="False"
集合.例如:
<Window x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<collections:ArrayList x:Key="menuItemValues" x:Shared="False">
<MenuItem Header="First"/>
<MenuItem Header="Second"/>
<MenuItem Header="Third"/>
</collections:ArrayList>
<MenuItem x:Key="menuItem" x:Shared="False"
ItemsSource="{StaticResource menuItemValues}"
Header="Shared menu item"/>
</Window.Resources>
<StackPanel>
<Menu HorizontalAlignment="Left" VerticalAlignment="Top">
<StaticResource ResourceKey="menuItem"/>
<StaticResource ResourceKey="menuItem"/>
</Menu>
</StackPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)
当然,假设项目只是给定Header
值,您可以MenuItem
通过提供string
值而不是值来使用默认模板行为MenuItem
.这允许您重用集合本身(没有潜在的无法重用):
<Window x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<collections:ArrayList x:Key="menuItemValues">
<s:String>First</s:String>
<s:String>Second</s:String>
<s:String>Third</s:String>
</collections:ArrayList>
<MenuItem x:Key="menuItem" x:Shared="False"
ItemsSource="{StaticResource menuItemValues}"
Header="Shared menu item"/>
</Window.Resources>
<StackPanel>
<Menu HorizontalAlignment="Left" VerticalAlignment="Top">
<StaticResource ResourceKey="menuItem"/>
<StaticResource ResourceKey="menuItem"/>
</Menu>
</StackPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)