DesTunK DesTunK - 3 months ago 29
C# Question

How to fill ContentPresenter by binding

I've a problem to connect.

I started to connect my

tabs
with a
tabcontrol.ressources
and it worked to show the text of each tabs.
Then I wanted to had a scroll for my
TabItems
and it doesn't work, nothing shows in tab... I can't even use
tabcontrol.ressources
anymore...

<DockPanel>
<Button Background="DarkGoldenrod" Height="Auto" Command="{Binding OpenFlyoutDataCommand}">
<StackPanel>
<materialDesign:PackIcon Kind="ArrowRightBoldCircleOutline" Width="30" Height="30"/>
</StackPanel>
</Button>
<TabControl ItemsSource="{Binding TabEDCWaferData, Mode=TwoWay}"
SelectedItem="{Binding SelectedTabEDCWaferData}">

<!-- Used to create a scroolbar for tabitems -->

<TabControl.Template>
<ControlTemplate TargetType="TabControl">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden" >
<TabPanel Grid.Column="0" Grid.Row="0"
Margin="2,2,2,0" IsItemsHost="true"/>
</ScrollViewer>
<ContentPresenter ContentSource="..."/>
</Grid>
</ControlTemplate>
</TabControl.Template>

<!-- Contains the text in the tab item ! -->

<TabControl.Resources>
<DataTemplate DataType="TabItem">
<DockPanel>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Content}" />
</DockPanel>
</DataTemplate>
</TabControl.Resources>

</TabControl>
</DockPanel>


This is connected to a collection of
TabItem
, where I've a function to add
Items
binding to an other button.

private ObservableCollection<TabItem> _TabEDCWaferData;
public ObservableCollection<TabItem> TabEDCWaferData
{
get { return _TabEDCWaferData; }
set
{
_TabEDCWaferData = value;
RaisePropertyChanged("TabEDCWaferData");
}
}

public void AddTabItem(string name)
{
TabItem tab = new TabItem();
tab.Header = name;
tab.Content = "Temporary content";
TabEDCWaferData.Add(tab);
}


I read that I have to use the
ContentPresenter
, but I don't know how to bind it. I think this is not working with
TabItems
...
I just want to bind it as I did in the
Ressources
by using the
ContentPresenter
.

I hope that I'm clear enough ! Thanks

EDIT : I try to display in the
ContentPresenter
the selected item tab content that I add in the function `AddTabItem.

Answer

With ContentPresenter, most times, this does the job:

 <ContentPresenter />

The default ContentSource is "Content". That means it'll look at the Content property of the templated parent and it'll take whatever it finds there for its own content.

But that doesn't help you at all, and you don't have to use ContentPresenter; it's just a convenience. In this case, the content you want to present is SelectedItem.Content, which isn't a valid ContentSource for ContentPresenter. But you can do the same thing with a binding on a ContentControl instead:

<TabControl.Template>
    <ControlTemplate TargetType="TabControl">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition />
            </Grid.RowDefinitions>
            <ScrollViewer 
                Grid.Row="0"
                HorizontalScrollBarVisibility="Auto"  
                VerticalScrollBarVisibility="Hidden" 
                >
                <TabPanel 
                    Grid.Column="0" 
                    Margin="2,2,2,0" IsItemsHost="true"/>
            </ScrollViewer>
            <ContentControl
                Grid.Row="1"
                Content="{Binding SelectedItem.Content, RelativeSource={RelativeSource TemplatedParent}}"
                />
        </Grid>
    </ControlTemplate>
</TabControl.Template>

TemplateBinding isn't going to work with a Path such as "SelectedItem.Content"; it only accepts names of properties on the templated parent. I fixed your Grid.Row attributes, too.

Also, you may as well delete that DataTemplate for TabItem that you put in TabControl.Resources. That's not what DataTemplate is for; you use DataTemplates to define visual presentations for your viewmodel classes, but TabItem is a control. It already knows how to display itself, and in fact that DataTemplate is being ignored, so it's best not to leave it there; you'll only waste time later on making changes to it and trying to figure out why it's not having any effect. Your TabItems will display correctly without it.