2012-12-05 63 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"); 
     } 
    }