Почему конвертер не вызывается при изменении коллекции? - PullRequest
4 голосов
/ 24 апреля 2009

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

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

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

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

Есть идеи, чего не хватает, чтобы заставить эту работу работать?

Ответы [ 2 ]

6 голосов
/ 24 апреля 2009

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

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

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 голос
/ 24 апреля 2009

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

Вы можете расширить 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}" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...