0

Caliburn Micro を使用して WPF MVVM アプリを作成しています。ScreenConductor であるシェル ビュー モデルのビューにあるメニュー (リボン) に一連のボタンがあります。現在アクティブなスクリーン ビュー モデルに基づいて、アクティブなスクリーンで使用できる場合はリボン ボタンを無効/有効にし、アクティブなスクリーンでアクションまたはコマンドを呼び出したいと考えています。

これは一般的なシナリオのようです。この動作を作成するためのパターンはありますか?

4

5 に答える 5

1

現在アクティブな画面でサポートされているコマンドを確認する代わりに、逆のことをしないのはなぜですか。アクティブな画面に、サポートするすべてのコントロールをメニューまたはリボン タブに入力させます (独自のユーザーを挿入させます)。コントロールは完全なメニューまたはリボン タブである可能性があります)、これにより、現在アクティブな画面で操作できるコントロールのみがユーザーに表示されるため、ユーザー エクスペリエンスも向上します。

于 2013-03-10T19:37:14.200 に答える
1

編集:あなたの質問をもう一度見るだけで、これは見た目よりもはるかに簡単だと思います

私が見ることができる唯一の問題は、子 VM にハンドラー (およびガード) メソッドがないということは、現在アクティブな VM に実装されていないボタンが引き続き有効になることです。

CM のデフォルトの戦略は、(アクション テキストの解析後に) 一致するメソッド名を見つけようとし、見つからない場合はボタンをそのままにしておくことです。デフォルトでボタンが無効になるようにその動作をカスタマイズする場合は、シェルにコマンド ボタンを実装するだけで簡単に動作させることができます。コマンド ターゲットをアクティブなアイテムに設定するようにしてください。

シェルでボタンを定義し、アクティブな子 VM を指すターゲットがあることを確認します。

<Button cal:Message.Attach="Command1" cal:Action.TargetWithoutContext="{Binding ActiveItem}" />

次に、通常どおり子 VM にメソッドを実装します。

public void Command1() { }

オプションで CanXX ガード

public bool CanCommand1 
{ 
    get 
    { 
        if(someCondition) return false; 

        return true; 
    } 
}

これよりもはるかに複雑にならないと仮定すると、それはうまくいくはずです

CM のソースをざっと見て、これに適したものを思いつくことができるかどうかを確認します。

編集:

func をカスタマイズして、ActionMessage.ApplyAvailabilityEffect必要な効果を得ることができます。bootstrapper.Configure() メソッド (または起動時のどこか) で次を使用します。

        ActionMessage.ApplyAvailabilityEffect = context =>
        {
            var source = context.Source;

            if (ConventionManager.HasBinding(source, UIElement.IsEnabledProperty))
            {
                return source.IsEnabled;
            }

            if (context.CanExecute != null)
            {
                source.IsEnabled = context.CanExecute();
            }
            // Added these 3 lines to get the effect you want
            else if (context.Target == null)
            {
                source.IsEnabled = false;
            }
            // EDIT: Bugfix - need this to ensure the button is activated if it has a target but no guard
            else 
            {
                source.IsEnabled = true;
            }

            return source.IsEnabled;
        };

これは私にとってはうまくいくようです-コマンドにバインドできなかったメソッドのターゲットがないため、その場合はIsEnabledfalseに設定しました。これは、アクティブな子 VM で一致するシグネチャを持つメソッドが見つかった場合にのみボタンをアクティブにします - 明らかに、使用する前に適切なテストを行ってください :)

于 2013-03-12T00:55:37.973 に答える
0

このシナリオでは、次のように Caliburn.Micro イベント集計を使用します。

  • ScreenCapabilities一連のブール属性で名前を付けたクラスを作成します (例: CanSaveCanLoadなど)。
  • ScreenActivatedMessageタイプのプロパティで名前が付けられたメッセージを作成しますScreenCapabilities
  • サブスクライブする (ハンドルする) リボンのビュー モデルを作成します。ScreenActivatedMessage

リボン ビュー モデルのHandleメソッドで、提供された に基づいてローカルの CanXXX プロパティを設定しScreenCapabilitiesます。

次のようになります (コードは手で入力され、テストされていません)。

public class ScreenCapabilities
{
  public bool CanSave { get; set; }
  // ...
}

public class ScreenActivatedMessage
{
  public ScreenCapabilities ScreenCapabilities { get; set; }
  // ...
}

public class RibbonViewModel : PropertyChangedBase, IHandle<ScreenActivatedMessage>
{
  private bool _canSave;
  public bool CanSave
  {
    get { return _canSave; }
    set { _canSave = value; NotifyPropertyChanged(() => CanSave); }
  }

  // ...

  public void Handle(ScreenActivatedMessage message)
  {
    CanSave = message.ScreenCapabilities.CanSave;
    // ...
  }
}

次に、適切な場所で、画面が変わったら、メッセージを公開します。詳細については、Caliburn.Micro wikiを参照してください。

于 2013-03-07T08:16:18.850 に答える
0

シェル ビュー モデルのコマンドごとに、メソッドと付随するブール プロパティを作成します。(例については、以下のコードを参照してください。) Caliburn.Micro の規則により、それらは自動的にボタンに結び付けられます。次に、ビューを変更して再評価するときに、ブール型プロパティのプロパティ変更イベントを発生させるだけです。

たとえば、[保存] ボタンがあるとします。xaml でのそのボタンの名前は Save であり、ビュー モデルでは、CanSave ブール値プロパティと共に Save メソッドを使用します。下記参照:

public void Save()
{
    var viewModelWithSave = ActiveItem as ISave;
    if (viewModelWithSave != null) viewModelWithSave.Save();
}

public bool CanSave { get { return ActivateItem is ISave; } }

次に、コンダクターで、アクティブな画面を変更するたびに を呼び出しますNotifyOfPropertyChange(() => CanSave);。これを行うと、アクティブな画面がそのコマンドを処理できるかどうかに応じて、ボタンが無効または有効になります。この例では、アクティブな画面が を実装していない場合、ISave[保存] ボタンは無効になります。

于 2013-03-07T01:20:22.140 に答える
0

シェル ビュー モデルでアクティブな画面のプロパティ (ActiveScreen としましょう) を定義します。また、DeleteButton、AddButton などの各ボタンのプロパティがあるとします。Screen は、スクリーンのビューモデルです。

    private Screen activeScreen;

    public Screen ActiveScreen
    {
        get
        {
            return activeScreen;
        }
        set
        {
            activeScreen= value;

            if (activeScreen.Name.equals("Screen1"))
            {
                 this.AddButton.IsEnabled = true; 
                 this.DeleteButton.IsEnabled = false; 
            }
            if else (activeScreen.Name.equals("Screen2"))
            {
                 this.AddButton.IsEnabled = true; 
                 this.DeleteButton.IsEnabled = true; 
            }

            NotifyPropertyChanged("ActiveScreen");
        }
    }
于 2013-03-07T10:44:01.840 に答える