在WPF C#中绑定可见性转换器

我有一个类型集合的依赖属性,当它的回调基于我需要设置屏幕上某些控件的可见性的计数触发时。

但控制仍然一直在崩溃。 根据代码,一个控件始终可见。

XAML绑定是

     

我的两个属性是

  public bool CountLabelVisible { get; set; } public bool CountLabelVisibleReverse { get; set; } 

依赖属性回调

  private static void ItemsCollectionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs eventArgs) { var listingUserControl = (obj as ListingUserControl); var itemsResult = (eventArgs.NewValue as List); if (listingUserControl != null && itemsResult != null) { listingUserControl.CountLabelVisible = itemsResult.Count > 0; listingUserControl.CountLabelVisibleReverse =itemsResult.Count <= 0; } } 

转换器代码是

  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (parameter == null) return (bool)value == false ? Visibility.Collapsed : Visibility.Visible; return (bool)value ? Visibility.Collapsed : Visibility.Visible; } 

您已经犯了绑定到对绑定有效的自动属性的经典错误,但在更改时不通知,这意味着绑定子系统无法检测更改并更新绑定目标。

要解决此问题,请在viewmodel上实现INotifyPropertyChanged ,然后确保从属性中通知属性更改。

举个例子,我在viewmodels的基类中有以下内容:

 public abstract class BaseViewModel : INotifyPropertyChanged { ///  /// Helper method to set the value of a property and notify if the value has changed. ///  ///  /// The value to set the property to. /// The current value of the property. /// Flag indicating whether there should be notification if the value has changed. /// The property names to notify that have been changed. protected bool SetProperty(ref T newValue, ref T currentValue, bool notify, params string[] notifications) { if (EqualityComparer.Default.Equals(newValue, currentValue)) return false; currentValue = newValue; if (notify && notifications.Length > 0) foreach (string propertyName in notifications) OnPropertyChanged(propertyName); return true; } ///  /// Raises the  event. ///  /// The name of the property that changed. protected void OnPropertyChanged(string propertyName) { if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } ///  /// Occurs when a property value changes. ///  public event PropertyChangedEventHandler PropertyChanged; } 

然后在你的常规viewmodel中:

 public class MyViewModel : BaseViewModel { private bool _countLabelVisible; public bool CountLabelVisible { get { return _countLabelVisible; } set { SetProperty(ref value, ref _countLabelVisible, true, "CountLabelVisible", "CountLabelVisibleReverse"); } } public bool CountLabelVisibleReverse { get { return !_countLabelVisible; }} } 

这样,当CountLabelVisible被更改时,它也会通知属性CountLabelVisibleReverse ,而属性CountLabelVisibleReverse只包含一个getter – 因为它始终是CountLabelVisible的反转。

因此,您可以按照自己的方式修复代码,但实际情况是您不需要保留CountLabelVisibleReverse属性,而是可以:

  • 创建一个逆可见性转换器作为单独的转换器
  • 通过在绑定上传递可选参数来创建多function可见性转换器
  • 堆叠多个转换器,其中一个转换器的输出通过管道输入到下一个转换器的输入

您绑定的布尔属性是否在更改时通知视图? 是这样的:

 private bool countLabelVisible; public bool CountLabelVisible { get { return countLabelVisible; } set { if (countLabelVisible != value) { countLabelVisible = value; RaisePropertyChanged(() => CountLabelVisible); } } 

对于lambda可用的方法RaisePropertyChanged,您的viewodel应该从NotificationObjectinheritance

您需要通知更改:

 public event PropertyChangedEventHandler PropertyChanged; private bool _countLabelVisible = false; private void RaisePropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } public bool CountLabelVisible { get { return _countLabelVisible; } set { _countLabelVisible = value; RaisePropertyChanged("CountLabelVisible"); } } 

需要告知绑定“框架”绑定需要刷新,这就是Raise …的意思。 这非常快速和肮脏(并且未经测试),但应该certificate您需要做什么。

Bool到能见度转换器类

  public class BoolToVisibilityConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (bool)value ? Visibility.Visible : Visibility.Hidden; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } 

下面提到的Xaml更改显示了可见性转换器类的使用。 此处使用组框来显示可见性。 更改单选按钮选择组框将显示/隐藏。

        

在ViewModel中,使用invokepropertychange只会获得xaml上的可见性更改。

 private Boolean isCustomerDetailChecked = false; public Boolean IsCustomerDetailChecked { get { return isCustomerDetailChecked; } set { isCustomerDetailChecked = value; InvokePropertyChanged("IsCustomerDetailChecked"); } }