WPF MultiBinding失败。为什么?
-
22-07-2019 - |
题
我有这样的标记:
<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称为未充满布尔值,但具有DependencyProperty.UnsetValue的值。
当我使用下面的标记(和改变所述转换器的返回类型)它的工作。
<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;
}
解决方案
问题无关与MultiBinding
或你的转换器。 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
类是某种MVVM
ViewModel
的。
其他提示
我的理论。色彩是结构(不能为空),所以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是对象(可以为空),因此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
这原因是这样,你可能要考虑学习MVVM。这种模式可以帮助您抽象模型和绑定,这样你就不必这么严重依赖移民 - 你可以简单地绑定到一个法定财产在视图模型,而不是
有MVVM上几个优秀的文章,所以我建议你阅读卡尔Shifflett,约什 - 史密斯,马龙格列奇和萨沙理发的作品开始。