C# WPF DataTemplate wewnątrz TabControl.ContentTemplate

0

Mam klasę ViewModel1 wraz z dwoma listami (Items, Movies), pierwsza jest binding do TabControl przez co tworzy zakładki mojego TabControl a druga ma binding do ItemsControl, problem polega na tym że kontrolki wewnątrz ItemsControl są niewyświetlane ale gdy dla sprawdzenia dałem w TabControl.ContentTemplate to wyświetlała się tylko że wtedy nie mogę ich binding z właściwościami klasy której obiekty zawiera druga lista.

XAML:

        <TabControl ItemsSource="{Binding Path=Items}">
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock
                    Text="{Binding Path=Name}" />
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <ItemsControl ItemsSource="{Binding Path=DataContext.movies, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Path=Name}" />
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>

C# TabControlViewModel

    public class TabControlViewModel
    {
        public ObservableCollection<TabItemViewModel> Items { get; set; } = new ObservableCollection<TabItemViewModel>
         {
                    new TabItemViewModel {Name="Tab 1", IsSelected = true },
                    new TabItemViewModel {Name="Tab 2" },
                    new TabItemViewModel {Name="Tab 3" },
                    new TabItemViewModel {Name="Tab 4" },
         };

        public ObservableCollection<Movie> movies{ get; private set; } = new ObservableCollection<Movie>();

    }
1

Na start przeczytaj różnice pomiędzy ItemTemplate a ContentTemplate https://stackoverflow.com/questions/25265266/wpfdifference-between-tabcontrol-itemtemplate-and-tabitem-contenttemplate
jak to zrobisz to szybko ogarniesz, na start pokażę wynik:
screenshot-20210323093640.png

pamiętaj, że TabControl przyjmuje listę, tak więc do DataContext przy ItemTemplate oraz ContentTemplate otrzymasz element z listy (tracisz więc dostęp do ViewModelu głównego):
TabControl.ItemTemplate edytujesz tzw. Header. Natomiast TabControl.ContentTemplate edytujesz to, co ma się pokazać po kliknięciu w header. Tak więc w Twoim przypadku filmy powinny być wewnątrz klasy TabItemViewModel. Zobacz przykład:

    public class MainWindowViewModel
    {
        public MainWindowViewModel()
        {
            Random r = new Random();
            Elements1.Add(new Element1(r.Next(1000)));
            Elements1.Add(new Element1(r.Next(1000)));
            Elements1.Add(new Element1(r.Next(1000)));
            Elements1.Add(new Element1(r.Next(1000)));
            Elements1.Add(new Element1(r.Next(1000)));
            Elements1.Add(new Element1(r.Next(1000)));
        }

        public IList<Element1> Elements1 { get; set; } = new ObservableCollection<Element1>();
    }
    public class Element1
    {
        public Element1(int num)
        {
            this.num = num;
        }
        public string Title { get; private set; } = "Tytuł";
        public int num { get; private set; }
    }
<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="500">
    <Grid>
        <Grid.DataContext>
            <local:MainWindowViewModel x:Name="hViewModel"/>
        </Grid.DataContext>
        <TabControl ItemsSource="{Binding Path=Elements1}">
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Black" BorderThickness="1">
                        <TextBlock Text="{Binding Path=Title}"/>
                    </Border>
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBlock Text="{Binding Path=num}"/>
                    </Grid>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </Grid>
</Window>

Jeżeli twoja lista filmów będzie taka sama dla każdego elementu TabItemViewModel wtedy możesz znaleźć swój główny ViewModel za pomocą FindAncestor użytego podczas bindingu lub odwołać się do ViewModelu poprzez ElementName:
screenshot-20210323094435.png

    public class MainWindowViewModel
    {
        public MainWindowViewModel()
        {
            Random r = new Random();
            Elements1.Add(new Element1(r.Next(1000)));
            Elements1.Add(new Element1(r.Next(1000)));
            Elements1.Add(new Element1(r.Next(1000)));
            Elements1.Add(new Element1(r.Next(1000)));
            Elements1.Add(new Element1(r.Next(1000)));
            Elements1.Add(new Element1(r.Next(1000)));
        }

        public IList<Element1> Elements1 { get; set; } = new ObservableCollection<Element1>();
        public string TEST { get; private set; } = "Ten tekst znajduje sie w MainWindowViewModel";
    }

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="500">
    <Grid>
        <Grid.DataContext>
            <local:MainWindowViewModel x:Name="hViewModel"/>
        </Grid.DataContext>
        <TabControl ItemsSource="{Binding Path=Elements1}">
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Black" BorderThickness="1">
                        <TextBlock Text="{Binding Path=Title}"/>
                    </Border>
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBlock Text="{Binding ElementName=hViewModel, Path=TEST}"/>
                    </Grid>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </Grid>
</Window>

W Twoim przypadku <ItemsControl ItemsSource="{Binding Path=DataContext.movies Twoim DataContext jest tutaj TabItemViewModel więc powstaje błąd powiązania do właściwości movies

1 użytkowników online, w tym zalogowanych: 0, gości: 1