10

ToggleButtonOneWayバインディングを使用してIsCheckedプロパティにバインドされたプロパティを持つを持っています。

<ToggleButton
    Command="{Binding Path=SomeCommand}"
    IsChecked="{Binding Path=SomeProperty, Mode=OneWay}" />

SomeCommandブールSomeProperty値を切り替え、。のイベントPropertyChangedが発生しSomePropertyます。

ビューモデルを変更SomePropertyすると、ToggleButton正しく押し下げられます。ただし、クリックするToggleButtonとバインディングが失われたように見え、の値に従ってボタンがチェックされなくなりますSomeProperty。この問題を解決する方法について何かアイデアはありますか?

4

5 に答える 5

13

元の投稿者の問題を解決するためのシンプルでエレガントな方法があります。ToggleButtonのIsCheckedプロパティを、変更ハンドラーでボタンのIsCheckedを設定する添付可能なプロパティに置き換えます。

namespace TBFix
{
  public class TBExtender
  {
    public static readonly DependencyProperty IsCheckedProperty =
      DependencyProperty.RegisterAttached("IsChecked", 
                                          typeof(bool),
                                          typeof(TBExtender),
                                          new PropertyMetadata(OnChanged));

    public static bool GetIsChecked(DependencyObject obj)
    {
      return (bool)obj.GetValue(IsCheckedProperty);
    }
    public static void SetIsChecked(DependencyObject obj, bool value)
    {
      obj.SetValue(IsCheckedProperty, value);
    }

    private static void OnChanged(DependencyObject o,
                                  DependencyPropertyChangedEventArgs args)
    {
      ToggleButton tb = o as ToggleButton;
      if (null != tb)
        tb.IsChecked = (bool)args.NewValue;
    }
  }
}

XAMLは次のようになります。

<ToggleButton Command="{Binding Path=SomeCommand}"
              TBFix:TBExtender.IsChecked="{Binding Path=SomeProperty,
                                                   Mode=OneWay}" />

編集:ボタンが押されるとIsCheckedプロパティがコードに設定されるため(これはMSがToggleButtonコントロールを実装する方法です)、OPソリューションは機能しません-プロパティを設定すると、バインディングが削除され、機能しなくなります。

アタッチされたプロパティを使用することで、この問題を克服できます。これは、コードで値が割り当てられることがなく、バインディングがそのまま維持されるためです。

于 2011-04-28T17:21:17.293 に答える
7

これは、一方向のデータバインディングを使用する場合の仕様によるものです。添付されたプロパティPresentationTraceSources.TraceLevel=Highをバインディングに追加すると、バインドが切断されたときに表示されます。このリンクでは、問題についても説明しています(解決策は提供されていません):WPFでのデータバインディングのデバッグ

私が通常解決する方法は、ユーザーの操作とコードビハインドのコマンドを使用して、プロパティが変更されたためにコントロールの外観を変更することです。

于 2010-09-22T18:12:14.473 に答える
2

私の知る限り、Sinatrは、少なくとも新しいフレームワークで発生する「非同期」に関して正しいです。

この問題を回避するもう1つの簡単な方法は、mode = onewayを削除し、空のセッターを実装することです。元:

    bool _MyIsEnabled;
    public bool MyIsEnabled
    {
        get { return _MyIsEnabled; }
        set { }
    }

このバインディング設定を使用すると、コマンドバインディング関数から、または必要かどうかから、バッキング変数の値を変更できます。RaisePropertyChangedを呼び出すことを忘れないでください。

于 2018-01-26T15:55:33.060 に答える
1

私も同様の問題を抱えています。

これは「バインディングが失われたように見える」ではありません (以前のフレームワークの問題でない限り)。バインディングは引き続き機能し、そのコマンドの外部でプロパティを変更することで簡単に証明できます(たとえば、別のボタンクリックイベント/コマンドのハンドラーで)。

問題はIsChecked、2つの方法で変更できることです。1)バインディング(SomePropertyボタンの値が変更されると更新されます。2)ユーザー(ユーザーがボタンを押すと変更されますがIsChecked、バインディングは更新さOneWaySomePropertyません)。

そのため、ボタンまたはその逆の場合に非同期が発生する可能性があります。SomeProperty == falseIsChecked == true

パフォーマンスバインディングメカニズムを最適化することは、新しい値が現在と異なるかどうかをチェックすることです。したがって、非同期が発生し、SomePropertyすでに持っている値で更新しようとしても、何も起こりません。

回避策は簡単です:2つのステップでプロパティを更新します

SomeProperty = !set;
SomeProperty = set;

ここsetで、は必要な値です(たとえば、currentの反対SomeProperty)。

于 2016-02-05T11:02:45.697 に答える
0

IsChecked問題の要約は、コマンドとバインディングの間の競合だと思います。私の解決策は、ビューモデルを変更してを公開し、それをプロパティbool?にバインドすることでした。IsCheckedコマンドをにバインドしませんでしたToggleButton。コード内の他の場所で、使用するプロパティを切り替えますSomeCommand

于 2010-09-22T18:13:37.710 に答える