WPF选项卡控件和MVVM选择
I have a TabControl in an MVVM WPF application. It is defined as follows.
<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>
因此,每个选项卡项目的内容都有与其相关联的自己的视图.这些视图均具有 MEF [Export]
属性,并通过视图发现与相关区域相关联,因此上面的代码就是我需要加载选项卡控件并在它们之间进行切换的全部操作.它们都引用了它们后面的同一个共享ViewModel对象,因此都可以无缝交互.
So each tab item content has its own view associated with it. Each of those views has the MEF [Export]
attribute and is associated with the relevant region through view discovery, so the above code is all I need to have the tab control load and switch between them. They all reference the same shared ViewModel object behind them and so all interact seamlessly.
我的问题是,当用户导航到父窗口时,我希望选项卡控件默认为第二个选项卡项.通过在XAML IsSelected="True"
中在TabItem 2号中指定,在第一次加载窗口时,这样做很容易.当用户离开屏幕然后返回到屏幕时,这样做不那么容易.
My problem is that when the user navigates to the parent window, I want the tab control to default to the second tab item. That is easy enough to do when the window is first loaded, by specifying in XAML IsSelected="True"
in TabItem number 2. It is less easy to do when the user navigates away from the screen and then comes back to it.
我考虑过在选项卡控件上具有SelectedItem={Binding SelectedTabItem}
属性,因此我可以通过编程方式在ViewModel中设置选定的选项卡,但是问题是我不知道ViewModel中的TabItem对象,因为它们在上文中已声明.仅XAML,因此我没有TabItem对象可传递给setter属性.
I thought about having a SelectedItem={Binding SelectedTabItem}
property on the tab control, so I could programmatically set the selected tab in the ViewModel, but the problem is I have no knowledge of the TabItem objects in the ViewModel as they are declared above in the XAML only, so I have no TabItem object to pass to the setter property.
我的一个想法是使子视图(构成上面每个选项卡项目的内容)在XAML的UserControl级别上具有一种样式,如下所示.
One idea I had was to make the child Views (that form the content of each of the tab items above) have a style on the UserControl level of their XAML, something along the following.
<Style TargetType={x:Type UserControl}>
<Style.Triggers>
<DataTrigger Property="IsSelected" Value="True">
<Setter Property="{ElementName={FindAncestor, Parent, typeof(TabItem)}, Path=IsSelected", Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
我知道findancestor位不正确;我只是将其放在此处以指定我的意图,但是我不确定确切的语法.基本上每个UserControl都有一个触发器来监听ViewModel上的一个属性(不确定我如何区分每个不同的UserControl,因为显然他们不能全部监听相同的属性,或者当该属性设置为时它们会同时选择)是的,但是为每个用户控件都有一个属性似乎很难看),然后找到其父TabItem容器并将IsSelected值设置为true.
I know the findancestor bit isn't correct; I've just put it there to specify my intent, but I am not sure of the exact syntax. Basically for each UserControl to have a trigger that listens to a property on the ViewModel (not sure how I would distinguish each different UserControl as obviously they can't all listen to the same property or they would all select simultaneously when the property is set to True, but having a property for each usercontrol seems ugly) and then finds its parent TabItem container and sets the IsSelected value to true.
我在正确的位置上有解决方案吗?是否可以做我正在考虑的事情?有更整洁的解决方案吗?
Am I on the right track with a solution here? Is it possible to do what I am pondering? Is there a tidier solution?
If you look at the TabControl
Class page on MSDN, you'll find a property called SelectedIndex
which is an int
. Therefore, simply add an int
property into your view model and Bind
it to the TabControl.SelectedIndex
property and then you can select whichever tab you like at any time from the view model:
<TabControl SelectedIndex="{Binding SelectedIndex}">
...
</TabControl>
更新>>>
UPDATE >>>
使用此方法设置启动"标签更为简单:
Setting a 'startup' tab is even easier using this method:
在视图模型中:
private int selectedIndex = 2; // Set the field to whichever tab you want to start on
public int SelectedIndex { get; set; } // Implement INotifyPropertyChanged here