Silverlight TabControl, связанный с ObservableCollection <строка>, не обновляющая, когда измененный набор

Единственный способ сделать c = [a stringByAppendingString: b] немного короче состоит в том, чтобы использовать автоматическое заполнение приблизительно в эти st точка. + оператор является частью C, который не знает об объектах Objective C.

5
задан John Dhom 18 August 2009 в 14:35
поделиться

4 ответа

Проблема может заключаться в том, что ваш ValueConverter возвращает List вместо ObservableCollection . Попробуйте изменить одну строчку и посмотрите, поможет ли это.

0
ответ дан 14 December 2019 в 13:43
поделиться

Expose

public ObservableCollection<TabItem> Classnames
{
    get { return _classnames; }
    set { _classnames = value; }
}

Если вы отлаживаете преобразователь значений, вы увидите, что это не так вас вызывают так часто, как вы думаете.

0
ответ дан 14 December 2019 в 13:43
поделиться

Обновление от 19.08

Краткий ответ заключается в том, что вам необходимо реализовать INotifyPropertyChanged в модели представления и уведомлять слушателей при изменении свойства / коллекции.

Внедрить INotifyPropertyChanged на ViewModel

* implement the interface INotifyPropertyChanged
* define the event (public event PropertyChangedEventHandler PropertyChanged)
* subscribe to the CollectionChanged event (Classnames.CollectionChanged += ...)
* fire the event for listeners

Наилучшее,

/ jhd


Обновление ViewModel, как указано выше ... ValueConverter теперь вызывает все изменения в Property / Collection

public class ViewModel : INotifyPropertyChanged
{
    private readonly ObservableCollection<string> _classnames = new ObservableCollection<string>();

    public ViewModel()
    {
        Classnames.CollectionChanged += Classnames_CollectionChanged;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void Classnames_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        NotifyPropertyChanged("Classnames");
    }

    private void NotifyPropertyChanged(string info)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            foreach (PropertyChangedEventHandler d in handler.GetInvocationList())
            {
                    d(this, new PropertyChangedEventArgs(info));
            }
        }
    }

    public ObservableCollection<string> Classnames
    {
        get { return _classnames; }
    }
}

Привязка XAML ...

<UserControl.Resources>
    <local:ViewModel x:Key="TheViewModel"/>
    <local:TabConverter x:Key="TabConverter" />
</UserControl.Resources>

<StackPanel DataContext="{StaticResource TheViewModel}">
    <ListBox ItemsSource="{Binding Classnames}" />
    <controls:TabControl x:Name="TheTabControl" 
        ItemsSource="{Binding Classnames, Converter={StaticResource TabConverter}, ConverterParameter={StaticResource TheViewModel}}"/>
    <Button Click="Button_Click" Content="Change Classnames" />
</StackPanel>

ValueConverter (в основном без изменений

    public class TabConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var source = value as ObservableCollection<string>;
            if (source == null)
                return null;

            //also sorted out the binding syntax to pass the ViewModel as a parameter
            var viewModel = parameter as ViewModel;
            if (viewModel == null)
                throw new ArgumentException("ConverterParameter must be ViewModel (e.g. ConverterParameter={StaticResource TheViewModel}");

            var tabItems = new List<TabItem>();
            foreach (string classname in source)
            {
                // real code dynamically loads controls by name
                var tabItem = new TabItem
                                  {
                                      Header = "Tab " + classname,
                                      Content = new Button {Content = "Content " + classname}
                                  };
                tabItems.Add(tabItem);
            }

            return tabItems;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
3
ответ дан 14 December 2019 в 13:43
поделиться

Я понимаю, что это немного старый вопрос, но я не знаю, что кто-то объяснил, почему вам нужно делать INotifyPropertyChanged на связанном свойстве на вашей модели представления.

Сам ItemsControl должен быть привязан к ObservableCollection, чтобы события изменения коллекции заставляли ItemsControl переоценивать. Ваш конвертер возвращает отдельную коллекцию List (или Observable) при каждом вызове, вместо того чтобы хранить одну ObservableCollection и добавлять в нее элементы. Поэтому в этих коллекциях никогда не возникает событий изменения коллекции... они всегда новые, каждый раз, когда привязка выполняется заново.

Поднятие PropertyChanged заставляет привязку быть переоцененной и повторно запускает ваш конвертер, возвращая отдельную коллекцию и отражая ваши изменения.

Мне кажется, что лучшим подходом может быть преобразование в вашей ViewModel, а не в конвертере. Предложите ObservableCollection of TabItem, к которой вы привязываетесь напрямую и которую вы изменяете на месте. Тогда TabControl будет видеть изменения, сделанные непосредственно в вашей коллекции, без необходимости поднимать PropertyChanged и заново оценивать всю привязку.

[Редактировать - Добавлен мой подход] ViewModel: public class TabSampleViewModel { private ObservableCollection _tabItems = new ObservableCollection();

    public TabSampleViewModel()
    {
        AddTabItem("Alpba");
        AddTabItem("Beta");
    }

    public ObservableCollection<TabItem> TabItems
    {
        get
        {
            return _tabItems;
        }
    }

    public void AddTabItem( string newTabItemName )
    {
        TabItem newTabItem = new TabItem();

        newTabItem.Header = newTabItemName;
        newTabItem.Content = newTabItemName;

        TabItems.Add( newTabItem );
    }
}

View:

3
ответ дан 14 December 2019 в 13:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: