为什么在Collection更改时不调用Converter?

时间:2009-04-24 19:16:12

标签: wpf data-binding

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

我这样用:

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

上述工作,但只有一次我加载UI。 ItemsObservableCollection。文本块不会更新,当我从Items添加或删除时,不会调用转换器。

知道缺少什么使这项工作?

2 个答案:

答案 0 :(得分:6)

绑定是产生集合的属性。它将在集合实例本身发生更改时生效,而不是在集合中的项目发生更改时生效。

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

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<T>子类,它维护一个类似于#2的单独连接字符串。

答案 1 :(得分:1)

仅在属性更改时才会调用Converter。在这种情况下,“项目”值不会更改。当您在集合中添加或删除新项目时,绑定部分不知道这一点。

您可以扩展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}" />