Определенное WPF XAML повторное использование MenuItem начинает работать, а затем исчезает

следующий простой код пытается повторно использовать 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>

это начинается отлично, и когда вы впервые выбираете меню, все выглядит хорошо. В первом меню есть нужные меню,

enter image description here

то же самое делает второй:

enter image description here

но когда вы переходите назад к первому меню, MenuItems исчезни:

enter image description here

может кто-нибудь объяснить, почему меню исчезает и способ заставить это работать?

Это было обнаружено при исследовании другого поэтому вопрос это было исключение. Я попытался использовать стратегию, обсуждаемую на еще один вопрос и это, казалось, решило проблему, пока вы не вернетесь в меню во второй раз, и она исчезнет.

я воспроизвел эту проблему на 2 разных машинах:

  1. Win 10, VS2013 Ult V12.0.40629.00 обновление 5, .NET V4.6.0138
  2. Win 7, VS2013 Prem V12.0.31101.00 обновление 4, .NET V4.5.51209

1 ответов


это происходит, потому что в то время как топ-уровня 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>

конечно, учитывая, что элементы просто дано 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>