WPF数据绑定在绑定整个对象时失败
本文关键字:对象 失败 数据绑定 绑定 WPF | 更新日期: 2023-09-27 18:27:53
在下面的DataTemplate
中,第一个绑定不起作用,而第二个绑定起作用,我想知道为什么。
<local:IsEnabledConverter x:Key="isEnabled"/>
<local:Boolean2TextConverter x:Key="txtConverter"/>
<DataTemplate x:Key="fileinfoTemplate" DataType="{x:Type local:MyFileInfo}">
<StackPanel>
<Label x:Name="1stLabel" Content="{Binding Path=Filename}" IsEnabled="{Binding Path=., Converter={StaticResource isEnabled}}"/> <--- doesn't work
<Label x:Name="2ndLabel" Content="{Binding Path=IfPrint, Converter={StaticResource txtConverter}}" IsEnabled="{Binding Path=IsChecked, ElementName=ckBox}"/> <--- works
<CheckBox x:Name="ckBox" IsChecked="{Binding Path=IfPrint}" IsEnabled="{Binding Path=IsValid}" Style="{StaticResource printCkBox}"/>
</StackPanel>
</DataTemplate>
IsEnabledConverter:
class IsEnabledConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
MyFileInfo f = value as MyFileInfo;
return f.IsValid && f.IfPrint;
}
//... omit ConvertBack NotImplementedException stuff
}
Boolean2TextConverter:
class IsEnabledConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
Boolean b = (Boolean)value;
return b.ToString();
}
//similarly omit ConvertBack here
}
MyFileInfo:的代码
public class MyFileInfo {
public string IfPrint {
get;
set;
}
public string IsValid {
get;
set;
}
...
}
问题:当切换CheckBox
时,第二个Label
变灰并显示"false",或者变为正常并显示"true"。然而,第一个Label
根本没有改变;其IsEnabled
状态假定为两个布尔值的结合,其中一个布尔值被CheckBox
改变。怎么了?(请注意,IsEnabledConverter
在GUI初始化时被调用一次,但在其绑定源更改时不会再次调用。)
这里有两个问题。首先,您必须为ViewModel MyFileInfo
实现INotifyPropertyChanged
。其次,这里必须使用MultiBinding
。因为我认为如果您将整个视图模型绑定到IsEnabled
目标,我们就没有办法触发更新目标(例如在切换复选框时)。以下是应该如何做到的:
您的视图模型:
public class MyFileInfo : INotifyPropertyChanged {
bool _ifPrint;
bool _isValid;
public bool IfPrint {
get { return _ifPrint; }
set {
if(_ifPrint != value) {
_ifPrint = value;
OnPropertyChanged("IfPrint");
}
}
}
public bool IsValid {
get { return _isValid; }
set {
if(_isValid != value) {
_isValid = value;
OnPropertyChanged("IsValid");
}
}
}
//Implement INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string prop){
var handler = PropertyChanged;
if(handler != null) handler(this, new PropertyChangedEventArgs(prop));
}
//.... should do the same for the remaining properties....
//...
}
以下是用于MultiBinding
的转换器,它应该实现IMultiValueConverter
(而不是IValueConverter
):
class IsEnabledConverter : IMultiValueConverter {
public object Convert(object[] values, Type targetType, object parameter,
System.Globalization.CultureInfo culture) {
if(values.Length == 2){
return (bool) values[0] && (bool) values[1];
}
return false;
}
//... omit ConvertBack NotImplementedException stuff
}
以下是修改后的XAML(改为使用MultiBinding):
<Label x:Name="firstLabel" Content="{Binding Path=Filename}">
<Label.IsEnabled>
<MultiBinding Converter="{StaticResource isEnabled}">
<Binding Path="IsValid"/>
<Binding Path="IfPrint"/>
</MultiBinding>
</Label.IsEnabled>
</Label>
现在IsValid
和IfPrint
中的一个更改将触发MultiBinding的转换器。在这里,您也可以直接绑定到CheckBox的IsChecked
,而不是通过IfPrint
间接绑定。
PS:注意XAML(以及codebehind)中使用的Name
不能以数字开头。
由于在选中/取消选中checkbox
时MyFileInfo
的实例不会更改,因此不会调用IsEnabledConverter
。
要根据两个属性启用/禁用1stLabel
,请使用MultiValueConverter
或通过将样式应用于标签来使用MultiDataTrigger
。