Единственный способ сделать c = [a stringByAppendingString: b]
немного короче состоит в том, чтобы использовать автоматическое заполнение приблизительно в эти st
точка. +
оператор является частью C, который не знает об объектах Objective C.
Проблема может заключаться в том, что ваш ValueConverter возвращает List
вместо ObservableCollection
. Попробуйте изменить одну строчку и посмотрите, поможет ли это.
Expose
public ObservableCollection<TabItem> Classnames
{
get { return _classnames; }
set { _classnames = value; }
}
Если вы отлаживаете преобразователь значений, вы увидите, что это не так вас вызывают так часто, как вы думаете.
Обновление от 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();
}
}
Я понимаю, что это немного старый вопрос, но я не знаю, что кто-то объяснил, почему вам нужно делать 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: