WPF选项卡控件和MVVM选择

WPF选项卡控件和MVVM选择,wpf,mvvm,prism,tabcontrol,Wpf,Mvvm,Prism,Tabcontrol,我在应用程序中有一个TabControl。它的定义如下 <TabControl Style="{StaticResource PortfolioSelectionTabControl}" SelectedItem="{Binding SelectedParameterTab}" > <TabItem Header="Trades" Style="{StaticResource PortfolioSelectionTabItem}"> <Con

我在应用程序中有一个TabControl。它的定义如下

<TabControl Style="{StaticResource PortfolioSelectionTabControl}" SelectedItem="{Binding SelectedParameterTab}" >
    <TabItem Header="Trades" Style="{StaticResource PortfolioSelectionTabItem}">
        <ContentControl Margin="0,10,0,5" Name="NSDetailTradeRegion" cal:RegionManager.RegionName="NSDetailTradeRegion" />
    </TabItem>
    <TabItem Header="Ccy Rates" Style="{StaticResource PortfolioSelectionTabItem}">
        <ContentControl Margin="0,10,0,5" Name="NSDetailCcyRegion" cal:RegionManager.RegionName="NSDetailCcyRegion" />
    </TabItem>
    <TabItem Header="Correlations / Shocks" Style="{StaticResource PortfolioSelectionTabItem}">
        <ContentControl Name="NSDetailCorrelationRegion" cal:RegionManager.RegionName="NSDetailCorrelationRegion" />
    </TabItem>
    <TabItem Header="Facility Overrides" Style="{StaticResource PortfolioSelectionTabItem}" IsEnabled="False">
        <ContentControl Name="NSDetailFacilityOverrides" cal:RegionManager.RegionName="NSDetailFacilityOverrides" />
    </TabItem>
</TabControl>
我知道findancestor位不正确;我只是把它放在那里来说明我的意图,但我不确定确切的语法。基本上,每个UserControl都有一个侦听ViewModel上某个属性的触发器(我不确定如何区分每个不同的UserControl,因为显然它们不能都侦听同一个属性,或者当该属性设置为True时,它们都会同时选择,但为每个UserControl设置一个属性似乎很难看)然后查找其父TabItem容器并将IsSelected值设置为true

我的解决方案正确吗?有可能做我正在思考的事情吗?有更整洁的解决方案吗?

如果您查看MSDN上的页面,您会发现一个名为
SelectedIndex
的属性,它是一个
int
。因此,只需将
int
属性添加到视图模型中,并将其绑定到
TabControl中。选择dex
属性,然后您可以随时从视图模型中选择所需的选项卡:

<TabControl SelectedIndex="{Binding SelectedIndex}">
    ...
</TabControl>
仅供参考, 我也遇到过同样的问题,我使用ObservableCollection源动态添加选项卡,但最后添加的选项卡没有被选中。 我做了和Sheridan说的一样的更改,按照SelectedIndex选择Tab。现在,上一个添加的选项卡被选中,但它没有得到关注。 因此,要聚焦选项卡,我们必须添加set Binding IsAsync属性True

<TabControl ItemsSource="{Binding Workspaces}" Margin="5" SelectedIndex="{Binding TabIndex, Mode=OneWay,UpdateSourceTrigger=PropertyChanged, IsAsync=True}">

下面的代码示例将使用MVVM创建一个动态选项卡

虚拟机类 下面的代码将填充并绑定内容。我正在创建两个选项卡,tab1和tab2。两个选项卡都将包含文本框。可以使用任何UIelement而不是文本框

Dim vm As New vmClass

vm.tabCategory = New ObjectModel.ObservableCollection(Of TabCategoryItem)

'VM.tabCategory colection will create all tabs

vm.tabCategory.Add(New TabCategoryItem() With {.TabHeader = "Tab1", .TabContent = new TextBlock().Text = "My first Tab control1"})
vm.tabCategory.Add(New TabCategoryItem() With {.TabHeader = "Tab2", .TabContent = new TextBlock().Text = "My first Tab control2"})

