0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Prism の Commanding を学ぶ

Posted at

RRISM LIBRARY の Documentation から Commanding の箇所を学んでみます。

そのまんまの翻訳ですが、メモとして。
日本語がへんなところは英語に戻ってそれなりに理解。。。

In addition to providing access to the data to be displayed or edited in the view, the ViewModel will likely define one or more actions or operations that can be performed by the user. Actions or operations that the user can perform through the UI are typically defined as commands. Commands provide a convenient way to represent actions or operations that can be easily bound to controls in the UI. They encapsulate the actual code that implements the action or operation and help to keep it decoupled from its actual visual representation in the view.
(Google翻訳)
ビューで表示または編集するデータへのアクセスを提供することに加えて、ViewModelは、ユーザーが実行できる1つ以上のアクションまたは操作を定義する可能性があります。 ユーザーがUIを介して実行できるアクションまたは操作は、通常、コマンドとして定義されます。 コマンドは、UIのコントロールに簡単にバインドできるアクションまたは操作を表す便利な方法を提供します。 これらは、アクションまたは操作を実装する実際のコードをカプセル化し、ビュー内の実際の視覚的表現から切り離しておくのに役立ちます。

Commands can be visually represented and invoked in many different ways by the user as they interact with the view. In most cases, they are invoked as a result of a mouse click, but they can also be invoked as a result of shortcut key presses, touch gestures, or any other input events. Controls in the view are data bound to the ViewModels's commands so that the user can invoke them using whatever input event or gesture the control defines. Interaction between the UI controls in the view and the command can be two-way. In this case, the command can be invoked as the user interacts with the UI, and the UI can be automatically enabled or disabled as the underlying command becomes enabled or disabled.
(Google翻訳)
コマンドは、ユーザーがビューを操作するときに、さまざまな方法で視覚的に表現して呼び出すことができます。 ほとんどの場合、マウスクリックの結果として呼び出されますが、ショートカットキーの押下、タッチジェスチャ、またはその他の入力イベントの結果としても呼び出されます。 ビュー内のコントロールは、ViewModelのコマンドにバインドされたデータであり、ユーザーは、コントロールが定義する入力イベントまたはジェスチャーを使用してそれらを呼び出すことができます。 ビューのUIコントロールとコマンドの間の相互作用は双方向です。 この場合、ユーザーがUIを操作するときにコマンドを呼び出すことができ、基になるコマンドが有効または無効になると、UIを自動的に有効または無効にすることができます。

The ViewModel can implement commands as a Command Object (an object that implements the ICommand interface). The view's interaction with the command can be defined declaratively without requiring complex event handling code in the view's code-behind file. For example, certain controls inherently support commands and provide a Command property that can be data bound to an ICommand object provided by the ViewModel. In other cases, a command behavior can be used to associate a control with a command method or command object provided by the ViewModel.
(Google翻訳)
ViewModelは、コマンドオブジェクト(ICommandインターフェイスを実装するオブジェクト)としてコマンドを実装できます。 ビューとコマンドの相互作用は、ビューの分離コードファイルに複雑なイベント処理コードを必要とせずに宣言的に定義できます。 たとえば、特定のコントロールは本質的にコマンドをサポートし、ViewModelによって提供されるICommandオブジェクトにデータバインドできるCommandプロパティを提供します。 他の場合では、コマンド動作を使用して、コントロールを、ViewModelによって提供されるコマンドメソッドまたはコマンドオブジェクトに関連付けることができます。

Implementing the ICommand interface is straightforward. Prism provides the DelegateCommand implementation of this interface that you can readily use in your applications.
(Google翻訳)
ICommandインターフェイスの実装は簡単です。 Prismは、アプリケーションですぐに使用できるこのインターフェイスのDelegateCommand実装を提供します。

NOTE
DelegateCommand can be found in the Prism.Commands namespace which is located in the Prism.Core NuGet package.
(Google翻訳)
注意
DelegateCommandは、Prism.Core NuGetパッケージにあるPrism.Commands名前空間にあります。

Creating a DelegateCommand

image.png

The Prism DelegateCommand class encapsulates two delegates that each reference a method implemented within your ViewModel class. It implements the ICommand interface's Execute and CanExecute methods by invoking these delegates. You specify the delegates to your ViewModel methods in the DelegateCommand class constructor. For example, the following code example shows how a DelegateCommand instance, which represents a Submit command, is constructed by specifying delegates to the OnSubmit and CanSubmit ViewModel methods. The command is then exposed to the view via a read-only property that returns a reference to the DelegateCommand.
(Google翻訳)
Prism DelegateCommandクラスは、それぞれがViewModelクラス内に実装されたメソッドを参照する2つのデリゲートをカプセル化します。 これらのデリゲートを呼び出すことにより、ICommandインターフェイスのExecuteメソッドとCanExecuteメソッドを実装します。 DelegateCommandクラスコンストラクターでViewModelメソッドへのデリゲートを指定します。 たとえば、次のコード例は、OnSubmitおよびCanSubmit ViewModelメソッドにデリゲートを指定することにより、Submitコマンドを表すDelegateCommandインスタンスがどのように構築されるかを示しています。 次に、コマンドは、DelegateCommandへの参照を返す読み取り専用プロパティを介してビューに公開されます。

