我开始研究这个是因为我在组合框上遇到了一些问题。不幸的是,我还没有解决我的问题,但我可以提供一些额外的见解和解决这个问题的方法。首先,让我们从我对原始 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>
请注意,我们可以在选项卡的 SelectedIndex 和组合控件之间创建一个双向绑定(本例中的默认值),而不是创建从选项卡控件到 ComboBox 的绑定,反之亦然。接下来,让我们向 TabItems 添加一些内容。在这一点上,类似于史蒂夫的建议,我们已经解决了“控制”问题。也就是说,更改选定的 TabItem 会更改选定的 ComboBox 项(您必须相信我,否则请继续阅读!)并且更改 ComboBox 会更改选定的 TabItem。伟大的!
上述 xaml 还将 DiplayMemberPath 属性更改为“名称”。我想你会发现这消除了hughdbrown的“奇怪结果”。回想一下,Header 属性(一个对象)是由 ContentPresenter 包装的。我相信如果没有提供模板,默认行为是将 Header 对象显示为 TextBlock 中的字符串。因此,“奇怪的结果”正确报告 TextBlock 控件不包含 Header 属性。
现在让我们对之前的 ComboBox xaml 进行一些更改。
<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 的内容。此外,该列表现在为每个 TabItem 显示“System.Windows.Controls.TabItem...”。我们可以将 TextBlock 绑定更改为 {Binding Header} 并显示 Header 对象,但 ComboBox 仍然显示所选 TabItem 的内容。由于星期五晚上很晚,世界上没有足够的啤酒,我没有调查可能的原因。但是,我确实有一个解决方法!
首先,让我们创建一个 ValueConverter 来将 TabControl 的 Items 集合转换为我们可以使用的东西。这是代码。
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
}
转换器只是从 TabControl 的 Items 集合中创建一个新集合,该集合包含来自每个 TabItem 的字符串化 Header 对象。这适用于简单的 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>
请记住,在 ItemsSource 绑定中使用的 ValueConverter 返回一个新集合。在本例中,我们将 TabControl 的 Items 集合转换为字符串集合。不要忘记创建转换器 StaticResource!它看起来像这样。
<local:TabItemCollectionConverter x:Key="ItemConverter"/>
现在,使用转换器,整个蜡球按预期工作。
仍然让我感到困惑的是,为什么 ComboBox 会在列表中显示 TabItem 标题,而将 TabItem 内容显示为选择。毫无疑问,有一些明显的解释,但正如我所说,现在是星期五......
希望这可以帮助!