2009-09-18 6 views
6

私はこのマークアップ持っている:私はwindow_loaded方法でこのラインを持っているの背後にあるコードではWPFマルチバインディングが失敗します。どうして?

<GroupBox BorderThickness="2"> 
    <GroupBox.BorderBrush> 
     <SolidColorBrush x:Name="Border"> 
      <SolidColorBrush.Color> 
       <MultiBinding Converter="{StaticResource ConnectionAndLoggedInToBorderBrush}"> 
        <Binding Path="IsConnected"/> 
        <Binding Path="IsLoggedIn"/> 
       </MultiBinding> 
      </SolidColorBrush.Color> 
     </SolidColorBrush> 
    </GroupBox.BorderBrush> 

を:

DataContext = uiManager; 

というUIManagerが接続されているとIsLoggedInという名前の2つのパブリックプロパティを持つタイプのUIManagerのです。

Multibindingによって呼び出されるConverterの値配列がブール値ではなく、値DependencyProperty.UnsetValueを持つため、このコードは起動時に失敗します。

私は以下のマークアップを使用して(そしてコンバータのreturntypeを変更すると)動作します。

<GroupBox BorderThickness="2"> 
    <GroupBox.BorderBrush> 
     <MultiBinding Converter="{StaticResource ConnectionAndLoggedInToBorderBrush}"> 
       <Binding Path="IsConnected"/> 
       <Binding Path="IsLoggedIn"/> 
     </MultiBinding> 
    </GroupBox.BorderBrush> 

コード内のDataContextを通じて結合セットの後ろに最初の例では失敗したが、2番目の1で動作しているようです。どうして? UIManagerのクラス下完全について

public class UIManager:IUIManager 
    { 

     #region Implementation of IUIManager 

     private const string IsLoggedInProperty = "IsLoggedIn"; 
     private bool loggedIn; 
     private readonly object loggedInLock = new object(); 
     public bool IsLoggedIn 
     { 
      get 
      { 
       lock (loggedInLock) 
       { 
        return loggedIn; 
       } 
      } 
      set 
      { 
       lock (loggedInLock) 
       { 
        if(value==loggedIn)return; 
        loggedIn = value; 
        OnPropertyChanged(IsLoggedInProperty); 
       } 
      } 
     } 

     private void OnPropertyChanged(string property) 
     { 
      if(PropertyChanged!=null)PropertyChanged(this,new PropertyChangedEventArgs(property)); 
     } 

     private const string IsConnectedProperty = "IsConnected"; 
     private bool isConnected; 
     private object isConnectedLock = new object(); 
     public bool IsConnected 
     { 
      get 
      { 
       lock (isConnectedLock) 
       { 
        return isConnected; 
       } 
      } 
      set 
      { 
       lock (isConnectedLock) 
       { 
        if(value==isConnected)return; 
        isConnected = value; 
        OnPropertyChanged(IsConnectedProperty); 
       } 
      } 
     } 

     #endregion 

     #region Implementation of INotifyPropertyChanged 

     public event PropertyChangedEventHandler PropertyChanged; 

     #endregion 
    } 