public class ArticleViewModel
{
    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand<object>(Submit, CanSubmit);
    }

    void Submit(object parameter)
    {
        //implement logic
    }

    bool CanSubmit(object parameter)
    {
        return true;
    }
}

When the Execute method is called on the DelegateCommand object, it simply forwards the call to the method in your ViewModel class via the delegate that you specified in the constructor. Similarly, when the CanExecute method is called, the corresponding method in your ViewModel class is called. The delegate to the CanExecute method in the constructor is optional. If a delegate is not specified, DelegateCommand will always return true for CanExecute.

The DelegateCommand class is a generic type. The type argument specifies the type of the command parameter passed to the Execute and CanExecute methods. In the preceding example, the command parameter is of type object. A non-generic version of the DelegateCommand class is also provided by Prism for use when a command parameter is not required, and is defined as follows:
(Google翻訳)
ExecuteメソッドがDelegateCommandオブジェクトで呼び出されると、コンストラクターで指定したデリゲートを介してViewModelクラスのメソッドへの呼び出しが転送されます。 同様に、CanExecuteメソッドが呼び出されると、ViewModelクラスの対応するメソッドが呼び出されます。 コンストラクターのCanExecuteメソッドへのデリゲートはオプションです。 デリゲートが指定されていない場合、DelegateCommandはCanExecuteに対して常にtrueを返します。

DelegateCommandクラスはジェネリック型です。 type引数は、ExecuteメソッドとCanExecuteメソッドに渡されるコマンドパラメータのタイプを指定します。 上記の例では、コマンドパラメータのタイプはオブジェクトです。 DelegateCommandクラスの非ジェネリックバージョンも、コマンドパラメーターが不要な場合に使用するためにPrismによって提供され、次のように定義されています。

public class ArticleViewModel
{
    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(Submit, CanSubmit);
    }

    void Submit()
    {
        //implement logic
    }

    bool CanSubmit()
    {
        return true;
    }
}

NOTE
The DelegateCommand deliberately prevents the use of value types (int, double, bool, etc). Because ICommand takes an object, having a value type for T would cause unexpected behavior when CanExecute(null) is called during XAML initialization for command bindings. Using default(T) was considered and rejected as a solution because the implementor would not be able to distinguish between a valid and defaulted values. If you wish to use a value type as a parameter, you must make it nullable by using DelegateCommand> or the shorthand ? syntax (DelegateCommand).
(Google翻訳)
注意
DelegateCommandは、意図的に値型(int、double、boolなど)の使用を禁止します。 ICommandはオブジェクトを取得するため、Tの値型を持つと、コマンドバインディングのXAML初期化中にCanExecute(null)が呼び出されたときに予期しない動作が発生します。 実装者が有効な値とデフォルト値を区別できないため、default(T)の使用はソリューションとして検討され、拒否されました。 値タイプをパラメーターとして使用する場合は、DelegateCommand >または省略形を使用して、値タイプをNULL可能にする必要があります。 構文(DelegateCommand )。

Invoking DelegateCommands from the View

There are a number of ways in which a control in the view can be associated with a command object provided by the ViewModel. Certain WPF, Xamarin.Forms, and UWP controls can be easily data bound to a command object through the Command property.
(Google翻訳)
ビューのコントロールを、ViewModelによって提供されるコマンドオブジェクトに関連付ける方法はいくつかあります。 特定のWPF、Xamarin.Forms、およびUWPコントロールは、Commandプロパティを使用して、コマンドオブジェクトに簡単にデータバインドできます。

<Button Command="{Binding SubmitCommand}" CommandParameter="OrderId"/>

A command parameter can also be optionally defined using the CommandParameter property. The type of the expected argument is specified in the DelegateCommand generic declaration. The control will automatically invoke the target command when the user interacts with that control, and the command parameter, if provided, will be passed as the argument to the command's Execute method. In the preceding example, the button will automatically invoke the SubmitCommand when it is clicked. Additionally, if a CanExecute delegate is specified, the button will be automatically disabled if CanExecute returns false, and it will be enabled if it returns true.
(Google翻訳)
コマンドパラメータは、CommandParameterプロパティを使用してオプションで定義することもできます。 予期される引数のタイプは、DelegateCommand ジェネリック宣言で指定されています。 ユーザーがそのコントロールを操作すると、コントロールは自動的にターゲットコマンドを呼び出し、コマンドパラメーターが指定されている場合は、引数としてコマンドのExecuteメソッドに渡されます。 前の例では、ボタンをクリックすると、SubmitCommandが自動的に呼び出されます。 さらに、CanExecuteデリゲートが指定されている場合、CanExecuteがfalseを返すとボタンは自動的に無効になり、trueを返すとボタンは有効になります。

Raising Change Notifications

