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初始化时被调用一次,但在其绑定源更改时不会再次调用。)

WPF数据绑定在绑定整个对象时失败

这里有两个问题。首先,您必须为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>

现在IsValidIfPrint中的一个更改将触发MultiBinding的转换器。在这里,您也可以直接绑定到CheckBox的IsChecked,而不是通过IfPrint间接绑定。

PS:注意XAML(以及codebehind)中使用的Name不能以数字开头。

由于在选中/取消选中checkboxMyFileInfo的实例不会更改,因此不会调用IsEnabledConverter

要根据两个属性启用/禁用1stLabel,请使用MultiValueConverter或通过将样式应用于标签来使用MultiDataTrigger

相关文章: