Я начал смотреть на это из-за некоторых проблем со списком. К сожалению, я не решил свою проблему, но я могу дать дополнительное понимание и обойти эту проблему. Прежде всего, давайте начнем с моих изменений в исходном xaml.
<TabControl Height="100" Name="TabControl1" Width="220">
<TabItem Header="TabItem1" x:Name="TabItem1">
<TextBlock Text="TabItem1 Content" />
</TabItem>
<TabItem Header="TabItem2" x:Name="TabItem2">
<TextBlock Text="TabItem2 Content" />
</TabItem>
</TabControl>
<ComboBox Height="23" Name="CmbTabs" Width="120"
ItemsSource="{Binding ElementName=TabControl1, Path=Items}"
SelectedIndex="{Binding ElementName=TabControl1, Path=SelectedIndex}"
DisplayMemberPath="Name"
>
</ComboBox>
Обратите внимание, что вместо создания привязки из элемента управления вкладками к ComboBox и наоборот мы можем создать привязку TwoWay (по умолчанию в данном случае) между SelectedIndex вкладки и элементами управления комбинированным. Далее, давайте добавим некоторый контент в TabItems. На данный момент, подобно предложению Стива, мы исправили «контролирующую» проблему. То есть, изменение выбранного TabItem изменяет выбранный элемент ComboBox (вам придется доверять мне в этом вопросе или продолжайте читать!), А изменение ComboBox изменяет выбранный TabItem. Отлично!
Приведенный выше xaml также изменяет свойство DiplayMemberPath на «Имя». Я думаю, вы обнаружите, что это устраняет «странный результат» Хьюдбрауна. Напомним, что свойство Header (объект) заключено в ContentPresenter. Я полагаю, что, если шаблон не указан, поведение по умолчанию заключается в отображении объекта Header в виде строки в TextBlock. Таким образом, «странный результат» правильно сообщает, что элемент управления TextBlock не содержит свойства Header.
Теперь давайте внесем некоторые изменения в предыдущий xaml ComboBox.
<ComboBox Height="23" Name="CmbTabs" Width="120"
ItemsSource="{Binding ElementName=TabControl1, Path=Items}"
SelectedIndex="{Binding ElementName=TabControl1, Path=SelectedIndex}"
>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Это на самом деле дает интересный результат и использует контент, который мы добавили к каждому TabItem. Когда этот код запустится, вы заметите, что ComboBox теперь отображает содержимое выбранного TabItem. Кроме того, в списке теперь отображается «System.Windows.Controls.TabItem ...» для каждого TabItem. Мы можем изменить привязку TextBlock на {Binding Header} и отобразить объект Header, но ComboBox по-прежнему отображает содержимое выбранного TabItem. Поскольку в пятницу вечером уже поздно и в мире просто не хватает пива, я не стал искать возможные причины для этого. Тем не менее, у меня есть обходной путь!
Во-первых, давайте создадим ValueConverter для преобразования коллекции Items TabControl в то, что мы можем использовать. Вот код.
public class TabItemCollectionConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ItemCollection collection = value as ItemCollection;
IList<string> names = new List<string>();
foreach (TabItem ti in collection.SourceCollection)
{
names.Add(ti.Header.ToString());
}
return names;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
#endregion
}
Преобразователь просто создает новую коллекцию из коллекции Items TabControl, которая содержит строковый объект Header из каждого TabItem. Это прекрасно работает для простых объектов Header, но, очевидно, имеет ограничения. Теперь давайте рассмотрим, как мы используем это в xaml.
<ComboBox Height="23" Name="CmbTabs" Width="120"
ItemsSource="{Binding ElementName=TabControl1, Path=Items, Converter={StaticResource ItemConverter}}"
SelectedIndex="{Binding ElementName=TabControl1, Path=SelectedIndex}"
>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Помните, что ValueConverter, используемый в привязке ItemsSource, возвращает новую коллекцию. В этом случае мы конвертируем коллекцию Items TabControl в коллекцию строк. Не забудьте создать конвертер StaticResource! Это выглядит примерно так.
<local:TabItemCollectionConverter x:Key="ItemConverter"/>
Теперь, используя конвертер, весь шарик воска работает как положено.
Что меня по-прежнему удивляет, так это то, что ComboBox отображает заголовки TabItem в списке и содержимое TabItem в качестве выбора. Без сомнения, есть какое-то очевидное объяснение, но, как я уже сказал, сегодня пятница ...
Надеюсь, это поможет!