DependencyProperty типа IList - изменение коллекции

243
07 марта 2017, 13:12

Есть некий UserControl. У него есть свойство зависимостей ItemsProperty типа IList<string> (да да, именно строго типизированный лист). К этому свойству можно биндиться извне и, к тому же, сам контрол использует это свойство для отображения. Но при изменении коллекции как то так Items.Add("asd") в отображении ничего не меняется. Это логично, но как сказать отображению, что коллекция изменилась?

Теперь что я пытался с этим поделать.

  1. Я пытался сделать ItemsProperty типа ObservableCollection<string>. Но при использовании контрола я не могу прибиндить ему свойство типа List<string> по понятным причинам.

  2. Я пытался вызывать DependencyObject.OnPropertyChanged, но ничего не получилось.

  3. Я пытался в xaml.cs контрола реализовать INotifyPropertyChanged и породить событие PropertyChanged для свойства Items

Так как же поступить?

Answer 1

Не знаю насколько сильно это вам поможет, но т.к. в большинстве случаев в качестве источника данных выступает ObservableCollection<T>, можем этим воспользоваться, поэтому делаем следующее:

1) В пользовательском контроле создаем DP.

public static readonly DependencyProperty ItemsSourceProperty =    
DependencyProperty.Register("ItemsSource", 
             typeof(IEnumerable<object>),           
             typeof(MyUserControl), 
             new PropertyMetadatadefault(IEnumerable<object>)));

public IEnumerable<object> ItemsSource
{
     get
     {
          return (IEnumerable<object>)GetValue(ItemsSourceProperty);
     }
     set
     {
         SetValue(ItemsSourceProperty, value);
     }
}

2) В конструкторе контролла подписываемся на изменение значения вашего DP.

public MyUserControl()
{
    InitializeComponent();
    var dp = DependencyPropertyDescriptor.FromProperty(ItemsSourceProperty, typeof(MyUserControl));     
    dp?.AddValueChanged(this, Handler);
}

3) В обработчике на изменение DP приводим ваше свойство к INotifyCollectionChangedи подписываемся на уведомления об изменении коллекции.

private void Handler(object sender, EventArgs eventArgs)
{
     var nc = ItemsSource as INotifyCollectionChanged;
     if (nc != null)
         nc.CollectionChanged += OnCollectionChanged;
}

4) Далее реализуем вашу логику, реагирующую на изменения коллекции:

private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
        // Ваша логика на реакцию об изменении свойства
}

Все целиком:

public partial class MyUserControl : UserControl
{
    public MyUserControl()
    {
        InitializeComponent();
        var dp = DependencyPropertyDescriptor.FromProperty(ItemsSourceProperty, typeof(MyUserControl));     
        dp?.AddValueChanged(this, Handler);
    }
    private void Handler(object sender, EventArgs eventArgs)
    {
        var nc = ItemsSource as INotifyCollectionChanged;
        if (nc != null)
            nc.CollectionChanged += OnCollectionChanged;
    }
    private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // Ваш код
    }
    public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
                                                    "ItemsSource", 
                                                    typeof(IEnumerable<object>), 
                                                    typeof(MyUserControl), 
                                                    new PropertyMetadata(default(IEnumerable<object>)));
    public IEnumerable<object> ItemsSource
    {
        get
        {
            return (IEnumerable<object>)GetValue(ItemsSourceProperty);
        }
        set
        {
            SetValue(ItemsSourceProperty, value);
        }
    }
}
READ ALSO
Запуск программ по расписанию через waitable timer C#

Запуск программ по расписанию через waitable timer C#

Я пишу курсовую запуск программ по расписанию на C#, тип проекта Windows FormsПреподаватель сказал реализовать через waitable timer

365
Какие ошибки не видит компилятор, но видит run-time?

Какие ошибки не видит компилятор, но видит run-time?

Проходил онлайн-собеседование и был предложен тест:

287
Как избежать ошибки PathTooLongException?

Как избежать ошибки PathTooLongException?

Имеется программа обрабатывающая различные файловые пути (напр: C:\Users\J

298
Определить язык произвольной строки

Определить язык произвольной строки

Из вне приходит произвольная строка и нужно определить ее язык

355