mywindow.DataContent = vm

接受的答案不适用于ViewModel上的DependencyObject

我正在将MVVM与DependencyObject一起使用,只是设置TabControl对我来说不起作用。我遇到的问题是,在设置从ViewModel中选择的tab-selectedIndex时,该属性没有得到视图的更新

我确实将模式设置为双向,但没有任何效果

<TabControl  SelectedIndex="{Binding SelectedTab,Mode=TwoWay}" >
    ...
</TabControl>
基本上我所要做的就是注册依赖属性(DependencyProperty),正如上面所示

让我很难理解的是,我在这个视图上有一堆其他属性,我不需要像那样注册它们来实现两种工作方式。出于某种原因,我不得不像上面那样在TabControl上注册属性

希望这能帮助别人

我的问题是因为我的组件有名称:

x:Name="xxxxxxxx"

在使用DependencyObject对组件进行投标的同时为组件命名似乎是我所有问题的主要原因。

为什么不创建将选择第二个选项卡的事件?我理想的做法是在MVVM中进行命名,因此没有任何代码隐藏。我同意我可以在代码中添加一个事件,但希望MVVM解决方案TabItem在MVVM中没有任何意义。TabItem只是一个UI。SelectedTab行为将在代码隐藏中。@user1122909您可以使用交互库,然后,例如,当您的应用程序获得焦点或其他事件时,根据您的需要,您可以在viewModel中而不是在代码隐藏中编写方法。回答简单,效果良好。我想到的另一个想法是,如果您想通过在XAML中指定来控制哪个选项卡项是启动选项卡,只需在该选项卡项上放置一个绑定,例如IsSelected={binding CcyTabSelected},并在ViewModel上有一个名为CcyTabSelected的bool属性。如果要返回到“启动”选项卡,只需将该属性设置为true。稍有不同的应用程序,此应用程序允许您轻松返回主页选项卡,您的解决方案允许通过索引-1选择列表中的任何选项卡项,因为这是不礼貌的,+1表示回答正确。因此,这是一个为非常具体的问题找到明确答案的好地方。我认为人们可以“总结”MSDN页面上已有的内容。因此,当你知道你的问题是什么时,它往往比MSDN更具可读性,并且是一个更好、更快的资源。我不允许指出,用户可以自己在MSDN上快速、轻松地找到这些答案吗?-1因为他们不礼貌,而且MVVM使用不当。将所选页索引绑定为int不是类型安全的。使用enum s和IValueConverter将更符合良好的MVVMpractice@HelloWorld -
Public Class vmClass

    Public Property tabCategory As ObjectModel.ObservableCollection(Of TabCategoryItem)
    Public Property SelectedCategory As TabCategoryItem
End Class
Dim vm As New vmClass

vm.tabCategory = New ObjectModel.ObservableCollection(Of TabCategoryItem)

'VM.tabCategory colection will create all tabs

vm.tabCategory.Add(New TabCategoryItem() With {.TabHeader = "Tab1", .TabContent = new TextBlock().Text = "My first Tab control1"})
vm.tabCategory.Add(New TabCategoryItem() With {.TabHeader = "Tab2", .TabContent = new TextBlock().Text = "My first Tab control2"})

mywindow.DataContent = vm
<TabControl  SelectedIndex="{Binding SelectedTab,Mode=TwoWay}" >
    ...
</TabControl>
//Not sure below if I need to mention the TwoWay mode
<TabControl  SelectedIndex="{Binding SelectedTab,Mode=TwoWay}" >
        ...
</TabControl>
public class ViewModel : DependencyObject
{
       public static readonly DependencyProperty SelectedTabDP =  DependencyProperty.Register("SelectedTab", typeof(int), typeof(ViewModel));

       public int SelectedTab
       {
          get { return (int)GetValue(SelectedTabDP); }
          set { SetValue(SelectedTabDP, value); }
       }
}
x:Name="xxxxxxxx"