【问题标题】:Text string bound to an ObservableCollection through a Converter not updating on collection change通过转换器绑定到 ObservableCollection 的文本字符串不会在集合更改时更新
【发布时间】:2017-12-18 10:23:29
【问题描述】:

我有一个非常简单的 IValueConverter,它将 IList<string> 转换为逗号分隔的字符串。问题是集合(它是一个 ObservableCollection)没有尝试更新文本,我可以判断,因为 IValueConverter 中的调试点显示在加载初始绑定后没有被调用。

转换器(这部分在实际调用时似乎工作正常)

public class CollectionToCommaSeperatedString : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return parameter.ToString();
        if (((IList<string>)value).Count > 0)
            return String.Join(", ", ((IList<string>)value).ToArray()) ?? parameter.ToString();
        else
            return parameter.ToString();
    }

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

绑定元素:

<TextBlock Text="{Binding SelectedChannels, ConverterParameter='(Click to select channels)', Converter={StaticResource CollectionToCommaSeperatedString}, ElementName=userControl, Mode=OneWay}" HorizontalAlignment="Left" VerticalAlignment="Top"/>

属性的 CB:

    public ObservableCollection<string> SelectedChannels
    {
        get { return (ObservableCollection<string>)GetValue(SelectedChannelsProperty); }
        set { SetValue(SelectedChannelsProperty, value); }
    }

    public static readonly DependencyProperty SelectedChannelsProperty =
        DependencyProperty.Register("SelectedChannels", typeof(ObservableCollection<string>), typeof(ChannelSelector), new PropertyMetadata(new ObservableCollection<string>()));

【问题讨论】:

  • 你是如何更新SelectedChannels的?
  • @Sinatr .Add()/.Remove() 哪个“应该”触发更新,对吗?
  • @Sinatr 我知道 CollectionChanged 事件正在触发,因为我钩住了它并添加了控制台转储,看起来不错。
  • CollectionChanged 不会触发该绑定。
  • 我想既然你绑定到Text,那么绑定是忽略INotifyCollectionChanged。您将不得不使用 standard 程序(订阅事件)。

标签: c# wpf binding observablecollection ivalueconverter


【解决方案1】:

实现所需的一种可能性是将转换器逻辑包装成可重用的行为。

这是一个,它将按照您的转换器的预期工作,但仅适用于TextBlock.Text

public static class Behaviors
{
    public static ObservableCollection<string> GetTest(DependencyObject obj) => (ObservableCollection<string>)obj.GetValue(TestProperty);
    public static void SetTest(DependencyObject obj, ObservableCollection<string> value) => obj.SetValue(TestProperty, value);

    public static readonly DependencyProperty TestProperty =
        DependencyProperty.RegisterAttached("Test", typeof(ObservableCollection<string>), typeof(Behaviors), new PropertyMetadata(null, (d, e) =>
        {
            var textBlock = d as TextBlock;
            var collection = e.NewValue as ObservableCollection<string>;
            collection.CollectionChanged += (s, a) => 
            {
                // put logic here
                textBlock.Text = ... ;
            };
        }));
}

像这样使用它:

<TextBlock local:Behaviors.Test="{Binding ...}" />

TODO:添加空检查、取消订阅(如果绑定到持久 ViewModel 属性可能会导致内存泄漏)、正确命名...

【讨论】:

    猜你喜欢
    • 2010-11-20
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    • 2016-04-22
    • 2012-02-29
    • 2011-10-25
    • 1970-01-01
    • 2019-11-10
    相关资源
    最近更新 更多