WPF Databinding在绑定整个对象时失败

时间:2014-10-27 07:17:49

标签: c# wpf data-binding

在下面的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会变灰并显示&#34; false&#34;,或者变为正常并显示&#34 ;真实&#34;,应该如此。但是,第一个Label根本没有变化;它的IsEnabled状态应该是两个布尔人的联合,其中一个由CheckBox改变。怎么了? (请注意,IsEnabledConverter在GUI初始化时调用一次,但在其绑定源更改时不再调用。)

2 个答案:

答案 0 :(得分:2)

这里有2个问题。首先,您必须为ViewModel INotifyPropertyChanged实施MyFileInfo。其次,你必须在这里使用MultiBinding。因为如果将整个视图模型绑定到IsEnabled目标,我认为我们没有办法触发更新目标(例如切换CheckBox时)。所以这是应该如何做的:

您的观看模型:

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(以及代码隐藏)中使用的Name不得以数字开头。

答案 1 :(得分:1)

由于MyFileInfo的实例在您选中/取消选中checkbox时未发生更改,因此IsEnabledConverter未被调用。

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