如何在 TabControl ItemsSource 更新后 select 第一个 TabItem?

How to select first TabItem after TabControl ItemsSource update?

我的应用程序使用 TabItems 来显示不同的用户控件,例如 login/products/settings 页面。当您打开应用程序时,只有一个选项卡可用并且 selected,即登录页面,成功登录后,该页面将被删除,其他页面将加载第一个 selected。当我注销时,所有页面都被删除并再次加载登录页面,但没有 selected。我正在使用 MVVM 模式,所以不想在 ViewModel 中写 UI 中的操作。

如果 ItemTab 是列表中的唯一一个,是否可以 select ItemTab?例如,在代码隐藏中编写一个方法并将其连接到 TabControl SelectedIndex?

我尝试在代码隐藏中为 SourceUpdated 和 TargetUpdated 创建事件处理程序,但没有成功。

MainWindow.xaml

<TabControl x:Name="ApplicationTabs"
    ItemsSource="{Binding Tabs}"                   
    SelectedIndex="0">

<TabControl.Resources>
    <Style TargetType="{x:Type TabPanel}">
        <Setter Property="HorizontalAlignment" Value="Center" />
    </Style>

    <DataTemplate DataType="{x:Type VMod:LoginViewModel}">
        <Pages:LoginView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type VMod:AdminViewModel}">
        <Pages:AdminView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type VMod:ProductsViewModel}">
        <Pages:ProductsView />
    </DataTemplate>                    
</TabControl.Resources>

<TabControl.ItemTemplate>
    <DataTemplate DataType="{x:Type inter:ITab}">
        <TextBlock>
            <Run Text="{Binding TabName}" />
        </TextBlock>
    </DataTemplate>
</TabControl.ItemTemplate> </TabControl>

MainWindowViewModel.cs(BaseViewModel 有 INotifyPropertyChanged)

class MainWindowViewModel : BaseViewModel
{
    public static IList<ITab> Tabs { get; set; }        
    public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;

    public MainWindowViewModel()
    {
        Tabs = new ObservableCollection<ITab>();
        LoadLoginPage();
    }

    public static void RaiseStaticPropertyChanged (string PropertyName)
    {StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(PropertyName));}

    public static void LoadLoginPage()
    {
        if (Tabs != null) Tabs.Clear();

        Tabs.Add(new LoginViewModel());     

        RaiseStaticPropertyChanged("Tabs");
    } // LoadTabs() create and load login page to the tab collection

    public static void LoadTabs()
    {
        if (Tabs != null) Tabs.Clear();

        Tabs.Add(new AdminViewModel());
        Tabs.Add(new ProductsViewModel());          

        RaiseStaticPropertyChanged("Tabs");         
    } // LoadTabs() method loads specific tabs to the collection

    public static void LogIn(object x)
    {
        LoggedInUser = (User)x;
        LoadTabs();
    }

    public static void LogOut(object x)
    {
        LoggedInUser = null;
        LoadLoginPage();            
    }   
}

经过多次尝试和错误,我最终发现我最初关于代码隐藏中的 TargetUpdated 事件处理程序的想法是正确的。我只是不知道我的 ItemSource 绑定需要 NotifyOnTargetUpdated。多亏了我没有违反 MVVM 规则。

更正后的绑定:

<TabControl x:Name="ApplicationTabs"
                ItemsSource="{Binding Tabs,                                                                                                        
                              NotifyOnTargetUpdated=True}"
                Grid.Row="1"                   
                TargetUpdated="TabsUpdated"> (...) </TabControl>

后面的代码:

private void TabsUpdated(object sender, DataTransferEventArgs e)
    {
        if(ApplicationTabs.Items.Count == 1)
        {
            ApplicationTabs.SelectedIndex = 0;
        }
    }