4

コマンドにバインドされたいくつかの ComboBoxItems を持つ ComboBox を含むカスタム SplitButton 実装があります。コマンドの Name および Text プロパティにバインドすることはできますが、ComboBoxItem のIsEnabledプロパティをコマンドのCanExecuteメソッドの結果にバインドする方法はありません。これはメソッドであるためです。メソッドにバインドするために知らない構文がありますか、それとも CanExecute にバインドするのに役立つトリックがありますか。

ところで、カスタム ValueConverter を使用することを考えましたが、CanExecute がプロパティではなく、コマンドがビジネス オブジェクトではないため、CanExecute が再評価されたときにおそらく更新を受け取らないことに気付きました。カスタム SplitButton コントロール内でのみ使用するには、この時点でコマンド用の ViewModel を作成する必要があるかもしれないと考えていますが、それは少しやり過ぎに思えます。

4

4 に答える 4

1

ItemContainerStyle(ComboBoxItemスタイル)内にボタン(ICommandにバインドされたコントロールテンプレートにボタンがない場合)を配置し、コマンドをそれにバインドし、トリガーを追加してButton.IsEnabledをチェックし、その値をComboBoxItemに設定できます。そこで、ここでは、CanExeuteからIsEnabledを取得するためだけにButtonをCommandSourceとして使用しました。ボタンの高さと幅をゼロに設定できます

 <ControlTemplate....>
   <Grid ...
       <Button x:Name="dummyButton" Command="{Binding YourCommand}" ....
           ......
   </Grid>

   <ControlTemplate.Triggers>
      <Trigger SourceName="dummyButton" Property="IsEnabled" Value="False">
        <Setter Property="IsEnabled" Value="False"/>
      </Trigger>
   </ControlTemplate.Triggers>
于 2010-02-23T18:29:18.610 に答える
1

MSDN フォーラムでこの議論を見つけました。WPF博士は、この正確な問題を解決するためにアタッチされたビヘイビアーの使用を推奨していました。彼は、それがどのように使用されるかの例を以下に示しました。

<Grid behaviors:CommandBehaviors.EnablingCommand="{x:Static commands:testcommand.test}">  
  . . .  
</Grid> 

このソリューションは非常に優れているように思えますが、このタイプの動作がどのように実装され、何が含まれているかを正確に理解するために時間を割くことができませんでした。誰かが詳しく説明したい場合は、別の方法で行ってください。このオプションを検討する機会があれば、この回答を詳細に修正します。

于 2010-02-24T13:37:31.220 に答える
1

ViewModel による別のソリューション。以下は、ViewModel を使用して問題を解決する方法です。そして、気の利いた NotifyPropertyChanged メソッドは、私の基本 ViewModel クラスの一部であることに注意してください。

public class RoutedUICommandViewModel : ViewModel
{
    private RoutedUICommand _command;
    private IInputElement _target;

    public string Name { get { return _command.Name; } }

    public string Text { get { return _command.Text; } }

    public bool CanExecute
    {
        get
        {
            return _command.CanExecute(null, _target);
        }
    }

    public RoutedUICommand Command { get { return _command; } }

    public RoutedUICommandViewModel(ReportCommand command, IInputElement target)
    {
        _command = command;
        _target = target;
        _command.CanExecuteChanged += _command_CanExecuteChanged;
    }

    private void _command_CanExecuteChanged(object sender, EventArgs e)
    {
        base.NotifyPropertyChanged(() => this.CanExecute);
    }
}
于 2010-02-23T21:07:44.387 に答える
0

コードでこの問題を解決する方法は、PreviewMouseDown イベントの ComboBox にイベント ハンドラーを追加することでした。ハンドラーは次のとおりです。

private void comboBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            ViewModel vm = this.DataContext as ViewModel;

            if (vm != null)
            {
                if (!vm.CanChangeSelection())
                {
                    e.Handled = true;
                    vm.RespondToFailedAttemptChangeUnits();
                }
            }
        }

これは、1 つの場所でのみ行う必要がある場合に最適です。このようなページがたくさんあると、少し面倒になるかもしれません。

また、私は MVVM パターンに従っていますが、私は純粋主義者ではありません。これは、文字どおりではないにしても、MVVM の精神に従う優れた実用的なソリューションであると考えています。

于 2011-05-27T15:12:45.967 に答える