C# 使用Catel命令更改CanExecuteChange上的内存泄漏
我分析了一个使用Catel作为MVVM框架的WPF应用程序,在一个ViewModel中,我看到了两个保留路径 现在,我在一个附加到上下文菜单的行为中创建这样的RadMenuItem,它们被定义为C# 使用Catel命令更改CanExecuteChange上的内存泄漏,c#,wpf,mvvm,catel,dotmemory,C#,Wpf,Mvvm,Catel,Dotmemory,我分析了一个使用Catel作为MVVM框架的WPF应用程序,在一个ViewModel中,我看到了两个保留路径 现在,我在一个附加到上下文菜单的行为中创建这样的RadMenuItem,它们被定义为 protected virtual IEnumerable<RadMenuItem> GetRowMenuItems(RadContextMenu contextMenu) { var rowItems = new List<RadMenuItem>()
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")) }
};
受保护的虚拟IEnumerable GetRowMenuItems(RadContextMenu contextMenu)
{
var rowItems=新列表();
RadMenuItem saveSettings=新RadMenuItem
{
Tag=“force”,
Header=CoreResources.LBL\u保存\u设置,
Command=DefaultRTViewContextMenuCommand.SaveLayoutDataCommand,
CommandParameter=AssociatedObject,
图标=新图像{Source=新位图图像(新Uri(“pack://application:,,,/IF.Tesoreria.Client.WPF.Core;component/Media/save.png”))}
};
添加(保存设置);
RadMenuItem loadSettings=新RadMenuItem
{
Tag=“force”,
Header=CoreResources.LBL\u加载\u设置,
Command=DefaultRTViewContextMenuCommand.LoadLayoutDataCommand,
CommandParameter=AssociatedObject,
图标=新图像{Source=新位图图像(新Uri(“pack://application:,,,/IF.Tesoreria.Client.WPF.Core;component/Media/load.png”))}
};
现在,在中定义了这些命令
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);
}
public类defaultrtviewContextMenuCommand
{
公共静态命令SaveLayoutDataCommand{get;private set;}
公共静态命令LoadLayoutDataCommand{get;private set;}
私有静态void OnLoadLayoutCommandExecute(FlexGridCommandParameter网格)
{
参数.IsNotNull(()=>grid);
var dependencyrolver=dependencyrolvermanager.Default;
var openFileService=dependencysolver.defaultdependencysolver.Resolve();
openFileService.Filter=“Gridview设置文件|*.flexgrid”;
if(openFileService.DetermineFile())
{
//用户选择了一个文件
使用(var fs=File.OpenRead(openFileService.FileName))
{
GridViewPersistenceHelper.LoadLayout(grid.grid,fs,null);
}
}
}
私有静态无效OnSaveLayoutCommandExecute(FlexGridCommandParameter网格)
{
参数.IsNotNull(()=>grid);
var dependencyrolver=dependencyrolvermanager.Default;
var saveFileService=dependencysolver.defaultdependencysolver.Resolve();
saveFileService.Filter=“Gridview设置文件|*.flexgrid”;
if(saveFileService.DetermineFile())
{
//用户选择了一个文件
使用(var fs=File.OpenWrite(saveFileService.FileName))
{
GridViewPersistenceHelper.SaveLayout(grid.grid,fs);
}
}
}
静态默认RTViewContextMenuCommand()
{
viewModelFactory=ServiceLocator.Default.ResolveType();
portfolioService=ServiceLocator.Default.ResolveType();
pkInstrumentsService=ServiceLocator.Default.ResolveType();
SaveLayoutDataCommand=new命令(OnSaveLayoutCommandExecute,=>true);
LoadLayoutDataCommand=new命令(OnLoadLayoutCommandExecute,=>true);
}
我做错了什么?
谢谢
对我来说很有用。你可以反编译并看到,当你这样做时,菜单项会从命令的CanExecuteChanged中注销自己。RadMenuItem似乎订阅了ICommand.CanExecuteChanged事件。因此命令绑定到GUI并通过事件委托保存菜单项。仍然无法判断你做错了什么,因为你没有描述ribe您期望的行为。当我关闭视图时,我期望viewmodel也会被释放…但由于这两个引用,它仍然处于活动状态…但我无法理解如何正确地处理它们?不,第二种方式不好…您订阅了事件-您应该取消订阅。检查RadMenuItem是否实现IDisposable接口,以及它是否NSSubscribes ICommand.CanExecuteChanged in Dispose方法。在.net profiler中搜索了许多小时,我也得到了这个。您的问题证实了我的正确性。您找到了任何解决方法吗?我注意到RadMenuItem根本没有实现IDisposableNo方法。。。
radMenuItem.Command = null;