Alireza Alireza - 26 days ago 13
C# Question

Why doesn't my styled ToggleButton work on the second tab of a TabControl?

I encountered a problem when I was developing a WPF application with a TabControl object. I tried to debug and find the problem and finally I've got it, but I didn't find any workaround to it. Here is some explanation:

I used this data grid filtering library (here is a codeproject url), which is the best (from my viewpoint). I want to customize it with the google material design theme and change some graphical features, such as using a toggle button in the first tab header of data gird to hide/show the filtering option.

I created a user control and placed my custom datagrid in it. Then I embedded that control into the tabItem. When I set this control to the first tabItem, everything works correctly. But when I change the user control to the other tabItem, the toggle button does not work.

Here is my main window xaml code that didn't work:

<TabControl x:Name="tabControl">
<TabItem Header="1'st Tab">
<ContentControl DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type Window}}}">
<Button Content="Do no thing"></Button>
</ContentControl>
</TabItem>
<TabItem Header="2'nd Tab">
<ContentControl DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type Window}}}">
<local:UserControl1/>
</ContentControl>
</TabItem>
</TabControl>


Note that if I change the order of TabItems, it works well. Does anyone have a suggestion how to solve this problem? Here is my sample project code on Github

Control was placed in the first tab
Control was placed in the other tab

Edit: Today, I test my application with "WPF Inspector" to find the structure of visual and logical tree. The behavior was too strange because when I attached "WPF Inspector" to my application, everything started to work. The below GIF is what I did:

Strange behavior GIF

Answer

This is not how you use a ContentControl.

When using a ContentControl for a Data-Object, in your case it's the data context, you bind the Content property to the Data-Object and specify the DataTemplate property. In this case the content within DataTemplate will have its DataContext set your Data-Object.

Here is a working sample:

    <TabControl x:Name="tabControl">
        <TabItem Header="1'st Tab">
            <ContentControl Content="{Binding .}">
                <ContentControl.ContentTemplate>
                    <DataTemplate>
                        <Button Content="Do no thing"></Button>
                    </DataTemplate>
                </ContentControl.ContentTemplate>
            </ContentControl>
        </TabItem>
        <TabItem Header="2'nd Tab">
            <ContentControl Content="{Binding .}">
                <ContentControl.ContentTemplate>
                    <DataTemplate>
                        <local:UserControl1/>
                    </DataTemplate>
                </ContentControl.ContentTemplate>
            </ContentControl>
        </TabItem>
    </TabControl>
Comments