EDIT:失敗XAML用 変換方法(それは値のブール値への変換に失敗した[0]用

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
     { 
      var is_connected = (bool) values[0]; 
      var is_loggedin = (bool) values[1]; 
      return is_loggedin 
         ? is_connected 
          ? Colors.YellowGreen 
          : Colors.Red 
         : Colors.Gray; 
     } 

作業XAML:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
     { 
      var is_connected = (bool) values[0]; 
      var is_loggedin = (bool) values[1]; 
      return is_loggedin 
         ? is_connected 
          ? Brushes.YellowGreen 
          : Brushes.Red 
         : Brushes.Gray; 
     } 
+0

あなたのコンバーターのコードも添付できますか? SolidColorBrush.Colorプロパティの代わりにGroupBoxをブラシに設定すると何が問題になりますか? – bendewey

+0

私はコンバータメソッドを追加しました。 ColorAninmationを実装するには、Colorプロパティを公開する必要があります。これは、マルチバインディングを削除すると、それ自体が最初のXAMLで動作します。 – Dabblernl

答えて

15

問題は0とは関係ありませんまたはコンバーター。 DependencyProperty.UnsetValueは、バインディングに値がないことを意味します。そして実際、あなたがデバッグモードで実行する場合は、Outputウィンドウにバインドエラーを見ることができます:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=IsConnected; DataItem=null; target element is 'SolidColorBrush' (HashCode=17654054); target property is 'Color' (type 'Color') 
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=IsLoggedIn; DataItem=null; target element is 'SolidColorBrush' (HashCode=17654054); target property is 'Color' (type 'Color') 

それでは、ビットをマークアップし、いくつかの診断を適用を簡素化してみましょう:

<GroupBox> 
    <GroupBox.BorderBrush> 
     <SolidColorBrush> 
      <SolidColorBrush.Color> 
       <Binding Path="GroupColor" PresentationTraceSources.TraceLevel="High"/> 
      </SolidColorBrush.Color> 
     </SolidColorBrush> 
    </GroupBox.BorderBrush> 
</GroupBox> 

は添付依存関係プロパティを適用するPresentationTraceSources.TraceLevel私たちは、バインディングがDataContextを見つけて、結合しないことがわかり

System.Windows.Data Warning: 52 : Created BindingExpression (hash=17654054) for Binding (hash=44624228) 
System.Windows.Data Warning: 54 : Path: 'GroupColor' 
System.Windows.Data Warning: 56 : BindingExpression (hash=17654054): Default mode resolved to OneWay 
System.Windows.Data Warning: 57 : BindingExpression (hash=17654054): Default update trigger resolved to PropertyChanged 
System.Windows.Data Warning: 58 : BindingExpression (hash=17654054): Attach to System.Windows.Media.SolidColorBrush.Color (hash=52727599) 
System.Windows.Data Warning: 60 : BindingExpression (hash=17654054): Use Framework mentor <null> 
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source 
System.Windows.Data Warning: 65 : BindingExpression (hash=17654054): Framework mentor not found 
System.Windows.Data Warning: 61 : BindingExpression (hash=17654054): Resolve source deferred 
System.Windows.Data Warning: 91 : BindingExpression (hash=17654054): Got InheritanceContextChanged event from SolidColorBrush (hash=52727599) 
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source 
System.Windows.Data Warning: 66 : BindingExpression (hash=17654054): Found data context element: GroupBox (hash=51393439) (OK) 
System.Windows.Data Warning: 67 : BindingExpression (hash=17654054): DataContext is null 
System.Windows.Data Warning: 91 : BindingExpression (hash=17654054): Got InheritanceContextChanged event from SolidColorBrush (hash=52727599) 
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source 
System.Windows.Data Warning: 65 : BindingExpression (hash=17654054): Framework mentor not found 
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source 
System.Windows.Data Warning: 65 : BindingExpression (hash=17654054): Framework mentor not found 
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source (last chance) 
System.Windows.Data Warning: 65 : BindingExpression (hash=17654054): Framework mentor not found 
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=GroupColor; DataItem=null; target element is 'SolidColorBrush' (HashCode=52727599); target property is 'Color' (type 'Color') 

:いくつかのより多くの出力を生成します失敗する。これは問題ではありません。他の場所でのバインディングのため以来、奇妙です

public Window1() 
{ 
    DataContext = ...; 
    InitializeComponent(); 
} 

:私はDataContextがコンテンツに結合作品を初期化する前に設定されているので、窓のコンストラクタを変更する場合。なぜそこで動作しないのかわからないので、私は回避策しか提供できません。どのような例のために働くことは(そのリソースもGroupBoxにローカルかもしれない)バインディングを持つリソースとしてブラシを作成します

<GroupBox BorderBrush="{DynamicResource resbrush}"> 
    <GroupBox.Resources> 
     <SolidColorBrush x:Key="resbrush"> 
      <SolidColorBrush.Color> 
       <MultiBinding Converter="{StaticResource ConnectionAndLoggedInToBorderBrush}"> 
        <Binding Path="IsConnected"/> 
        <Binding Path="IsLoggedIn"/> 
       </MultiBinding> 
      </SolidColorBrush.Color> 
     </SolidColorBrush> 
    </GroupBox.Resources> 
</GroupBox> 

私はMultiBindingをドロップすると、いくつかの前処理を行うためにかかわらず、お勧めしますUIManagerクラスが何らかの種類のMVVMViewModelの場合はDataContextです。

+0

Kudosでは、コンストラクタ内のDataContextをコードの背後に設定することがそのトリックを行いました。 – Dabblernl

0

これは、MVVMの学習を検討したいという理由からです。このパターンは、モデルとバインディングを抽象化し、DPに大きく依存する必要がなくなります。代わりに、ビューモデルの通知可能なプロパティにバインドするだけで済みます。

MVVMには優れた記事がいくつかありますので、Karl Shifflett、Josh Smith、Marlon Grech、Sacha Barberの作品を読むことから始めてください。

+2

彼はすでにINotifyPropertyChangedクラスにバインドしています。 – gix

1

私の理論。色は構造体です(nullにはできません)。したがって、SolidColorBrush.Color = nullが間違っています。 WPFはSolidColorBrushを作成することができず、例外が発生します。

<GroupBox.BorderBrush> 
    <SolidColorBrush x:Name="Border"> 
     <SolidColorBrush.Color> 
      <MultiBinding Converter="{StaticResource 
          ConnectionAndLoggedInToBorderBrush}"> 
       <Binding Path="IsConnected"/> 
       <Binding Path="IsLoggedIn"/> 
      </MultiBinding> 
     </SolidColorBrush.Color> 
    </SolidColorBrush> 
</GroupBox.BorderBrush> 

BorderBrushはオブジェクトです(nullでもかまいません)。GroupBox.BorderBrush = nullです。

<GroupBox.BorderBrush> 
     <MultiBinding Converter="{StaticResource 
        ConnectionAndLoggedInToBorderBrush}"> 
      <Binding Path="IsConnected"/> 
      <Binding Path="IsLoggedIn"/> 
     </MultiBinding> 
</GroupBox.BorderBrush> 

このSolidColorBrushはオブジェクトではなくFACTORYです。これは必要なときにのみインスタンス化され、その時点でDataContextがすでにアタッチされています。

<GroupBox.Resources> 
     <SolidColorBrush x:Key="resbrush"> 
      <SolidColorBrush.Color> 
       <MultiBinding Converter="{StaticResource 
           ConnectionAndLoggedInToBorderBrush}"> 
        <Binding Path="IsConnected"/> 
        <Binding Path="IsLoggedIn"/> 
       </MultiBinding> 
      </SolidColorBrush.Color> 
     </SolidColorBrush> 
</GroupBox.Resources> 

ちょうど私の2セントです。

奇妙なコンバーターで奇妙なバインディングやアニメーションが必要な場合は、私の記事btwを読むと便利です。 http://www.codeproject.com/KB/WPF/BindingHub.aspx

関連する問題