문제

따라서이 특정 MVVM 구현에서는 여러 명령이 필요합니다. 나는 ICOMMAND 클래스를 하나씩 구현하는 데 지쳤으므로 솔루션을 생각해 냈지만 그것이 얼마나 좋은지 모르겠으므로 여기서 WPF 전문가의 입력은 크게 감사 할 것입니다. 더 나은 솔루션을 제공 할 수 있다면 더 나은 것입니다.

내가 한 일은 단일 ICOMMAND 클래스와 두 명의 대의원으로, 객체를 매개 변수로 취하고, 한 대의원은 무효 (OneXecute의 경우), 다른 대표는 다른 부울 (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
}
도움이 되었습니까?

해결책

이것은 방법과 거의 동일합니다 Karl 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;
}

방금 조금 만들었습니다 예시 구성 스타일을 통한 컨벤션에서 명령을 구현하는 방법을 보여줍니다. 그러나 반사가 필요합니다. 지원 코드는 조금 이상하게 보일 수 있지만 한 번 작성하면 여러 번 사용할 수 있습니다.

괴롭히는 사람:

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);
    }
}

}

업데이트: 이제 일부 라이브러리가 존재하는 것 같습니다 http://www.codeproject.com/articles/101881/executing-command-logic-a-view-model Icommand Boilerplate Code의 문제를 해결합니다.

@carlo 나는 당신의 구현을 정말 좋아하지만 내 버전과 내 뷰 모델에서 사용하는 방법을 공유하고 싶었습니다.

먼저 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
}

매개 변수를 제거했습니다 IcommandOnexecute 그리고 IcommandonCanexecute 생성자에 널을 추가했습니다

그런 다음 뷰 모델에서 사용합니다

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
        });
    }
}

변수를 할당 할 필요가없고 인스턴스화 할 필요가 없으므로 이런 방식으로 더 깨끗합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top