在 WPF C# 中绑定可见性转换器 [英] Binding Visibility Converter in WPF C#

查看:26
本文介绍了在 WPF C# 中绑定可见性转换器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a dependency property of type collection, when its callback fires based on the count I need to set the visibility of some of the controls on the screen.

但控件始终处于折叠状态.根据代码,一个控件始终可见.

But the controls remains Collapsed all the time. As per the code, one control remains visible all the time.

XAML 绑定是

   <TextBlock Text="106 search results for 'a'" Margin="5,0,100,0" Visibility="{Binding CountLabelVisibleReverse, Converter={StaticResource VisibilityConverter}}"/>
 <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,0,90,0"  
                            Visibility="{Binding CountLabelVisible, Converter={StaticResource VisibilityConverter}}">
 <TextBlock Text="Sort By"  />
 <ComboBox Style="{StaticResource ComboBoxStyle1}" Width="100" x:Name="ComboBoxSorting" ItemsSource="{Binding SortBy}" />
   </StackPanel>

我的两个属性是

    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<ItemsResult>);
        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;
    }

推荐答案

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

You have made the classic mistake of binding to auto properties that are valid for binding, but don't notify upon change, which means the binding subsystem cannot detect changes and update the binding targets.

要解决此问题,请在您的设备上实施 INotifyPropertyChangedviewmodel,然后确保你从properties中通知property的变化.

To fix this, implement INotifyPropertyChanged on your viewmodel, and then ensure that you notify the property change from the properties.

例如,我的视图模型的基类中有以下内容:

As an example, I have the following in the base class for my viewmodels:

public abstract class BaseViewModel : INotifyPropertyChanged
{

    /// <summary>
    /// Helper method to set the value of a property and notify if the value has changed.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="newValue">The value to set the property to.</param>
    /// <param name="currentValue">The current value of the property.</param>
    /// <param name="notify">Flag indicating whether there should be notification if the value has changed.</param>
    /// <param name="notifications">The property names to notify that have been changed.</param>
    protected bool SetProperty<T>(ref T newValue, ref T currentValue, bool notify, params string[] notifications)
    {
        if (EqualityComparer<T>.Default.Equals(newValue, currentValue))
            return false;

        currentValue = newValue;
        if (notify && notifications.Length > 0)
            foreach (string propertyName in notifications)
                OnPropertyChanged(propertyName);

        return true;
    }

    /// <summary>
    /// Raises the <see cref="E:PropertyChanged"/> event.
    /// </summary>
    /// <param name="propertyName">The name of the property that changed.</param>
    protected void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    /// <summary>
    /// Occurs when a property value changes.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

}

然后在您的常规视图模型中:

then in your regular 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 的倒数.

This way, when CountLabelVisible gets changed it also notifies on the property CountLabelVisibleReverse, and the property CountLabelVisibleReverse consists of only a getter - because it will always be the inverse of CountLabelVisible.

这样就可以按照您拥有的方式修复您的代码,但实际情况是您不需要保留 CountLabelVisibleReverse 属性,而是可以:

So that fixes your code the way you have it, but the reality is you don't need to keep the CountLabelVisibleReverse property, instead you could:

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

这篇关于在 WPF C# 中绑定可见性转换器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