【问题标题】:Data Binding + Converter doesn't update bound property - XAML - WPF数据绑定 + 转换器不更新绑定属性 - XAML - WPF
【发布时间】:2015-10-28 14:11:01
【问题描述】:

我想要什么:

将一个可观察的集合绑定到一个属性(例如Opacity),该属性应该采用转换器类的返回值。


XAML 代码:

    <ListBox x:Name="HostDeviceList" 
            ItemsSource="{Binding ObservableCollection}" 
            SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
            ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <ListBox.Background>
        <ImageBrush ImageSource="assets/Tapako.ico" 
                    Opacity="{Binding ObservableCollection, Converter={StaticResource IsNullToFloatConverter}}" Stretch="None">
        </ImageBrush>
    </ListBox.Background>

我的转换器类:

public class IsNullToFloatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    float lowValue = 0.1f;
    float highValue = 0.5f;

    if (parameter is float && value != null)
    {
        return parameter;
    }
    else
    {
        if (value is IEnumerable)
        {
            if (((IEnumerable)value).Any())
            {
                return lowValue;
            }
            else
            {
                return highValue;
            }
        }
        if (value != null)
        {
            return lowValue;
        }
        else
        {
            return highValue;
        }
    }
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    throw new NotImplementedException();
}
}

什么有效:

  1. ListView 已正确更新
  2. 如果我不使用转换器类而是使用Opacity="{Binding ObservableCollection.Count}",那么一旦第一个元素出现,不透明度就会从 0 变为 1

什么不起作用: 如果我使用转换器,Convert 只会在启动时调用一次,但不会在ListView 中出现新元素时调用

【问题讨论】:

  • Convert 方法仅在引发属性更改事件时运行。您的 ObservableCollection 属性是否实现了 INotifyPropertyChanged 或者它是否得到了更新?请记住,添加/删除项目不会触发此事件。

标签: c# xaml data-binding


【解决方案1】:

很可能您的集合没有改变(我的意思是对您的集合的引用),因此您必须实现机制来处理集合更改事件(当添加或删除值时触发)

注意:在这两种情况下,您都需要更改转换器以直接使用计数

所以你应该可以这样做,如果它不起作用 -> 这意味着集合在计数更改时不会通知你走下面描述的更长的路:

<ImageBrush ImageSource="assets/Tapako.ico" 
            Opacity="{Binding ObservableCollection.Count, Converter={StaticResource IsNullToFloatConverter}}" Stretch="None">
</ImageBrush>

如果上述方法不起作用,我会这样做:

创建一个新属性 -> 我将在 VM 中将 CollectionCount 绑定到该属性

public int collectionCount;

public int CollectionCount
{
    get
    {
        return collectionCount;
    }
    set
    {
        collectionCount = value;
        RaisePropertyChanged("CollectionCount");
    }
} 

更改您的绑定以使用它而不是整个集合

<ImageBrush ImageSource="assets/Tapako.ico" 
            Opacity="{Binding CollectionCount, Converter={StaticResource IsNullToFloatConverter}}" Stretch="None">
</ImageBrush>

注册集合更改并创建一个处理程序,该处理程序将为您的属性提供计数,然后在更改时触发并调用转换器

ObservableCollectionProp.CollectionChanged += CollectionChangedHandler;

private void CollectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
{
    CollectionCount = ObservableCollectionProp.Count;
}

【讨论】:

  • 您的第一个建议奏效了。 &lt;ImageBrush ImageSource="assets/Tapako.ico" Opacity="{Binding ObservableCollection.Count, Converter={StaticResource IsNullToFloatConverter}}" Stretch="None"&gt; &lt;/ImageBrush&gt; 完成了这项工作。谢谢! --> 所以总的来说,问题是ObservableCollection 不会触发事件,但ObservableCollection.Count 会触发?那为什么绑定ListBoxworks?
  • ObservableCollection 没有改变,因为当你绑定集合本身时,你绑定到它的引用,而不是用新的引用来改变它(例如 ObsColProp = new ObservableCollection ....)。 ListBox 中的绑定有效,因为您的 ObservableCollection 正在通知 ListBox 其元素的更改,但它仍然不是包含它们的引用的更改。例如,如果您将 ItemsSource 绑定到 ObsColProp,然后使用新的 ObservableCollection 更改引用 -> 新的更改不会发送到 ListBox(因为它绑定到旧的)
猜你喜欢
  • 2013-08-06
  • 2016-08-07
  • 1970-01-01
  • 1970-01-01
  • 2015-11-23
  • 1970-01-01
  • 2013-06-17
  • 2023-01-16
  • 2023-03-23
相关资源
最近更新 更多