[英]Binding Visibility Converter in 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;
}
您已經犯了綁定到對綁定有效的自動屬性的經典錯誤,但是在更改時不通知,這意味着綁定子系統無法檢測更改並更新綁定目標。
要解決此問題,請在viewmodel上實現INotifyPropertyChanged ,然后確保從屬性中通知屬性更改。
舉個例子,我在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;
}
然后在你的常規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
屬性,而是可以:
您綁定的布爾屬性是否在更改時通知視圖? 是這樣的:
private bool countLabelVisible;
public bool CountLabelVisible
{
get
{
return countLabelVisible;
}
set
{
if (countLabelVisible != value)
{
countLabelVisible = value;
RaisePropertyChanged(() => CountLabelVisible);
}
}
對於具有lambda的RaisePropertyChanged方法,您的viewodel應該從NotificationObject繼承
您需要通知更改:
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 ...的意思。 這非常快速和骯臟(並且未經測試),但應該證明您需要做什么。
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更改顯示了可見性轉換器類的使用。 此處使用組框來顯示可見性。 更改單選按鈕選擇組框將顯示/隱藏。
<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");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.