您可以编写自己的命令。
这是我用于命令的基类。
它有一些非常基本的东西,让生活更轻松。
- 该
Execute
方法接受一个对象,因此您将能够传递数组
- 可以轻松传入视图模型,即您将在命令中使用的视图模型(大多数情况下,如果您不需要,请将其刷出)
- 更改后的处理程序利用 CommandManager。这真的很有帮助
也许你想改变一些事情。我添加的所有内容都在那里,因为它非常有帮助。(尤其是视图模型)
public abstract class CommandBase : ICommand
{
public abstract bool CanExecute(object o);
public abstract void Execute(object o);
public PropertyChangedBase ViewModel { get; set; }
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
你会有像这样的实现
public class ExampleCommand : CommandBase
{
public ExampleCommand (PropertyChangedBase viewModel)
{
this.ViewModel = viewModel;
}
public override void Execute(object o)
{
// something like
var settings = UnityContainer.Resolve<ISettings>();
settings.MagicValue = (this.ViewModel as ConcreteViewModel).MagicValue;
}
public override bool CanExecute(object o)
{
return true;
}
}
在您的 ViewModel 中,您通过拥有一个属性将命令公开给视图:
public class ExampleViewModel : PropertyChangedBase
{
public ExampleViewModel ()
{
this.DoThisAndThatCommand = new ExampleCommand(this);
}
public CommandBase DoThisAndThatCommand { get; set; }
}
// and in XAML, you can use it like
<Button x:Name="Ok"
Command="{Binding DoThisAndThatCommand }" />
(假设您已通过设置的正确连接ViewModel
和)View
DataContext
View
现在,每当单击按钮时,都会调用命令的执行方法。
您的 ViewModel 就在 中Command
,因此您可以轻松地使用它。
在命令或ViewModel
. 关于 MVVM 的技巧是将 与View
分开,ViewModel
而
.UIElements
ViewModel
如果您没有 PropertyChangedBase(这个是 Caliburn.Micro 附带的),那么我建议您使用一些简单的 INotifyPropertyChanged 实现。
我在这里找到了这个,不过应该是德语
公共抽象类 NotifyPropertyChangedBase : INotifyPropertyChanged { #region < INotifyPropertyChanged > 成员
/// <summary>
/// Is connected to a method which handle changes to a property (located in the WPF Data Binding Engine)
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raise the [PropertyChanged] event
/// </summary>
/// <param name="propertyName">The name of the property</param>
protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
private Dictionary<string, object> propertyValueStorage;
#region Constructor
public NotifyPropertyChangedBase()
{
this.propertyValueStorage = new Dictionary<string, object>();
}
#endregion
/// <summary>
/// Set the value of the property and raise the [PropertyChanged] event
/// (only if the saved value and the new value are not equal)
/// </summary>
/// <typeparam name="T">The property type</typeparam>
/// <param name="property">The property as a lambda expression</param>
/// <param name="value">The new value of the property</param>
protected void SetValue<T>(Expression<Func<T>> property, T value)
{
LambdaExpression lambdaExpression = property as LambdaExpression;
if (lambdaExpression == null)
{
throw new ArgumentException("Invalid lambda expression", "Lambda expression return value can't be null");
}
string propertyName = this.getPropertyName(lambdaExpression);
T storedValue = this.getValue<T>(propertyName);
if (!object.Equals(storedValue, value))
{
this.propertyValueStorage[propertyName] = value;
this.OnPropertyChanged(propertyName);
}
}
/// <summary> Get the value of the property </summary>
/// <typeparam name="T">The property type</typeparam>
/// <param name="property">The property as a lambda expression</param>
/// <returns>The value of the given property (or the default value)</returns>
protected T GetValue<T>(Expression<Func<T>> property)
{
LambdaExpression lambdaExpression = property as LambdaExpression;
if (lambdaExpression == null)
{
throw new ArgumentException("Invalid lambda expression", "Lambda expression return value can't be null");
}
string propertyName = this.getPropertyName(lambdaExpression);
return getValue<T>(propertyName);
}
/// <summary>
/// Try to get the value from the internal dictionary of the given property name
/// </summary>
/// <typeparam name="T">The property type</typeparam>
/// <param name="propertyName">The name of the property</param>
/// <returns>Retrieve the value from the internal dictionary</returns>
private T getValue<T>(string propertyName)
{
object value;
if (propertyValueStorage.TryGetValue(propertyName, out value))
{
return (T)value;
}
else
{
return default(T);
}
}
/// <summary>
/// Extract the property name from a lambda expression
/// </summary>
/// <param name="lambdaExpression">The lambda expression with the property</param>
/// <returns>The extracted property name</returns>
private string getPropertyName(LambdaExpression lambdaExpression)
{
MemberExpression memberExpression;
if (lambdaExpression.Body is UnaryExpression)
{
var unaryExpression = lambdaExpression.Body as UnaryExpression;
memberExpression = unaryExpression.Operand as MemberExpression;
}
else
{
memberExpression = lambdaExpression.Body as MemberExpression;
}
return memberExpression.Member.Name;
}
}
这是非常容易使用!
在您的 ViewModel 中,您必须为 Binding 提供公共属性(这非常重要)并触发更改通知。
这是一个如何使用 INPC (INotifyPropertyChanged) 的基本实现的示例
public class LoginViewModel : NotifyPropertyChangedBase
{
public string UserName { get;set; }
}
这个 INPC 实现会为您调用 NotifyOfPropertyChange,您不必关心它!但是您必须检查最适合您的情况。
在您的问题中,您已经有一个 ViewModelBase。也许您想使用这个而不是上面的。