2

I was profiling a WPF application that uses Catel as MVVM Framework and I've seen that in a ViewModel I've got 2 retention path as enter image description here

Now I create such RadMenuItem in a behavior I attach to the context menu and they're defined as

protected virtual IEnumerable<RadMenuItem> GetRowMenuItems(RadContextMenu contextMenu)
    {
        var rowItems = new List<RadMenuItem>();

        RadMenuItem saveSettings = new RadMenuItem
        {
            Tag = "force",
            Header = CoreResources.LBL_SAVE_SETTINGS,
            Command = DefaultRtViewContextMenuCommands.SaveLayoutDataCommand,
            CommandParameter = AssociatedObject,

            Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/IF.Tesoreria.Client.WPF.Core;component/Media/save.png")) }
        };

        rowItems.Add(saveSettings);

        RadMenuItem loadSettings = new RadMenuItem
        {
            Tag = "force",
            Header = CoreResources.LBL_LOAD_SETTINGS,
            Command = DefaultRtViewContextMenuCommands.LoadLayoutDataCommand,
            CommandParameter = AssociatedObject,
            Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/IF.Tesoreria.Client.WPF.Core;component/Media/load.png")) }
        };

Now The commands are defined in

    public class DefaultRtViewContextMenuCommands
{
   public static Command<FlexGridCommandParameter> SaveLayoutDataCommand { get; private set; }
    public static Command<FlexGridCommandParameter> LoadLayoutDataCommand { get; private set; }

    private static void OnLoadLayoutCommandExecute(FlexGridCommandParameter grid)
    {
        Argument.IsNotNull(() => grid);

        var dependencyResolver = DependencyResolverManager.Default;
        var openFileService = dependencyResolver.DefaultDependencyResolver.Resolve<IOpenFileService>();
        openFileService.Filter = "Gridview setting file|*.flexgrid";
        if (openFileService.DetermineFile())
        {
            // User selected a file
            using (var fs = File.OpenRead(openFileService.FileName))
            {
                GridViewPersistenceHelper.LoadLayout(grid.Grid, fs, null);
            }
        }
    }

    private static void OnSaveLayoutCommandExecute(FlexGridCommandParameter grid)
    {
        Argument.IsNotNull(() => grid);

        var dependencyResolver = DependencyResolverManager.Default;
        var saveFileService = dependencyResolver.DefaultDependencyResolver.Resolve<ISaveFileService>();
        saveFileService.Filter = "Gridview setting file|*.flexgrid";
        if (saveFileService.DetermineFile())
        {
            // User selected a file
            using (var fs = File.OpenWrite(saveFileService.FileName))
            {
                GridViewPersistenceHelper.SaveLayout(grid.Grid, fs);
            }
        }
    }

 static DefaultRtViewContextMenuCommands()
    {
        viewModelFactory = ServiceLocator.Default.ResolveType<IViewModelFactory>();
        portfolioService = ServiceLocator.Default.ResolveType<IPortfoliosService>();
        pkInstrumentsService = ServiceLocator.Default.ResolveType<IPkInstrumentsService>();

        SaveLayoutDataCommand = new Command<FlexGridCommandParameter>(OnSaveLayoutCommandExecute,_=>true);
        LoadLayoutDataCommand = new Command<FlexGridCommandParameter>(OnLoadLayoutCommandExecute,_=>true);
    }

What am I doing wrong? Thanks

advapi
  • 3,661
  • 4
  • 38
  • 73
  • It seems that RadMenuItem subscribes ICommand.CanExecuteChanged event. So command is bound to the GUI and holds menu item via event delegate. Still can't tell what are you doing wrong because you did not describe what behaviour you expect. – Ed Pavlov Jan 25 '17 at 14:21
  • when I close the view I expect that viewmodel goes disposed as well.... but it's still alive due to those 2 references...but I can't understand how to dispose them correctly? – advapi Jan 25 '17 at 14:23
  • No, the second way is bad... You subscribed event - you should unsubscribe it. Check if RadMenuItem implements IDisposable interface and if it unsubscribes ICommand.CanExecuteChanged in Dispose method. – Ed Pavlov Jan 25 '17 at 15:13
  • Many hours of searching in .net profiler, I got this too. Your question confirms that I was correct. Did you found any workaround? I noticed that RadMenuItem doesn’t implement IDisposable – Yitzchak Mar 14 '18 at 10:46
  • No way at all... – advapi Mar 14 '18 at 13:52

1 Answers1

1
radMenuItem.Command = null;

Works for me. You can decompile and see that when you do it, the menu item unregisters himself from the Command’s CanExecuteChanged

Yitzchak
  • 3,303
  • 3
  • 30
  • 50