2012-12-05 32 views
3

我有一个类型集合的依赖属性,当它的回调触发基于计数我需要设置屏幕上的一些控件的可见性。在WPF C中绑定可见性转换器#

但控件始终处于崩溃状态。 按照代码,一个控件始终可见。

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; 
    } 
+0

您的类是否实现INotifyPropertyChanged? – Harry

+0

@Harry这是我的用户控件,我从某处读到INOtifyPropertyChanged实现用户控件不是正确的做法。请建议,如果是。 –

+2

@MSingh这是不正确的 - “INotifyPropertyChanged”是一个简单的接口 - 没有更多 - 应该通过任何想要通知属性已经改变的任何东西来实现 - 这意味着用户控件,数据对象等。实施它,但它肯定有帮助。 – slugster

回答

3

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

要解决此问题,请在您的视图模型上执行INotifyPropertyChanged,然后确保您从属性中通知属性更改。当CountLabelVisible被还通知改变了它

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

这样,:

举个例子,我有基类以下为我的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; 

} 

然后在你的定期视图模型在属性CountLabelVisibleReverse,和属性CountLabelVisibleReverse只包含一个吸气剂 - 因为它将永远是CountLabelVisible的倒数。

这样即修复您的代码有它的方式,但现实是,你不需要保持CountLabelVisibleReverse属性,而不是你可以:

  • 建立逆知名度转换器作为一个独立的转换器
  • 通过使一个可选参数上的结合
  • 堆叠多个转换器,其中来自一个转换器的输出用管道输送到下一个转换器的输入创建一个多功能能见度变换器
低于3210
+0

我喜欢“经典错误”这个词。这将帮助我记住这个错误和解决方案。十分感谢。一个upvote –

0

做你的布尔属性,你绑定通知视图时,他们被改变?某事像这样:

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

对于拉姆达可用RaisePropertyChanged的方法,你viewodel应该继承NotificationObject

0

您需要更改通知:

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 ...所关心的。这是非常快速和肮脏(和未经测试),但应该证明你需要做的。

+0

谢谢一个upvote –

0

布尔能见度转换器类

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中提到的更改显示使用可视性转换器类的。 此处使用组框来显示可见性。 关于更改单选按钮选择组框将会显示/隐藏。

<Page x:Class="WpfApplication.MainWindow" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:vm="clr-namespace:WpfApplication" HorizontalAlignment="Left" VerticalAlignment="Top" 
      Title="Customer" Loaded="Page_Loaded"> 
     <Page.Resources> 
      <vm:BoolToVisibilityConverter x:Key="converter" 
    </Page.Resources> 
<RadioButton Grid.Column="0" x:Name="rdbCustomerDetail" 
    Content="Show Customer" 
    IsChecked="{Binding IsCustomerDetailChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> 
      <GroupBox Header="Customer Details" Visibility="{Binding 

      Path=IsCustomerDetailChecked, 
      UpdateSourceTrigger=PropertyChanged, 
      Converter={StaticResource converter}}"> 
    </GroupBox> 

在ViewModel中使用invokepropertychange比只有你会得到你的xaml的可见性变化。

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