WPF XAML determines that reusing MenuItem starts working and then disappears

The following simple code attempts to reuse the MenuItem defined in Window.Resources on two separate menus.

<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> 

It starts out great, and when you first select a menu, everything looks good. The first menu has the necessary menu items,

enter image description here

So the second one:

enter image description here

But when you go to the first menu, the MenuItems elements disappear:

enter image description here

Can someone explain why the menu disappears and how to make it work?

This was discovered by examining another question, https://stackoverflow.com/a/166268/2126 , which received an exception. I tried using the strategy discussed on another SO question and it seems to have solved the problem until you return to the menu again and disappear.

I reproduced this problem on two separate machines:

  • Win 10, VS2013 Ult V12.0.40629.00 Update 5, .NET V4.6.0138
  • Win 7, VS2013 Prem V12.0.31101.00 Update 4, .NET V4.5.51209
+6
source share
1 answer

This is because although MenuItem top-level MenuItem x:Shared="False" , the MenuItem objects in your collection are not. They are declared once in the ArrayList collection, and then reused in each instance of the created MenuItem object.

To make the code work, you need to get WPF to create new instances. One option would be to apply x:Shared="False" to the collection. For instance:

 <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> 

Of course, given that the elements are simply assigned Header values, you can simply use the default behavior of the MenuItem template by specifying string values ​​instead of MenuItem values. This allows you to reuse the collection itself (which has no reason to be reused):

 <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> 
+7
source

All Articles