C# 命令停止执行
我正在制作一个小型MVVM应用程序。它应该接受一个充满C# 命令停止执行,c#,.net,wpf,mvvm,mvvm-light,C#,.net,Wpf,Mvvm,Mvvm Light,我正在制作一个小型MVVM应用程序。它应该接受一个充满Func的类,并显示一个按钮列表,每个按钮执行一个包含Func的命令,并在另一个列表中显示其返回值 该程序一开始运行良好,但在随机按下大量按钮后,它就会停止执行命令。用户界面仍然响应良好。就好像装订断了似的 类有点太多了,所以我在下面的链接中附加了整个项目: 相关代码: namespace AdapterTester.ViewModel { public class MainViewModel : ViewModelBase {
Func
的类,并显示一个按钮列表,每个按钮执行一个包含Func
的命令,并在另一个列表中显示其返回值
该程序一开始运行良好,但在随机按下大量按钮后,它就会停止执行命令。用户界面仍然响应良好。就好像装订断了似的
类有点太多了,所以我在下面的链接中附加了整个项目:
相关代码:
namespace AdapterTester.ViewModel
{
public class MainViewModel : ViewModelBase
{
public ObservableCollection<ViewableRelayCommand> CommandsList { get; set; }
public ObservableCollection<string> Log { get; set; }
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
CommandsList = new ObservableCollection<ViewableRelayCommand>();
Log = new ObservableCollection<string>();
MapCommands();
}
/// <summary>
/// adds a ViewableRelayCommand to the CommandsList
/// </summary>
public void Add(Func<string> iCommand, string CommandName, Func<bool> CanExecute = null)
{
CommandsList.Add(new ViewableRelayCommand()
{
Command = new RelayCommand(() => { Log.Insert(0, "-------------\n" + CommandName + "\n" + (iCommand.Invoke())); }),
CommandName = CommandName
});
}
/// <summary>
/// For Each Func<string> in TestFunctions create a ViewableRelayCommand
/// </summary>
private void MapCommands()
{
var target = new TestFunctions();
var methods = target.GetType().GetMethods().Where(m => m.DeclaringType == typeof(TestFunctions));
foreach (var method in methods)
{
if( (method.ReturnType == typeof(string)) && (method.GetParameters().Length ==0))
{
Func<string> func = (Func<string>)Delegate.CreateDelegate(typeof(Func<string>), target, method);
Add(func, method.Name);
}
}
}
}
public class ViewableRelayCommand : ViewModelBase
{
public RelayCommand Command { get; set; }
/// <summary>
/// The <see cref="CommandName" /> property's name.
/// </summary>
public const string CommandNamePropertyName = "CommandName";
private string _CommandName = "Hello";
/// <summary>
/// Sets and gets the CommandName property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public string CommandName
{
get
{
return _CommandName;
}
set
{
if (_CommandName == value)
{
return;
}
RaisePropertyChanging(CommandNamePropertyName);
_CommandName = value;
RaisePropertyChanged(CommandNamePropertyName);
}
}
}
}
对这样的事情:
List<Action> actions = new List<Action>();
public void Add(Func<string> iCommand, string CommandName, Func<bool> CanExecute = null)
{
Action act = () => { Log.Insert(0, "-------------\n" + CommandName + "\n" + (iCommand.Invoke())); };
actions.Add(act);
CommandsList.Add(new ViewableRelayCommand()
{
Command = new RelayCommand(act)
,
CommandName = CommandName
});
}
List actions=new List();
public void Add(Func-iCommand,string-CommandName,Func-CanExecute=null)
{
Action act=()=>{Log.Insert(0,-----------\n“+CommandName+”\n“+(iCommand.Invoke());};
添加(act);
添加(新的可视RelayCommand()
{
命令=新的中继命令(act)
,
CommandName=CommandName
});
}
因为添加到中继命令的操作没有根
更新更改为我自己的中继命令有帮助。虽然支持Funcs没有
Command = new RelayCommand(() => { Log.Insert(0, "-------------\n" + CommandName + "\n" + (Command.Invoke())); })
改为:
Command = new RelayCommand(() => { Log.Insert(0, "-------------\n"); })
它可以工作,但我不知道为什么不能在Lambda表达式中使用参数(Command和CommandName)?您从命令中调用命令对吗
Command = new RelayCommand(() => { Log.Insert(0, "-------------\n" + CommandName + "\n" + (Command.Invoke())); })
这不是递归的吗
能否尝试从表达式中删除调用?
为什么要从内部调用它?是否使用MVVMLight中的RelayCommand 如果是这样,您可能会遇到GC问题。RelayCommand在内部对其回调使用弱引用 如果您传入的anon函数不是根在其他地方,那么当GC运行时,它可能会被清除 大多数情况下,这不是问题,因为func是对VM的回调,而VM本身的根位于DataContext、ViewModelLocator或其他地方。如果您创建的Func不是根函数,那么这可能是一个问题
根目录这些Func的一种方法是在ViewModel中有一个
列表
,并在创建RelayCommand的同时将它们添加到列表中。修改绑定跟踪级别,如本例所示:并告诉我们,关于该绑定的调试输出是什么。第一次加载后没有任何变化。很抱歉,现在说不。我在编译你的代码时遇到问题,可能是因为你使用了Blend,而我没有?您是否在命令
或内容
绑定上设置了TraceLevel=High
?输出建议为CommandName
打印详细信息。但我们要调试的是命令
。@rook我没有混合。我刚刚使用了mvvm灯光模板。我确实看到按钮停止工作几分钟后,一个线程停止运行,不知道使用C threadno,左边的命令是ViewableRelayCommand参数。右边的命令是Add函数参数。这是一个糟糕的命名,仅此而已。或者让你知道原因的正确性,但是支持使用funcs而不是funcs创建操作的根:)是的,当然,很好这是因为WeakFunc/Action实际上打开了原始func并将值存储在WeakReferences中。
Command = new RelayCommand(() => { Log.Insert(0, "-------------\n"); })
Command = new RelayCommand(() => { Log.Insert(0, "-------------\n" + CommandName + "\n" + (Command.Invoke())); })