12

ほとんどの WPF mvvm アプリケーションはICommand、ビュー モデルで使用しています。しかし、それは参照していSystem.Windows.Inputます。System.Windows.Inputそのため、ビューモデルは名前空間と密接に結合されています。私の理解によれば、view-model は通常の C# winform アプリケーションまたは asp.net アプリケーションで使用できるはずです。

通常、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または、ビューモデルから名前空間を削除する方法はありますか?

4

3 に答える 3

6

このアプローチに関する提案はありますか?

これは、間接的に実装している場合でも、実装する必要があるため、まだあなたSystem.Windows.Inputを切り離しません。RelayCommandICommand

ViewModel 内での実装ICommandは、実用的にするために必要になる傾向があるものの 1 つです。理想的には、ICommand(または同様のインターフェイス) は、XAML 固有ではない名前空間に実装されていました。そうは言っても、Portable Class Libraries内で直接サポートされているため、一般的な XAML ほど特定のフレームワーク (WPF、Silverlight、Phone など) に結び付けられていません。

于 2013-03-12T19:20:29.370 に答える
6

必要に応じて、ViewModel を ICommand に結合するのを避けるのは非常に簡単です。おそらく悪い考えではありませんが、WPF はいつか MFC に取って代わられるでしょう。やり過ぎ?たぶん、しかしここに方法があります:

あなたの見解では:

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

ViewModel を DataContext に挿入し、View Model からネイティブ コマンドの責任を負います。

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を使用していることに注意してください。INotifyPropertyChanged は System.dll です。

次に、このコントラクトをバインドします。

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

...ネイティブの Command オブジェクトを提供するものに。

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

ほら、切り離されたコマンド。

ランニング

また、注入は最初のアプリケーションの開始時に行われることに注意してください。ViewModel は、選択した IoC コンテナーから切り離されます。

于 2013-03-12T20:46:20.663 に答える
2

まあ、理論的には、あなたはほとんど正しいです。ICommand が完全に UI プラットフォームに依存しないのは素晴らしいことです。

しかし、実用的な観点から言えば、WPF アプリで MVVM を使用している場合は、とにかく WPF のデータバインディングおよびデータテンプレート機能にかなり依存している可能性がかなりあります。そのようなものの上に WinForms UI を貼り付けようとすると、かなりの追加の労力が必要になる可能性があります。

過去にかなり大規模な WPF/MVVM プロジェクトに取り組んできました。MVVM は、UI の特定の詳細をコードから分離する方法であると考えました。WinForms/ASP.NET などに切り替えるためではなく、UI のルック アンド フィールを変更できるようにするためです (つまり、編集します)。 ViewModel を変更する必要はありません。この点で、MVVM は完璧に機能しました。

複数の種類のプロジェクト間でコードを共有することを本当に懸念している場合は、ビュー モデルではなく、一般的な「ビジネス レイヤー」タイプのクラス ライブラリに共通のコードを配置することをお勧めします。

于 2013-03-12T20:00:11.663 に答える