我有一个像这样的tabcontrol:
<TabControl>
<local:TabItem x:Name="son" Header="son">
<local_son:SonView />
</local:TabItem>
<local:TabItem x:Name="daughter" Header="daughter">
<local_daughter:DaughterView />
</local:TabItem>
</TabControl>
在DaughterView中有一个按钮,我想点击此按钮切换到 儿子选项卡。我的问题是如何在DaughterView中找到儿子选项卡的tabindex?
提前谢谢!
答案 0 :(得分:0)
在选项卡内部有一个按钮切换到另一个选项卡似乎有点奇怪。我认为这将是一个工具栏按钮或类似的东西。即选项卡外面。但是如果你坚持:))我会使用信使/事件聚合器模式并发布一个事件并让视图订阅并切换选项卡。我不会让孩子看到自己这样做。
答案 1 :(得分:0)
您需要将“SelectedIndex”绑定到视图模型中的属性。我个人喜欢保持类型安全且能够进行单元测试,因此当我需要在代码中操作TabControl时,我通常首先为每个选项卡声明一个带有一个值的枚举:
public enum MyTabs : int
{
[Description("Tab 1")]
Tab1,
[Description("Tab 2")]
Tab2,
[Description("Tab 3")]
Tab3
}
description属性是我希望在标题页中显示的文本,稍后会详细介绍。我的视图模型包含MyTabs类型的成员,只要用户单击选项卡就会更新,我也可以通过代码手动设置:
public class MyViewModel : ViewModelBase
{
private MyTabs _CurrentTab;
public MyTabs CurrentTab
{
get { return this._CurrentTab;}
set { this._CurrentTab = value; RaisePropertyChanged(() => this.CurrentTab); }
}
}
现在您需要将TabControl绑定到此属性:
<TabControl
ItemsSource="{Binding Source={StaticResource MyTabs}}"
SelectedIndex="{Binding CurrentTab, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
<TabControl.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Header" Value="{Binding Path=., Converter={StaticResource EnumDescriptionConverter}}" />
</Style>
</TabControl.Resources>
</TabControl>
不幸的是,WPF绑定不够智能,不能使用整数枚举,所以我也使用转换器在枚举和整数之间进行转换:
public class EnumToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (int)value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Enum.ToObject(targetType, value);
}
}
这里还有其他一些事情......首先你会注意到我实际上并没有在任何地方声明TabItems。那是因为我从Enum值本身自动生成它们;如果我在MyTab枚举中添加一个新值,那么它会出现一个神奇的标签!在这种情况下,我使用键“MyTabs”绑定到静态资源,这是一个ObjectDataProvider,它枚举了我的枚举中的值:
<ObjectDataProvider x:Key="MyTabs" MethodName="GetValues" ObjectType="{x:Type sys:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:MyTabs"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
这引发了一个问题,即标签如何知道在标题和tabitem内容区域中显示的内容。标头使用枚举中声明的“Description”属性,EnumDescriptionConverter的代码位于another page on this site。要为每个页面指定内容,我为每个枚举值创建一个ControlTemplate,并将其键入枚举值本身。然后使用数据模板选择适用于每个选项卡的数据模板:
<Window.Resources>
<ControlTemplate x:Key="{x:Static local:MyTabs.Tab1}">
<TextBlock Text="This is the first tab" />
</ControlTemplate>
<ControlTemplate x:Key="{x:Static local:MyTabs.Tab2}">
<TextBlock Text="This is the second tab" />
</ControlTemplate>
<ControlTemplate x:Key="{x:Static local:MyTabs.Tab3}">
<TextBlock Text="This is the third tab" />
</ControlTemplate>
<DataTemplate DataType="{x:Type local:MyTabs}">
<ContentControl>
<ContentControl.Template>
<MultiBinding Converter="{StaticResource ResourceKey=BindingToResourceConverter}">
<Binding RelativeSource="{RelativeSource AncestorType={x:Type Window}}" Path="Resources" />
<Binding />
</MultiBinding>
</ContentControl.Template>
</ContentControl>
</DataTemplate>
</Window.Resources>
最后一个难题是BindingToResourceConverter,它只需要一个绑定(即其中一个枚举值)并使用它来查找相应的ControlTemplate:
public class BindingToResourceConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (values[0] as ResourceDictionary)[values[1]];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
就是这样!每次我想向TabControl添加一个新页面时,我只需在其相应的枚举中添加一个值,并为该值创建一个ContentControl键。其他一切都是自动发生的,最重要的是它既是类型安全的又是可单元测试的。