The ViewModel often needs to indicate a change in the command's CanExecute status so that any controls in the UI that are bound to the command will update their enabled status to reflect the availability of the bound command. The DelegateCommand provides several ways to send these notifications to the UI.
(Google翻訳)
多くの場合、ViewModelはコマンドのCanExecuteステータスの変更を示す必要があります。これにより、コマンドにバインドされているUIのコントロールは、バインドされたコマンドの可用性を反映するために、有効なステータスを更新します。 DelegateCommandは、これらの通知をUIに送信するいくつかの方法を提供します。

RaiseCanExecuteChanged

Use the RaiseCanExecuteChanged method whenever you need to manually update the state of the bound UI elements. For example, when the IsEnabled property values changes, we are calling RaiseCanExecuteChanged in the setter of the property to notify the UI of state changes.
(Google翻訳)
バインドされたUI要素の状態を手動で更新する必要がある場合は常に、RaiseCanExecuteChangedメソッドを使用します。 たとえば、IsEnabledプロパティの値が変更されると、プロパティのセッターでRaiseCanExecuteChangedを呼び出して、UIに状態の変更を通知します。

        private bool _isEnabled;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                SetProperty(ref _isEnabled, value);
                SubmitCommand.RaiseCanExecuteChanged();
            }
        }

ObservesProperty

In cases where the command should send notifications when a property value changes, you can use the ObservesProperty method. When using the ObservesProperty method, whenever the value of the supplied property changes, the DelegateCommand will automatically call RaiseCanExecuteChanged to notify the UI of state changes.
(Google翻訳)
プロパティ値が変更されたときにコマンドが通知を送信する必要がある場合は、ObservesPropertyメソッドを使用できます。 ObservesPropertyメソッドを使用する場合、提供されたプロパティの値が変更されると、DelegateCommandは自動的にRaiseCanExecuteChangedを呼び出して、状態の変更をUIに通知します。

public class ArticleViewModel : BindableBase
{
    private bool _isEnabled;
    public bool IsEnabled
    {
        get { return _isEnabled; }
        set { SetProperty(ref _isEnabled, value); }
    }

    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(Submit, CanSubmit).ObservesProperty(() => IsEnabled);
    }

    void Submit()
    {
        //implement logic
    }

    bool CanSubmit()
    {
        return IsEnabled;
    }
}

NOTE
You can chain-register multiple properties for observation when using the ObservesProperty method. Example: ObservesProperty(() => IsEnabled).ObservesProperty(() => CanSave).
(Google翻訳)
注意
ObservesPropertyメソッドを使用すると、複数のプロパティをチェーン登録して監視できます。 例:ObservesProperty(()=> IsEnabled).ObservesProperty(()=> CanSave)。

ObservesCanExecute

If your CanExecute is the result of a simple Boolean property, you can eliminate the need to declare a CanExecute delegate, and use the ObservesCanExecute method instead. ObservesCanExecute will not only send notifications to the UI when the registered property value changes but it will also use that same property as the actual CanExecute delegate.
(Google翻訳)
CanExecuteが単純なブール型プロパティの結果である場合、CanExecuteデリゲートを宣言する必要をなくし、代わりにObservesCanExecuteメソッドを使用できます。 ObservesCanExecuteは、登録されたプロパティ値が変更されたときにUIに通知を送信するだけでなく、実際のCanExecuteデリゲートと同じプロパティを使用します。

public class ArticleViewModel : BindableBase
{
    private bool _isEnabled;
    public bool IsEnabled
    {
        get { return _isEnabled; }
        set { SetProperty(ref _isEnabled, value); }
    }

    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(Submit).ObservesCanExecute(() => IsEnabled);
    }

    void Submit()
    {
        //implement logic
    }
}

WARNING
Do not attempt to chain-register ObservesCanExecute methods. Only one property can be observed for the CanExcute delegate.
(Google翻訳)
警告
ObservesCanExecuteメソッドをチェーン登録しないでください。 CanExcuteデリゲートで監視できるプロパティは1つだけです。

Implementing a Task-Based DelegateCommand

In today's world of async/await, calling asynchronous methods inside of the Execute delegate is a very common requirement. Everyone's first instinct is that they need an AsyncCommand, but that assumption is wrong. ICommand by nature is synchronous, and the Execute and CanExecute delegates should be considered events. This means that async void is a perfectly valid syntax to use for commands. There are two approaches to using async methods with DelegateCommand.
(Google翻訳)
今日の非同期/待機の世界では、実行デリゲート内で非同期メソッドを呼び出すことは非常に一般的な要件です。 全員の最初の本能は、AsyncCommandが必要であるということですが、その仮定は間違っています。 ICommandは本質的に同期であり、実行デリゲートとCanExecuteデリゲートはイベントと見なされます。 つまり、async voidはコマンドに使用するのに完全に有効な構文です。 DelegateCommandで非同期メソッドを使用するには、2つの方法があります。

Option 1:

public class ArticleViewModel
{
    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(Submit);
    }

    async void Submit()
    {
        await SomeAsyncMethod();
    }
}

Option 2:

public class ArticleViewModel
{
    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(async ()=> await Submit());
    }

    Task Submit()
    {
        return SomeAsyncMethod();
    }
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?