C# WPF Menu no longer works after upgrade project to SDK style

52 views Asked by At

Problem: The menu no longer works after an upgrade with the upgrade-assistant to SDK style

Starting point:

Project type: WPF App (.Net Framework)

Default generated App.xaml

Modified MainWindow.xaml:

<Grid>
    <Menu UsesItemContainerTemplate="True"
          DataContext="{Binding MenuBar}" 
          ItemsSource="{Binding MenuItems}"
          IsMainMenu="True">
        <Menu.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="MenuStyles.xaml" />
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Menu.Resources>
    </Menu>
</Grid>

Modified MainWindow.xaml.cs:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var items = new List<IMenuItemViewModel>();
        items.Add(new CommandMenuItemViewModel("Sub menu 1"));
        items.Add(new SeparatorMenuItemViewModel());
        items.Add(new CommandMenuItemViewModel("Sub menu 2"));
        var popup = new PopupMenuItemViewModel(items);
        var model = new MenuViewModel(new[] { popup });
        this.DataContext = new MainWindowModel(model);
    }
}

public class MainWindowModel
{
    public MainWindowModel(MenuViewModel model)
    {
        this.MenuBar = model;
    }

    public MenuViewModel MenuBar { get; set; }
}

public interface IMenuViewModel { }

public class MenuViewModel : IMenuViewModel
{
    private IList<IMenuItemViewModel> menuItems;

    public MenuViewModel(IList<IMenuItemViewModel> menuItems)
    {
        this.menuItems = menuItems;
    }

    public IList<IMenuItemViewModel> MenuItems => this.menuItems;
}

public interface IMenuItemViewModel { }

public class CommandMenuItemViewModel : IMenuItemViewModel
{
    private string _displayName;

    public CommandMenuItemViewModel(string displayName)
    {
        _displayName = displayName;
    }

    public string DisplayName
    {
        get => _displayName;
        set => _displayName = value;
    }

    private bool _isEnabled = true;

    public bool IsEnabled
    {
        get => _isEnabled;
        set => _isEnabled = value;
    }
}

public class PopupMenuItemViewModel : IMenuItemViewModel
{
    private string _displayName = "Main menu";

    public string DisplayName
    {
        get => _displayName;
        set => _displayName = value;
    }
    private bool _isEnabled = true;

    public bool IsEnabled
    {
        get => _isEnabled;
        set => _isEnabled = value;
    }

    private IList<IMenuItemViewModel> menuItems;

    public PopupMenuItemViewModel(IList<IMenuItemViewModel> menuItems)
    {
        this.menuItems = menuItems;
    }

    public IList<IMenuItemViewModel> MenuItems => this.menuItems;
}

public class SeparatorMenuItemViewModel : IMenuItemViewModel
{
    private string _displayName = "Test 4";

    public string DisplayName
    {
        get => _displayName;
        set => _displayName = value;
    }
    private bool _isEnabled = true;

    public bool IsEnabled
    {
        get => _isEnabled;
        set => _isEnabled = value;
    }
}

added MenuStyles.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:wpfApp2="clr-namespace:WpfApp2">

    <ItemContainerTemplate DataType="{x:Type wpfApp2:CommandMenuItemViewModel}">
        <MenuItem Header="{Binding DisplayName}">
        </MenuItem>
    </ItemContainerTemplate>

    <ItemContainerTemplate DataType="{x:Type wpfApp2:PopupMenuItemViewModel}">
        <MenuItem Header="{Binding DisplayName}" ItemsSource="{Binding MenuItems}" UsesItemContainerTemplate="True" />
    </ItemContainerTemplate>
    
    <ItemContainerTemplate DataType="{x:Type wpfApp2:SeparatorMenuItemViewModel}">
        <Separator Margin="30,2,0,2" />
    </ItemContainerTemplate>

</ResourceDictionary>

Display of the menu

after the upgrade from the old project structure using the upgrade assistant to the new SDK style ("upgrade project features" -> "convert project to SDK style" -> 2 succeeded, 0 failed, 0 skipped)

The menu now only shows the main entry. The submenu entries are no longer displayed or the menu can no longer be expanded.

Display of the menu: SDK style

Content of the project file:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net48</TargetFramework>
    <OutputType>WinExe</OutputType>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <UseWPF>true</UseWPF>
    <ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
    <PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
  </ItemGroup>
</Project>

Everything looks fine, but it doesn't work. Suggestions?

changing target framework does not work:
<TargetFramework>net8.0-windows</TargetFramework>

using ItemContainerTemplateSelector:

ItemsControl.FindResource(resourceKey)

does not find the resource, Application.FindResource does not find anything either

other styles specified in MenuStyle.xaml work and are applied

1

There are 1 answers

1
Noe On

the upgrade assistent is innocent / known wpf bug (since 2020):

Workaround: this seems to work if you remove DataType="{x:Type …}" and put x:Key="{ItemContainerTemplateKey {x:Type …}}" instead.

link to solution