首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >wpf如何从嵌套视图切换父选项卡

wpf如何从嵌套视图切换父选项卡
EN

Stack Overflow用户
提问于 2015-08-14 05:53:28
回答 2查看 193关注 0票数 2

我有一个这样的tabcontrol:

代码语言:javascript
复制
<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中访问tab _ in _in_tab?

提前谢谢你!

EN

回答 2

Stack Overflow用户

发布于 2015-08-14 06:28:35

在标签中有一个按钮切换到另一个标签看起来有点奇怪。我认为那应该是一个工具栏按钮或类似的东西。即在翼片的外部。但是如果你坚持:)..。我会使用messenger / event aggregator模式,发布一个事件,并让视图订阅并切换选项卡。我不会让子视图自己去做。

票数 0
EN

Stack Overflow用户

发布于 2015-08-14 09:00:40

您需要将"SelectedIndex“绑定到视图模型中的属性。我个人喜欢保持类型安全并且能够进行单元测试,所以当我需要在代码中操作TabControls时,我通常首先为每个选项卡声明一个枚举:

代码语言:javascript
复制
public enum MyTabs : int
{
    [Description("Tab 1")]
    Tab1,

    [Description("Tab 2")]
    Tab2,

    [Description("Tab 3")]
    Tab3
}

description属性是我希望显示在选项卡头中的文本,稍后将对此进行详细介绍。我的视图模型包含一个MyTabs类型的成员,每当用户单击选项卡时都会更新该成员,我也可以通过代码手动设置它:

代码语言:javascript
复制
public class MyViewModel : ViewModelBase
{
    private MyTabs _CurrentTab;
    public MyTabs CurrentTab
    {
        get { return this._CurrentTab;}
        set { this._CurrentTab = value; RaisePropertyChanged(() => this.CurrentTab); }
    }       
}

现在,您需要将TabControl绑定到此属性:

代码语言:javascript
复制
<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绑定不够智能,无法处理整数枚举,所以我还使用了一个转换器在枚举和整数之间进行转换:

代码语言:javascript
复制
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);
    }
}

在here...first上还有一些其他的事情,你会注意到,我实际上并没有在任何地方声明TabItems。这是因为我是从枚举值本身自动生成它们的;如果我向MyTab枚举添加一个新值,那么它的一个选项卡就会神奇地出现!在本例中,我使用键"MyTabs“绑定到一个静态资源,这是一个枚举枚举中的值的ObjectDataProvider:

代码语言:javascript
复制
    <ObjectDataProvider x:Key="MyTabs" MethodName="GetValues" ObjectType="{x:Type sys:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="local:MyTabs"/>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>

这就提出了一个问题:选项卡如何知道在其标题和tabitem内容区域中显示什么内容。标头使用枚举中声明的“EnumDescriptionConverter”属性,描述的代码在another page on this site上。为了指定每个页面的内容,我为我的每个枚举值创建了一个ControlTemplate,并将其键控到枚举值本身。然后使用数据模板为每个选项卡选择适当的数据模板:

代码语言:javascript
复制
<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:

代码语言:javascript
复制
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();
    }
}

就是这样!每次我想要向枚举添加新页面时,我只需向其相应的枚举添加值,并为该值创建一个ContentControl键。其他一切都是自动发生的,最棒的是它既是类型安全的,又是单元可测试的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31999068

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档