Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF数据绑定在绑定整个对象时失败_C#_Wpf_Data Binding - Fatal编程技术网

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

C# WPF数据绑定在绑定整个对象时失败,c#,wpf,data-binding,C#,Wpf,Data Binding,在下面的DataTemplate中,第一个绑定不起作用,而第二个绑定起作用,我想知道原因 <local:IsEnabledConverter x:Key="isEnabled"/> <local:Boolean2TextConverter x:Key="txtConverter"/> <DataTemplate x:Key="fileinfoTemplate" DataType="{x:Type local:MyFileInfo}"> <Sta

在下面的
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>
Boolean2TextConverter:

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
}
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;
    }
   ...
}

问题:当切换
复选框时,第二个
标签将变灰并显示“false”,或者变为正常并显示“true”,这是应该的。然而,第一个
标签
根本没有改变;它的
IsEnabled
状态应该是两个布尔值的结合,其中一个由
复选框更改。怎么了?(请注意,
IsEnabledConverter
在GUI初始化时被调用一次,但在其绑定源更改时不会再次调用。)

因为当您选中/取消选中
复选框时,
MyFileInfo
的实例不会更改,因此不会调用
IsEnabledConverter


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

这里有两个问题。首先,必须为ViewModel
MyFileInfo
实现
INotifyPropertyChanged
。其次,您必须在这里使用
多重绑定
。因为如果将整个视图模型绑定到
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....
  //...
}
以下是用于多绑定的转换器,它应该实现
IMultiValueConverter
(而不是
IValueConverter
):

以下是修改后的XAML(改为使用多重绑定):


现在,
IsValid
IfPrint
中的一个更改将触发多重绑定的转换器。在这里,您还可以直接绑定到复选框的
IsChecked
,而不是通过
IfPrint
间接绑定


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

似乎没有源对象本身的更改通知,只有其属性,如
IfPrint
。您也可以使用带有
IMultiValueConverter
MultiBinding
绑定到
IsValid
IfPrint
属性。再次感谢您的耐心和好意:)您能解释一下为什么需要为
多值
转换器实现
INotifyPropertyChanged
,但不是单一的
ValueConverter
?@绿色当使用MVVM模式时,您必须始终实现
INotifyPropertyChanged
。否则,它可能只工作一次(例如加载后立即工作)。但在我的原始代码中,它每次都适用于单值绑定(文本在复选框切换时在“true”和“false”之间变化),而不实现
INotifyPropertyChanged
。只是好奇为什么…@格林:嗯,很有趣。我说的规则事实上是正确的。通常我们必须使用代码更改属性,然后
inotifypropertychanged
将显示这是必要的(如果不实现它,使用代码更改属性将不会触发绑定)。在本例中,您的
IfPrint
通过UI(复选框)更改(绑定到),因此它会自动通知并使后续绑定工作(在本例中,后续绑定位于标签内容和
IfPrint
属性之间).@green这也让我感到惊讶(以前从未经历过,因为我总是实现
INotifyPropertyChanged
),+1出于您有用的好奇心,它教会了我一些新东西:)
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
}
<Label x:Name="firstLabel" Content="{Binding Path=Filename}">
    <Label.IsEnabled>
        <MultiBinding Converter="{StaticResource isEnabled}">
            <Binding Path="IsValid"/>
            <Binding Path="IfPrint"/>
        </MultiBinding>
    </Label.IsEnabled>
</Label>