提供TabControl3 个标签TabItem。每个选项卡都有自己的VM. 整个东西都保存在收藏中ObservableCollection<AbstractVM> TabItemsVM。
<TabControl ItemsSource="{Binding TabItemsVM}"
SelectedItem="{Binding SelectedTabVM}"
TabStripPlacement="Top">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding Header}"/>
<Setter Property="Width" Value="100"/>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>

通过分配从代码中选择另一个选项卡时SelectedTabVM TabItemsVM[0]。代码如下:
_selectedTabVM = TabItemsVM[0]; //присваиваю именно приватному полю,
//т.к. в публичном, в сеттере хранится некая логика проверки.
//в то время как я хочу изменить вкладку без проверки
//Вызываю PropertyChanged("SelectedTabVM");
一切正常时选项卡会更改:
实施SelectedTabVM:
private Abstract VM _selectedTabVM;
public AbstractVM SelectedTabVM
{
get { return _selectedTabVM; }
set
{
if (modeChangeExecute())
{
_selectedTabVM = value;
NotifyPropertyChanged("SelectedTabVM");
}
}
}

但是当你通过界面切换标签时,你会得到这样的画面:

那些。两个选项卡的属性IsSelected设置为True。有什么问题?IsSelected为什么属性没有从我从代码切换到的选项卡中删除
UPD 在英语 stackoverflow 上发现了一个不太相似的问题: https ://stackoverflow.com/questions/7929646/how-to-programmaticaly-select-a-tabitem-in-wpf-tabcontrol
这里看起来像是控制错误TabControl本身WPF
问题是您正在使用对话框阻止设置器。在对话期间,x 属性必须有一些值,因此 system
Binding的被关闭并且无法按预期工作。解决方案是从设置器中删除允许选项卡更改的逻辑。同时,二传手也将变得普遍适用。那么,UI 逻辑(消息框)可以从 VM 中卸载,这也不错。所以看看你需要什么。
首先,我们从 setter 中删除长操作。二传手必须快。
现在,我们需要禁用
TabItem'a 的正常点击,并将其重定向到我们的代码。为此,您需要某种可以取消事件的 EventTrigger。(例如,像这里一样。)但是这种技术将传送EventArgs到它们不属于的 VM,所以让我们来看看附加的行为。(是的,这是一个严肃的武器,我没有找到另一个。)首先,通过 nuget 连接
System.Windows.Interactivity.WPF(参考 → 鼠标右键 → Manage NuGet Packages... → Search =System.Windows.Interactivity.WPF)。让我们写Behavior:这里一切都很简单:连接时,我们订阅
PreviewMouseDowny'aTabItem,断开连接时,我们取消订阅,当点击到达时,我们通过取消标准处理e.Handled。到底为什么PreviewMouseDown?因为这个事件在内部处理程序之前到达我们这里,我们可以在不让它进入内部的情况下取消它。现在问题来了,当检测到点击时怎么办?好的,您需要从 VM 调用命令,让 VM 决定下一步要做什么。从哪里获得命令和参数?答案很明显——通过附加属性附加。这些附加属性可以放在一个单独的类中,但您可以将它们放在
RouteClickBehaviour.我们得到一个改进的版本:
唯一的微妙之处在于我们异步发送命令。
下一个问题是如何通过样式将附加行为添加到
TabItem?如果我们TabItem手动创建它,就不会有问题:(并且命令可以通过参数传递)。但是我们有一种风格,通过一种风格传递行为,一切都变得复杂了。
让我们使用标准解决方法:通过另一个附加属性。让我们添加
RouteClickBehaviour这个:现在,如果您设置
Inject = true,所需的行为将自动挂起。好的,接下来 - 我们需要在 VM 中使用一个命令来决定是否更改 Tab。对于命令,您可以使用普通的
RelayCommand. 当然,我们将把命令放在它所在的同一个地方modeChangeExecute:好的,VM 部分已准备就绪。现在让我们通过 XAML 将它们联系在一起。
设置
local:RouteClickBehaviour.Inject = True为启用行为。该命令必须从TabControl'a 的 VM 获取,因为它是决定切换问题的外部 VM。作为参数,我们传递要激活的本地 VM。我们检查。应该管用。
为什么选项卡需要绑定属性
IsSelected?限制自己SelectedItem,这就足够了。使用 IsSelected 属性,控件将在没有您的情况下解决。如果您需要知道 VM 中此属性的值,则通过以下方式绑定它Mode=OneWay更新:
我就是这么做的。我必须马上说我并没有真正在意架构,我只是把它放进去这样它会更快:)
这是背景
一切对我来说都很好,选项卡一一突出显示。你的问题很可能是在别处,你没有表现出来,以为与问题无关。查找分配给您的选项卡的位置
IsSelected = true。或者完全从逻辑上抽象出来,只留下这个基础,其余的都装上stub,慢慢连接逻辑。