Creating a Dynamic WPF Menu : Part 3

Search for a command to run...

No comments yet. Be the first to comment.
A series of articles imported from my previous blog hosted at https://www.talkingitthrough.co.uk.
When I first started out as developer, the usefulness of interfaces was one of the things I never quite worked out. However, as I got more into design and testing then everything suddenly became much more clear. By developing to interfaces we can m...
Introduction Semantic Kernel is an open-source framework by Microsoft that integrates machine learning and natural language processing to build AI applications. It offers tools for tasks like language understanding, text generation, and semantic sear...

Introduction In the earlier articles in my PDF Splitter series, we have relied on the inbuild .NET libraries to handle working with PDF files in MAUI, but these only support opening and displaying of PDF files. Now that we are looking to save our new...

Introduction In the previous article, we created a PDF model and service to allow us to work with and track PDF pages. The next step is to build the UI to allow us to interact with the service. To do this we will create a single 'view' and a 'view mo...

Introduction For the fourth article in my PDF Splitter series, we will start working with PDF files in .NET MAUI. Helpfully, MAUI contains a lot of useful PDF tools for reading PDF files out of the box, so we do not need to use any additional librari...

Introduction In this article, I'm going to introduce basic navigation into my .NET MAUI PDF Splitter application. If you're following my PDF Splitter Application series, you will have a simple application based on the out-the-box .NET template with a...

In the first part of this series, I introduced the menu service and the menu item base class.
In the second part I introduced the command implementation and the hierarchical data template.
In this third and final part, I will bring it all together.
I have created 4 different menu items, a top-level File menu, a menu item responsible for adding a third, which can then remove itself. A fourth item will disable itself when clicked.
Top level file menu:
class FileMenuItem : MenuItem
{
public FileMenuItem() : base("File", "\_File")
{
}
public override void OnItemSelected()
{
// Top level item, we don't need to do anything.
}
}
A menu item which can add a third:
class AddMenuItem : MenuItem
{
MenuService menuService;
public AddMenuItem(MenuService menuService) : base ("AddMenu", "Add MenuItem")
{
this.menuService = menuService;
}
public override void OnItemSelected()
{
RemoveMenuItem removeItem = new RemoveMenuItem(this.menuService);
menuService.AddMenuItem(removeItem, "File");
}
}
A menu item which can remove itself:
class RemoveMenuItem : MenuItem
{
private MenuService menuService;
public RemoveMenuItem(MenuService menuService) : base ("Remove", "Remove Me")
{
this.menuService = menuService;
}
public override void OnItemSelected()
{
menuService.RemoveMenuItem(this);
}
}
A menu item which can disable itself:
class DisableMenuItem : MenuItem
{
private bool enabled = true;
public DisableMenuItem() : base("DisableMenuItem", "Disable Me!")
{
}
public override void OnItemSelected()
{
this.enabled = false;
}
public override bool ItemCanBeSelected()
{
return this.enabled;
}
}
The view model that initiates the service and starts building the menu’s:
class MainWindowViewModel : INotifyPropertyChanged
{
MenuService menuService;
public MainWindowViewModel()
{
this.menuService = new MenuService();
FileMenuItem fileMenu = new FileMenuItem();
AddMenuItem addMenu = new AddMenuItem(this.menuService);
DisableMenuItem disableableMenuItem = new DisableMenuItem();
menuService.AddMenuItem(fileMenu);
menuService.AddMenuItem(addMenu, "File");
menuService.AddMenuItem(disableableMenuItem, ("File"));
}
public List ParentItems
{
get
{
return this.menuService.GetParentMenuItems();
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
And setting the data context in the view code behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
}
As you can see, most of the hard work is done in the menu item base class, and the file menu service. After that, adding, removing and disabling menu items is very simple, and can be carried out at run time.
This could be extended to allow separators using a style converter, and an IsSeparator boolean, and additionally it would be easy to include a sort order property which the service can apply/use to order the items, but I have left them out to keep the code clean and straightforward.
The post Creating a Dynamic WPF Menu : Part 3 appeared first on Talking I.T. Through.