Как выбрать первый TabItem после обновления TabControl ItemsSource? - PullRequest
0 голосов
/ 10 апреля 2020

Мое приложение использует TabItems для отображения различных пользовательских элементов управления, таких как страница входа в систему / продукты / настройки. При открытии приложения доступна и выбрана только одна вкладка, то есть страница входа, после успешного входа эта страница удаляется, а другие страницы загружаются с выбранной первой. Когда я выхожу из системы, все страницы удаляются и страница входа снова загружается, но не выбирается. Я использую шаблон MVVM, поэтому не хочу писать в ViewModel, что делать в пользовательском интерфейсе.

Можно ли выбрать 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();            
    }   
}

1 Ответ

1 голос
/ 13 апреля 2020

После многих проб и ошибок наконец-то выяснилось, что мое первоначальное представление о Event Handler для 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;
        }
    }
...