2009-03-16 4 views

답변

22

차이점은 RelayCommand는 대리인을 받아 들일 수 있다는 점입니다. ViewModel 외부에서 RelayCommand를 정의 할 수 있습니다. 그런 다음 ViewModel은 명령을 만들어 컨트롤과 같은 UI 개체에 바인딩 할 때 명령에 대리자를 추가 할 수 있습니다. 위임자는 ViewModel의 범위에서 정의 된대로 ViewModel의 private 변수에 액세스 할 수 있습니다.

ViewModel에 포함 된 코드의 양을 줄이려면 ViewModel 내부에서 중첩 된 클래스로 Routed 명령을 정의해야합니다. 이 두 기능은 다른 점에서 유사합니다.

67

RoutedCommand은 WPF의 일부이며, RelayCommand은 WPF Disciple, Josh Smith에 의해 작성되었습니다.

심각하게도 RS Conley는 몇 가지 차이점을 설명했습니다. 주요 차이점은 RoutedCommand는 명령에 대한 CommandBinding이 발견 될 때까지 RoutedEvent를 사용하여 트리를 통해 라우팅하는 ICommand 구현입니다. 반면 RelayCommand는 라우팅을 수행하지 않고 대신 일부 대리자를 직접 실행합니다. M-V-VM 시나리오에서는 RelayCommand (Prism의 DelegateCommand)가 아마도 더 나은 선택 일 것입니다. MVVM에서 RelayCommand 및 RoutedCommand의 사용에 관한

34

나를 위해 주요 차이점은 다음과 같다 :

RelayCommand 당신이 (모든 클래스에서 명령을 구현할 수 있습니다 코드의

위치 ICommand의-속성으로 위임자와 함께).이 명령은 일반적으로 명령을 호출하는 컨트롤에 데이터 바인딩됩니다. 이 클래스는 ViewModel입니다. 라우팅 된 명령을 사용하는 경우 메서드가 CommandBinding 요소의 특성에 의해 지정되므로 컨트롤의 코드 숨김 코드에있는 명령과 관련된 메서드를 구현해야합니다. 엄격한 MVVM은 "비어있는"코드 숨김 파일을 가지고 있음을 의미한다고 가정 할 때 실제로 MVVM에서 표준 라우트 된 명령을 사용할 가능성은 없습니다.

무엇 RS 콘리 RelayCommand 당신이 ViewModel에 외부 RelayCommand는 옳은 정의 할 수 있습니다,하지만 우선 당신이 안에 그것을 RoutedCommand하지 않는 뷰 모델을 을 정의 할 수 있다고 말했다. 한편 라우팅

, (전에 말했듯이) RelayCommands이 인터페이스는 하나의 뷰 모델을 기반으로 한, 문제가되지 않습니다 어떤 나무를 통해 라우팅을 지원하지 않습니다. 그렇지 않은 경우, 예를 들어, 독자적인 viewModel를 가지는 아이템의 콜렉션을 가져, 부모 엘리먼트의 각 아이템에 대해서 ViewModel의 커멘드를 동시에 호출하고 싶은 경우는, 라우팅을 사용할 필요가 있습니다 (CompositeCommands도 참조) .

전체적으로 엄격한 MVVM에서는 표준 RoutedCommands를 사용할 수 없습니다. RelayCommands는 MVVM에 적합하지만 필요한 라우팅을 지원하지 않습니다.

+0

설명의 추가 깊이와 CompositeCommands에 대한 언급을 보내 주셔서 감사합니다. –

13

저는 RoutedCommands가 엄격한 MVVM에서 완벽하게 합법적이라고 주장합니다. RelayCommands는 단순성 때문에 종종 선호되지만 RoutedCommands는 때로 조직적인 이점을 제공합니다.예를 들어 공유 ICommand 인스턴스에 연결하는 여러 가지보기가 기본 CommandModel에 해당 명령을 직접 노출하지 않고 수행되도록 할 수 있습니다.

참고로 엄격한 MVVM이 코드 숨김 사용을 금지하지 않는다는 점을 기억하십시오. 그것이 사실이라면 뷰에서 사용자 지정 종속성 속성을 결코 정의 할 수 없습니다!

  1. 사용자 정의 명령에 대한 정적 RoutedCommand 인스턴스를 선언 : 다음 단계를 수행 할 수있는 엄격한 MVVM 프레임 워크 내에서 RoutedCommand를 사용하기 위해서는

    . ApplicationCommands 클래스에서 미리 정의 된 명령을 사용하려는 경우이 단계를 건너 뛸 수 있습니다. 예를 들어 요구 (의 ViewModel 명령 기능을 구현 중 예) 적절한 뷰 모델에 바인딩 귀하의 의견의

    <Button Command="{x:Static local:MyCommands.MyCustomCommand}" /> 
    
  2. 하나 :

    public static class MyCommands { 
        public static RoutedCommand MyCustomCommand = new RoutedCommand(); 
    } 
    
  3. 은 RoutedCommand 사용하여 XAML에 원하는 뷰를 연결 당신의 ViewModel의 구현에 바인딩됩니다 사용자 정의하는 DependencyProperty를 노출합니다 :

    public partial class MainView : UserControl 
    { 
        public static readonly DependencyProperty MyCustomCommandProperty = 
         DependencyProperty.Register("MyCustomCommand", 
         typeof(ICommand), typeof(MainView), new UIPropertyMetadata(null)); 
    
        public ICommand MyCustomCommand { 
         get { return (ICommand)GetValue(MyCustomCommandProperty); } 
         set { SetValue(MyCustomCommandProperty, value); } 
        } 
    
  4. 목 전자 같은보기는 XAML에서 1 단계에서 RoutedCommand에 자신을 결합해야합니다

    <UserControl.CommandBindings> 
        <CommandBinding Command="{x:Static local:MyCommands.MyCustomCommand}" 
            CanExecute="MyCustomCommand_CanExecute" 
            Executed="MyCustomCommand_Executed" 
            /> 
    </UserControl.CommandBindings> 
    

    을에서 코드 숨김보기 위해 관련 이벤트 핸들러는 3 단계에서 선언 된 종속성 속성에서 ICommand의 위임합니다 :

    private void MyCustomCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) { 
        var command = this.MyCustomCommand; 
        if (command != null) { 
         e.Handled = true; 
         e.CanExecute = command.CanExecute(e.Parameter); 
        } 
    } 
    private void MyCustomCommand_Executed(object sender, ExecutedRoutedEventArgs e) { 
        var command = this.MyCustomCommand; 
        if (command != null) { 
         e.Handled = true; 
         command.Execute(e.Parameter); 
        } 
    } 
    
  5. 마지막으로, XAML에서 사용자 지정 종속성 속성에 (AN ICommand의이어야 함) 귀하의 ViewModel의 명령 구현을 바인딩 :

    <local:MainView DataContext="{Binding MainViewModel}" 
           MyCustomCommand="{Binding CustomCommand}" /> 
    

이 방법의 장점은 ViewModel이 ICommand 인터페이스의 단일 구현 만 제공하면됩니다 (또한 RelayCommand 일 수도 있음). 필요하지 않아도 RouteCommand를 통해 뷰를 연결할 수 있음 그 ViewModel에 직접 바인드됩니다.

불행히도 ICommand.CanExecuteChanged 이벤트가 작동하지 않는다는 단점이 있습니다. ViewModel이 뷰에서 CanExecute 속성을 새로 고치려면 CommandManager.InvalidateRequerySuggested()를 호출해야합니다.