2013-03-12 3 views
10

대부분의 WPF mvvm 응용 프로그램에서는 뷰 모델에 ICommand을 사용하고 있습니다. 그러나 System.Windows.Input을 참조하고 있습니다. 따라서 뷰 모델은 System.Windows.Input 네임 스페이스와 밀접하게 연결됩니다. 내 이해보기 - 모델에 따라 일반적인 C#을 winform 응용 프로그램이나 asp.net 응용 프로그램에서 사용할 수 있어야합니다.보기 모델에서 ICommand를 사용해도 괜찮습니까?

일반적으로 다음 코드 줄을 사용하여 RelayCommand 구현으로 명령에 사용하고 있습니다. 내가 어떤 느낌

private RelayCommand testCommand;// or private ICommand testCommand; 

public ICommand TestCommand 
{ 
    get 
    { 
     return testCommand ?? 
      (testCommand = new RelayCommand(param => Test())); 
    } 
} 

public void Test() 
{ 

} 

우리가 모든 ICommand를 제거하고 대신 RelayCommand를 사용할 필요가있다. 따라서 뷰 모델에서 System.Windows 네임 스페이스를 제거 할 수 있습니다. 최종 코드는 다음과 같습니다.

private RelayCommand testCommand; 

public RelayCommand TestCommand 
{ 
    get 
    { 
     return testCommand ?? 
      (testCommand = new RelayCommand(param => Test())); 
    } 
} 

public void Test() 
{ 

} 

이 접근에 대한 제안 사항은 무엇입니까? 또는 뷰 모델에서 System.Windows 네임 스페이스를 제거 할 수있는 방법이 있습니까?

+0

@BoltClock 'ICommand'는'System.Windows.Input.ICommand'입니다. –

+0

@ 리필 copsey :/facepalm 내가 어떻게 그리워 할 수 있습니다. – BoltClock

+0

'ICommand'는'System.Windows.Input' 안에 있습니다 –

답변

4

이 접근에 대한 제안 사항은 무엇입니까?

이 여전히 RelayCommand로 여전히 간접적으로 구현 될지라도, ICommand를 구현해야합니다 System.Windows.Input에서 당신을 분리하지 않습니다.

ViewModel 내에 ICommand을 구현하는 것은 실용적 일 필요가있는 것들 중 하나입니다. 이상적으로 ICommand (또는 이와 유사한 인터페이스)은 XAML과 관련이없는 네임 스페이스에 구현되었을 것입니다. 즉, Portable Class Libraries 내에서 직접 지원되므로 특정 프레임 워크 (WPF, Silverlight, Phone 등)와 일반적으로 XAML만큼 관련이 없습니다.

+0

휴대용 클래스 라이브러리는 Visual Studio 2012에서만 사용할 수 있습니다. ( –

+0

@ChamikaSandamal 그들은 휴대용 라이브러리 도구를 사용하여 VS 2010에서 작동합니다 참조 : http://msdn.microsoft.com/en-us/library/vstudio/gg597391 v1.100) .aspx –

2

글쎄 이론적으로 말하면, 당신은 꽤 옳습니다. ICommand가 UI 플랫폼에 완전히 영향을받지 않으면 멋질 것입니다.

그러나 실용적인 관점에서 볼 때 WPF 앱에서 MVVM을 사용하는 경우 WPF의 데이터 바인딩 및 데이터 작성 기능에 상당히 의존 할 가능성이 높습니다. WinForms UI를 그 위에 올려 놓으려고하면 많은 노력이 필요할 것입니다.

나는 과거 꽤 큰 WPF/MVVM 프로젝트를 작업 해왔다. 우리는 MVVM을 UI의 특정 세부 사항을 코드에서 분리하는 방법으로 간주했습니다. WinForms/ASP.NET/무엇이든간에 전환 할 수는 없지만 UI의 모양과 느낌을 변경할 수 있습니다 (예 : 편집 XAML)을 사용하여 ViewModel을 변경할 필요가 없습니다. 이 점에서 MVVM은 완벽하게 작동했습니다.

여러 유형의 프로젝트에서 코드를 공유하는 것이 정말 염려되는 경우보기 모델 대신 일반적인 '비즈니스 계층'유형의 클래스 라이브러리에 공통 코드를 삽입하는 것이 좋습니다.

+0

비슷한 접근 방식을 따르는 경향이 있는데, 한 가지 고려해야 할 것은 'UI 종속성'이 뷰 모델의 단위 테스트에 대한로드 블록을 생성하는지 여부입니다. RelayCommand는 문제를 생성하지 않습니다. 그러나 DispatcherTimer를 주입하는 것과 같은 일들은 잠재적으로 일어날 수 있습니다. –

5

원하는 경우 ViewModel을 ICommand에 연결하는 것을 피하는 것이 아주 간단합니다. 아마도 나쁜 생각은 아니지만, WPF는 언젠가 MFC의 길을 간다. 잔인한가요?어쩌면, 그러나 여기 있는 방법 :

보기에

:

<StackPanel> 
    <Button Command="{Binding Path=MyCommand}"> Do it! Kill me Now!</Button> 
    <TextBlock Text="{Binding Path=Message}"></TextBlock> 
</StackPanel> 

이 당신의 DataContext로의 ViewModel을 주입 기본 명령에 대한 책임을,보기 모델의 아웃 :

public class ViewModel : INotifyPropertyChanged 
{ 
    public string Message { get; set; } 
    public object MyCommand { get; set; } 


    public void OnMyCommand(object parameter) 
    { 
     Message += "I Ran something" + Environment.NewLine; 
    } 

    public bool CanMyCommand(object parameter) 
    { 
     return true; 
    } 

    // Injected Native Command handler 
    public ViewModel(ICommandFactory factory) 
    { 
     MyCommand = factory.CreateInstance(OnMyCommand, CanMyCommand); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

참고 FODY ~ weave in 속성 변경 처리기를 사용하고 있습니다. INotifyPropertyChanged는 System.dll btw입니다. 당신에게 기본 Command 개체를 줄 것이다 뭔가 ...

public interface ICommandFactory 
{ 
    object CreateInstance(Action<object> action, Func<object, bool> predicate); 
} 

; 이제

이 계약을 바인딩

public class NativeCommand : ICommand 
{ 
    private readonly Action<object> _action; 
    private readonly Func<object, bool> _predicate; 

    public NativeCommand(Action<object> action, Func<object, bool> predicate) 
    { 
     _action = action; 
     _predicate = predicate; 
    } 

    public bool CanExecute(object parameter) 
    { 
     return _predicate(parameter); 
    } 

    public void Execute(object parameter) 
    { 
     _action(parameter); 
    } 

    public event EventHandler CanExecuteChanged; 
} 


public class NativeCommandFactory : ICommandFactory 
{ 
    public object CreateInstance(Action<object> action, Func<object, bool> predicate) 
    { 
     return new NativeCommand(action, predicate); 
    } 
} 

Bind<ICommandFactory>().To<NativeCommandFactory>();

자보세요

는 명령을 분리.

running

또한 주사는 초기 응용 프로그램 시작시에 이루어집니다 유의하십시오. ViewModel은 선택한 IoC 컨테이너와 분리되어 있습니다.

+0

FODY는 큰 라이브러리이며 이것을 위해 사용하기가 어렵습니다. 제안 해 주셔서 감사합니다. :) –

+0

음, 간략하게하기 위해. 당신은 스스로 속성 변경 핸들러를 구현할 수 있습니다 ... 아, 그리고 fody는 라이브러리가 아닙니다. IL의 제직 ... 커플 링이없고 참조가 없습니다. –

관련 문제