2009-09-18 129 views
6

我有这样的标记:WPF MultiBinding失败。为什么?

<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> 

在后面的代码我有该线路window_loaded方法:

DataContext = uiManager; 

UIManager的是,有一个名为IsConnected和IsLoggedIn两个公共属性类型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中的代码绑定集在第一个例子后面会失败,但在第二个作品。为什么?

对于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 
    } 

编辑: 发生故障的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

你可以附上你的转换器代码吗?将GroupBox设置为Brush而不是SolidColorBrush.Color属性有什么问题? – bendewey 2009-09-18 22:23:03

+0

我添加了转换器方法。我需要公开Color属性以便能够实现ColorAninmation。当我删除MultiBinding时,它本身可以与第一个XAML一起使用。 – Dabblernl 2009-09-18 22:54:54

回答

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产生一些输出:

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') 

我们看到的是,结合没有找到DataContext和绑定失败。当我改变窗口的构造函数,以便DataContext正在初始化内容的绑定工作,之前设置:

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

这是因为在其他地方,这并不重要绑定怪异。不知道为什么它不能在那里工作,所以我只能提供解决方法。因为适合的例子是创建笔刷与绑定的资源(即资源也可以是本地的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并在做一些预处理DataContext如果您的UIManager类是某种MVVMViewModel

+0

荣誉,在后面的代码中的构造函数中设置DataContext做了诀窍。 – Dabblernl 2009-09-19 07:39:36

0

出于这样的原因,您可能需要考虑学习MVVM。此模式可帮助您抽象模型和绑定,以便您不必非常依赖DP,只需将其绑定到视图模型中的可通知属性即可。

MVVM上有很多优秀的文章,所以我建议你先看看Karl Shifflett,Josh Smith,Marlon Grech和Sacha Barber的作品。

+2

他已经绑定到INotifyPropertyChanged类。 – gix 2009-09-19 13:38:58

1

我的理论。颜色是结构(不能为空),所以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是object(可以为null),所以GroupBox.BorderBrush = null是OK。

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

这个SolidColorBrush不是一个对象,而是一个工厂。它仅在需要时实例化,并且此时您已经附加了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美分。

阅读我的文章,顺便说一句,可能是有用的,如果你需要一些奇怪的绑定或动画与奇怪的转换器。 http://www.codeproject.com/KB/WPF/BindingHub.aspx