program tip

MVVM 라우팅 및 릴레이 명령

radiobox 2020. 10. 19. 07:56
반응형

MVVM 라우팅 및 릴레이 명령


RoutedCommandRelayCommand 의 차이점은 무엇입니까 ? RoutedCommand를 언제 사용하고 MVVM 패턴에서 RelayCommand를 언제 사용합니까?


RoutedCommand 는 WPF의 일부이며 RelayCommand 는 WPF Disciple, Josh Smith;)에 의해 생성되었습니다.

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


MVVM에서 RelayCommand 및 RoutedCommand를 사용하는 것과 관련하여 저에게 가장 큰 차이점은 다음과 같습니다.

코드 위치

RelayCommand를 사용하면 모든 클래스 (대리자가있는 ICommand 속성)에서 명령을 구현할 수 있습니다. 그러면 일반적으로 명령을 호출하는 컨트롤에 데이터 바인딩됩니다. 이 클래스는 ViewModel 입니다. 라우팅 된 명령을 사용하는 경우 메서드는 CommandBinding 요소의 특성에 의해 지정되므로 컨트롤 코드 숨김 에서 명령과 관련된 메서드를 구현해야합니다 . 엄격한 MVVM이 "빈"코드 숨김 파일을 의미한다고 가정하면 실제로 MVVM에서 표준 라우팅 명령을 사용할 가능성이 없습니다.

RS Conley가 말한대로 RelayCommand를 사용하면 ViewModel 외부에서 RelayCommand를 정의 할 수 있지만 먼저 RoutedCommand가 아닌 ViewModel 내부 에서 정의 할 수 있습니다 .

라우팅

반면에 RelayCommands는 인터페이스가 단일 viewModel을 기반으로하는 한 트리를 통한 라우팅을 지원하지 않습니다 (앞서 언급했듯이), 이는 문제가되지 않습니다. 그렇지 않은 경우, 예를 들어 자신의 viewModel이있는 항목 모음이 있고 부모 요소에서 각 항목에 대해 자식 ViewModel의 명령을 한 번에 호출하려는 경우 라우팅을 사용해야합니다 (CompositeCommands 참조). .

대체로 표준 RoutedCommand는 엄격한 MVVM에서 사용할 수 없다는 것입니다. RelayCommand는 MVVM에 적합하지만 필요한 라우팅을 지원하지 않습니다.


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

ViewModel 내부에 Routed 명령을 중첩 된 클래스로 정의하는 추세이므로 ViewModel에 포함 된 코드의 양을 줄이는 데 사용됩니다. 두 가지의 기능은 그렇지 않으면 비슷합니다.


RoutedCommands는 엄격한 MVVM에서 완벽하게 합법적이라고 주장합니다. RelayCommand는 단순성 때문에 선호되는 경우가 많지만 RoutedCommand는 조직적 이점을 제공하는 경우가 있습니다. 예를 들어, 기본 ViewModel에 해당 명령을 직접 노출하지 않고 여러 다른 뷰를 공유 ICommand 인스턴스에 연결할 수 있습니다.

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

엄격한 MVVM 프레임 워크 내에서 RoutedCommand를 사용하려면 다음 단계를 따르십시오.

  1. 사용자 지정 명령에 대한 정적 RoutedCommand 인스턴스를 선언합니다. ApplicationCommands 클래스에서 미리 정의 된 명령을 사용하려는 경우이 단계를 건너 뛸 수 있습니다. 예를 들면 :

    public static class MyCommands {
        public static RoutedCommand MyCustomCommand = new RoutedCommand();
    }
    
  2. XAML을 사용하여 RoutedCommand에 원하는 뷰를 연결합니다.

    <Button Command="{x:Static local:MyCommands.MyCustomCommand}" />
    
  3. 적합한 ViewModel에 바인딩 된 뷰 중 하나 (즉, 명령 기능을 구현하는 ViewModel)는 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. 동일한 뷰가 1 단계의 RoutedCommand에 자신을 바인딩해야합니다. XAML에서 :

    <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. 마지막으로, ViewModel의 명령 구현 (ICommand이어야 함)을 XAML의 사용자 지정 종속성 속성에 바인딩합니다.

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

The advantage of this approach is that your ViewModel only needs to provide a single implementation of the ICommand interface (and it can even be a RelayCommand), while any number of Views can attach to it via the RoutedCommand without needing to be directly bound to that ViewModel.

Unfortunately there is a downside in that the ICommand.CanExecuteChanged event will not work. When your ViewModel wants the View to refresh the CanExecute property then you must call CommandManager.InvalidateRequerySuggested().

참고URL : https://stackoverflow.com/questions/650010/mvvm-routed-and-relay-command

반응형