WPF XAML定义的MenuItem重用开始工作,然后消失

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台不同的机器上重现了这个问题:

  1. Win 10,VS2013 Ult V12.0.40629.00 Update 5,.NET V4.6.0138
  2. Win 7,VS2013 Prem V12.0.31101.00 Update 4,.NET V4.5.51209

Pet*_*iho 9

发生这种情况是因为,虽然顶层MenuItemx: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)