Почему конвертер не вызывается при изменении коллекции?

Я сделал CollectionToStringConverter который может конвертировать любой IList в строку через запятую (например, "Item1, Item2, Item3").

Я использую это так:

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

Выше работает, но только один раз, когда я загружаю пользовательский интерфейс. Items является ObservableCollection, Текстовый блок не обновляется, и конвертер не вызывается при добавлении или удалении из Items,

Любая идея, что не хватает, чтобы сделать эту работу?

2 ответа

Решение

Привязка к свойству, дающему коллекцию. Он вступает в силу всякий раз, когда изменяется сам экземпляр коллекции, а не когда изменяются элементы в коллекции.

Есть немало способов достичь желаемого поведения, в том числе:

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.

Конвертер будет вызываться только при изменении свойства. В этом случае значение "Предметы" не меняется. Когда вы добавляете или удаляете новые элементы в коллекции, связывающая часть не знает об этом.

Вы можете расширить 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}" />
Другие вопросы по тегам