ICommand MVVM 구현
그래서 제가하고있는이 특정 MVVM 구현에서는 몇 가지 명령이 필요합니다. ICommand 클래스를 하나씩 구현하는 것이 정말 지겨워서 해결책을 찾았지만 그것이 얼마나 좋은지 모르겠으므로 여기에있는 WPF 전문가의 의견은 크게 감사 할 것입니다. 그리고 더 나은 솔루션을 제공 할 수 있다면 더 좋습니다.
내가 한 일은 하나의 ICommand 클래스와 개체를 매개 변수로 사용하는 두 개의 대리자입니다. 하나의 대리자는 무효 (OnExecute의 경우)이고 다른 하나는 Bool (OnCanExecute의 경우)입니다. 따라서 내 ICommand의 생성자 (ViewModel 클래스에 의해 호출 됨)에서 두 메서드를 보내고 각 ICommand 메서드에서 대리자의 메서드를 호출합니다.
정말 잘 작동하지만 이것이 나쁜 방법인지 또는 더 나은 방법이 있는지 확실하지 않습니다. 아래는 완전한 코드입니다. 어떤 입력이라도 대단히 감사하겠습니다. 부정적 일지라도 건설적이어야합니다.
ViewModel :
public class TestViewModel : DependencyObject
{
public ICommand Command1 { get; set; }
public ICommand Command2 { get; set; }
public ICommand Command3 { get; set; }
public TestViewModel()
{
this.Command1 = new TestCommand(ExecuteCommand1, CanExecuteCommand1);
this.Command2 = new TestCommand(ExecuteCommand2, CanExecuteCommand2);
this.Command3 = new TestCommand(ExecuteCommand3, CanExecuteCommand3);
}
public bool CanExecuteCommand1(object parameter)
{
return true;
}
public void ExecuteCommand1(object parameter)
{
MessageBox.Show("Executing command 1");
}
public bool CanExecuteCommand2(object parameter)
{
return true;
}
public void ExecuteCommand2(object parameter)
{
MessageBox.Show("Executing command 2");
}
public bool CanExecuteCommand3(object parameter)
{
return true;
}
public void ExecuteCommand3(object parameter)
{
MessageBox.Show("Executing command 3");
}
}
나는 명령한다:
public class TestCommand : ICommand
{
public delegate void ICommandOnExecute(object parameter);
public delegate bool ICommandOnCanExecute(object parameter);
private ICommandOnExecute _execute;
private ICommandOnCanExecute _canExecute;
public TestCommand(ICommandOnExecute onExecuteMethod, ICommandOnCanExecute onCanExecuteMethod)
{
_execute = onExecuteMethod;
_canExecute = onCanExecuteMethod;
}
#region ICommand Members
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return _canExecute.Invoke(parameter);
}
public void Execute(object parameter)
{
_execute.Invoke(parameter);
}
#endregion
}
이 방법은 거의 동일 칼 Shifflet 입증 을 RelayCommand
경우, Execute
화재가 소정 Action<T>
. 저에게 묻는다면 최고의 솔루션입니다.
public class RelayCommand : ICommand
{
private Predicate<object> _canExecute;
private Action<object> _execute;
public RelayCommand(Predicate<object> canExecute, Action<object> execute)
{
this._canExecute = canExecute;
this._execute = execute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
이것은 다음으로 사용될 수 있습니다 ...
public class MyViewModel
{
private ICommand _doSomething;
public ICommand DoSomethingCommand
{
get
{
if (_doSomething == null)
{
_doSomething = new RelayCommand(
p => this.CanDoSomething,
p => this.DoSomeImportantMethod());
}
return _doSomething;
}
}
}
자세히보기 :
Josh Smith (의 소개 자 RelayCommand
) : 패턴-MVVM 디자인 패턴을 사용하는 WPF 앱
ICommand 인터페이스에 대한 이 기사 를 작성했습니다 .
두 대리자를받는 범용 명령을 만드는 아이디어 : 하나는 호출 될 때 ICommand.Execute (object param)
호출되고 두 번째는 명령을 실행할 수 있는지 여부를 확인합니다 (ICommand.CanExecute (object param))
.
이벤트 전환 방법이 필요합니다 CanExecuteChanged
. 상태 CanExecute()
명령 을 전환하기 위해 사용자 인터페이스 요소에서 호출됩니다 .
public class ModelCommand : ICommand
{
#region Constructors
public ModelCommand(Action<object> execute)
: this(execute, null) { }
public ModelCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return _canExecute != null ? _canExecute(parameter) : true;
}
public void Execute(object parameter)
{
if (_execute != null)
_execute(parameter);
}
public void OnCanExecuteChanged()
{
CanExecuteChanged(this, EventArgs.Empty);
}
#endregion
private readonly Action<object> _execute = null;
private readonly Predicate<object> _canExecute = null;
}
구성 스타일에 대한 규칙으로 명령을 구현하는 방법을 보여주는 간단한 예제 를 방금 만들었습니다 . 그러나 Reflection.Emit ()을 사용할 수 있어야합니다. 지원 코드가 약간 이상해 보일 수 있지만 일단 작성하면 여러 번 사용할 수 있습니다.
괴롭히는 사람:
public class SampleViewModel: BaseViewModelStub
{
public string Name { get; set; }
[UiCommand]
public void HelloWorld()
{
MessageBox.Show("Hello World!");
}
[UiCommand]
public void Print()
{
MessageBox.Show(String.Concat("Hello, ", Name, "!"), "SampleViewModel");
}
public bool CanPrint()
{
return !String.IsNullOrEmpty(Name);
}
}
}
UPDATE: now there seem to exist some libraries like http://www.codeproject.com/Articles/101881/Executing-Command-Logic-in-a-View-Model that solve the problem of ICommand boilerplate code.
@Carlo I really like your implementation of this, but I wanted to share my version and how to use it in my ViewModel
First implement ICommand
public class Command : ICommand
{
public delegate void ICommandOnExecute();
public delegate bool ICommandOnCanExecute();
private ICommandOnExecute _execute;
private ICommandOnCanExecute _canExecute;
public Command(ICommandOnExecute onExecuteMethod, ICommandOnCanExecute onCanExecuteMethod = null)
{
_execute = onExecuteMethod;
_canExecute = onCanExecuteMethod;
}
#region ICommand Members
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return _canExecute?.Invoke() ?? true;
}
public void Execute(object parameter)
{
_execute?.Invoke();
}
#endregion
}
Notice I have removed the parameter from ICommandOnExecute and ICommandOnCanExecute and added a null to the constructor
Then to use in the ViewModel
public Command CommandToRun_WithCheck
{
get
{
return new Command(() =>
{
// Code to run
}, () =>
{
// Code to check to see if we can run
// Return true or false
});
}
}
public Command CommandToRun_NoCheck
{
get
{
return new Command(() =>
{
// Code to run
});
}
}
I just find this way cleaner as I don't need to assign variables and then instantiate, it all done in one go.
ReferenceURL : https://stackoverflow.com/questions/1468791/icommand-mvvm-implementation
'programing' 카테고리의 다른 글
Windows에서 pip가 사용하는 CA 저장소에 사용자 지정 CA 루트 인증서를 추가하는 방법은 무엇입니까? (0) | 2021.01.14 |
---|---|
Java Iterable을 Scala Iterable로 어떻게 변환 할 수 있습니까? (0) | 2021.01.14 |
스택 가비지가 Java에서 수집됩니까? (0) | 2021.01.14 |
"불법 한 정의 시작"을주는 Scala (0) | 2021.01.14 |
Clojure에서 벡터 앞에 추가하는 관용적 방법은 무엇입니까? (0) | 2021.01.14 |