One menu item needs to change the state (enabled/disabled) of some other items in the menu.

3 posts, 1 answers
  1. Mart71
    Mart71 avatar
    4 posts
    Member since:
    Jan 2014

    Posted 20 Jan 2014 Link to this post

    Hello,

    I'm using RadMenu in a "C#-WPF-MVVM-Microsoft Prism" application.

    I have made a very simple example that reproduces the problem. In this example, I have a "File" menu with two items: "Open" and "Close".
    At first, I want the "Open" item to be enabled, and the "Close" item to be disabled since there is nothing to close.

    When the user clicks on "Open", the open operation is called via a Prism DelegateCommand. 
    After this, I want the "Open" item to be disabled and the "Close" item to be enabled.

    If you run the example, you will see that now both items are disabled.

    MainWindow.xaml:
    <Window x:Class="WpfApplication1.MainWindow"
            xmlns:Effects="clr-namespace:Telerik.Windows.Controls.ColorEditor.Effects;assembly=Telerik.Windows.Controls.Input"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
       <Window.Resources>
          <Style x:Key="MenuStyle" TargetType="telerik:RadMenuItem">
             <Setter Property="Header" Value="{Binding Name}"/>
             <Setter Property="ItemsSource" Value="{Binding ItemsCollection}"/>
             <Setter Property="Command" Value="{Binding MenuItemCommand}"/>
          </Style>
       </Window.Resources>
        <
    Grid>
          <telerik:RadMenu x:Name="radMenu" ItemsSource="{Binding MenusCollection}" ItemContainerStyle="{StaticResource MenuStyle}" HorizontalAlignment="Left" VerticalAlignment="Top">
          </telerik:RadMenu>
       </Grid>
    </Window>


    MainWindow.xaml.ca:
    namespace WpfApplication1
       {
       /// <summary>
       /// Interaction logic for MainWindow.xaml
       /// </summary>
       public partial class MainWindow : Window
          {
          ViewModel _viewModel = new ViewModel();
          public MainWindow()
             {
             InitializeComponent();
             base.DataContext = _viewModel;
             }
          }
       }


    ViewModel.cs :
    using System;
    using System.ComponentModel;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.Practices.Prism.Events;
    using Microsoft.Practices.Prism.ViewModel;
    using Microsoft.Practices.Prism.Commands;
     
    namespace WpfApplication1
       {
       public delegate void MenuActionDelegate(object command);
       public delegate bool MenuIsEnabledDelegate(object command);
     
       public class ViewModel : NotificationObject
          {
          public ViewModel()
             {
             _menusCollection = new ObservableCollection<MyMenuItem>();
     
             MyMenuItemInfo menuInfo = new MyMenuItemInfo("File", 1, null, null);
             MyMenuItemInfo itemInfo = new MyMenuItemInfo("Open", 10, MenuAction, IsClosed);
             AddMenu(menuInfo, itemInfo);
     
             itemInfo = new MyMenuItemInfo("Close", 20, MenuAction, IsOpened);
             AddMenu(menuInfo, itemInfo);
             }
     
          private bool _isOpen;
          public bool IsOpened(object command)
             {
             return _isOpen;
             }
          public bool IsClosed(object command)
             {
             return !_isOpen;
             }
     
          public void MenuAction(object command)
             {
             if ((int)command == 10)
                {
                _isOpen = true;
                }
             else if ((int)command == 20)
                {
                _isOpen = false;
                }
             }
     
          private ObservableCollection<MyMenuItem> _menusCollection { get; set; }
          public ObservableCollection<MyMenuItem> MenusCollection
             {
             get { return this._menusCollection; }
             }
     
          public void AddMenu(MyMenuItemInfo menuInfo, MyMenuItemInfo itemInfo)
             {
             bool menuExists = false;
             MyMenuItem theMenu = null;
             foreach (MyMenuItem menu in _menusCollection)
                {
                if (menu.Name == menuInfo.Name)
                   {
                   theMenu = menu;
                   menuExists = true;
                   }
                }
     
             if (menuExists)
                {
                theMenu.AddMenuItem(itemInfo);
                }
             else
                {
                MyMenuItem newMenu = new MyMenuItem(menuInfo);
                newMenu.AddMenuItem(itemInfo);
                _menusCollection.Add(newMenu);
                }
             }
          }
     
     
       public class MyMenuItem
          {
          public MyMenuItem(MyMenuItemInfo itemInfo)
             {
             _itemInfo = itemInfo;
             _menuItemsCollection = new ObservableCollection<MyMenuItem>();
             MenuItemCommand = new DelegateCommand(MenuItemExecute, MenuItemCanExecute);
             }
     
          public void AddMenuItem(MyMenuItemInfo itemInfo)
             {
             MyMenuItem menuItem = new MyMenuItem(itemInfo);
             _menuItemsCollection.Add(menuItem);
             }
     
          private ObservableCollection<MyMenuItem> _menuItemsCollection { get; set; }
          public ObservableCollection<MyMenuItem> ItemsCollection
             {
             get { return _menuItemsCollection; }
             }
     
          public DelegateCommand MenuItemCommand { get; private set; }
     
          public void MenuItemExecute()
             {
             if (_itemInfo.MenuAction != null)
                {
                _itemInfo.MenuAction.Invoke(_itemInfo.Command);
                MenuItemCommand.RaiseCanExecuteChanged();
                }
             }
     
          private bool MenuItemCanExecute()
             {
             bool itemIsEnabled = true;
             if (_itemInfo.IsEnabled != null)
                {
                itemIsEnabled = _itemInfo.IsEnabled.Invoke(_itemInfo.Command);
                }
             return itemIsEnabled;
             }
     
          private MyMenuItemInfo _itemInfo;
          public string Name
             {
             get { return _itemInfo.Name; }
             set { _itemInfo.Name = value; }
             }
          }
     
     
     
       public class MyMenuItemInfo
          {
          public MyMenuItemInfo(string name, object command, MenuActionDelegate menuAction, MenuIsEnabledDelegate isEnabled)
             {
             Name = name;
             Command = command;
             MenuAction = menuAction;
             IsEnabled = isEnabled;
             }
     
          public string Name
             {
             get { return _name; }
             set { _name = value; }
             }
          public object Command
             {
             get { return _command; }
             set { _command = value; }
             }
          public MenuActionDelegate MenuAction
             {
             get { return _menuAction; }
             set { _menuAction = value; }
             }
          public MenuIsEnabledDelegate IsEnabled
             {
             get { return _isEnabled; }
             set { _isEnabled = value; }
             }
     
          private string _name;
          private object _command;
          private MenuActionDelegate _menuAction;
          private MenuIsEnabledDelegate _isEnabled;
          }
       }



    Did I missed something?

    Thanks
    Mart71
  2. Answer
    Kalin
    Admin
    Kalin avatar
    1209 posts

    Posted 23 Jan 2014 Link to this post

    Hello Mart,

    You can achieve the desired scenario by enabling/disabling the MenuItems or the Commands themselves. For the first approach you will need to have a bool property bound the IsEnabled property in MenuItemStyle in XAML. For the second approach you will need to change the CanExecute value of the commands attached to the custom MenuItems when the command is executed. I have prepared and attached a sample project which demonstrates the second approach.

    Hope this helps.

    Regards,
    Kalin
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  3. UI for WPF is Visual Studio 2017 Ready
  4. Mart71
    Mart71 avatar
    4 posts
    Member since:
    Jan 2014

    Posted 24 Jan 2014 Link to this post

    Hello Kalin,

    I have implemented something similar a few days ago. I was worried about performances, because my application contains a menus hierarchy with many menu items. Finally, it seems to be OK.

    Yout answer give me the confirmation that this is the good approach.
    Thanks,
    Mart
Back to Top