【问题标题】:Why is Converter not called when Collection changes?为什么在 Collection 更改时不调用 Converter?
【发布时间】:2009-04-24 19:16:11
【问题描述】:

我创建了一个CollectionToStringConverter,它可以将任何IList 转换为逗号分隔的字符串(例如“Item1, Item2, Item3”)。

我是这样使用的:

<TextBlock Text="{Binding Items, 
                  Converter={StaticResource CollectionToStringConverter}}" />

上述方法有效,但仅在我加载 UI 时有效。 ItemsObservableCollection。文本块不会更新,当我从Items 添加或删除时,转换器不会被调用。

知道要完成这项工作还缺少什么吗?

【问题讨论】:

    标签: wpf data-binding


    【解决方案1】:

    绑定到产生集合的属性。它会在集合实例本身发生变化时生效,而不是在集合中的项目发生变化时生效。

    有很多方法可以实现您想要的行为,包括:

    1) 将ItemsControl 绑定到集合并配置ItemTemplate 以输出以逗号开头的文本,如果它不是集合中的最后一项。比如:

    <ItemsControl ItemsSource="{Binding Items}">
        <ItemsControl.ItemTemplate>
            <TextBlock>
                <TextBlock Visibility="{Binding RelativeSource={RelativeSource PreviousData}, Converter={StaticResource PreviousDataConverter}}" Text=", "/>
                <TextBlock Text="{Binding .}"/>
            </TextBlock>
        </ItemsControl.ItemTemplate>    
    </ItemsControl>
    

    2) 在您的代码隐藏中编写代码以观察集合的变化并更新将项目连接成单个string 的单独属性。比如:

    public ctor()
    {
        _items = new ObservableCollection<string>();
    
        _items.CollectionChanged += delegate
        {
            UpdateDisplayString();
        };
    }
    
    private void UpdateDisplayString()
    {
        var sb = new StringBuilder();
    
        //do concatentation
    
        DisplayString = sb.ToString();
    }
    

    3) 编写您自己的ObservableCollection&lt;T&gt; 子类,该子类维护一个类似于#2 的单独连接字符串。

    【讨论】:

    • 我实际上已经开始使用 ItemsTemplate 方法,但是在代码审查期间,我们认为通过多绑定转换器来完成它会更简单,认为当观察到的集合发生变化时绑定会更新.我会恢复到那个方法 :) 谢谢!
    • 您在示例中的 ItemsControl.ItemTemplate 和第一个 TextBlock 元素之间缺少 DataTemplate。
    【解决方案2】:

    只有在属性改变时才会调用转换器。在这种情况下,“Items”值不会改变。当您在集合中添加或删除新项目时,绑定部分不会意识到这一点。

    您可以扩展 ObservableCollection 并在其中添加一个新的 String 属性。请记住在您的 CollectionChanged 事件处理程序中更新该属性。

    这里是实现

    public class SpecialCollection : ObservableCollection<string>, INotifyPropertyChanged
    {
    
        public string CollectionString
        {
            get { return _CollectionString; }
            set { 
                _CollectionString = value;
                FirePropertyChangedNotification("CollectionString");
            }
        }
    
    
        protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            string str = "";
    
            foreach (string s in this)
            {
                str += s+",";
            }
    
            CollectionString = str;
    
            base.OnCollectionChanged(e);
        }
    
        private void FirePropertyChangedNotification(string propName)
        {
            if (PropertyChangedEvent != null)
                PropertyChangedEvent(this,
                   new PropertyChangedEventArgs(propName));
        }   
    
        private string _CollectionString;
        public event PropertyChangedEventHandler PropertyChangedEvent;   
    
    }
    

    你的 XAML 会是这样的

    <TextBlock DataContext={Binding specialItems} Text="{Binding CollectionString}" />
    

    【讨论】:

      猜你喜欢
      • 2011-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-04
      • 1970-01-01
      • 1970-01-01
      • 2021-11-27
      • 1970-01-01
      相关资源
      最近更新 更多