简体   繁体   中英

WPF Bind to Parent's SelectedItem's Property From BasedOn

I have the following style:

<SolidColorBrush x:Key="TabPanelBorderBrush" Color="#007ACC"/>
<Style TargetType="{x:Type local:MetroTabControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MetroTabControl}">
                <Grid>
                    <Grid KeyboardNavigation.TabNavigation="Local" SnapsToDevicePixels="True">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Grid>
                            <ScrollViewer x:Name="ScrollViewer" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Hidden" Style="{DynamicResource TabPanelScrollViewer}">
                                <TabPanel x:Name="HeaderPanel" IsItemsHost="True" Panel.ZIndex="1" KeyboardNavigation.TabIndex="1"/>
                            </ScrollViewer>
                            <Button x:Name="AddTabItem" Content="&#xE109;"  Style="{DynamicResource TabControlButton}" HorizontalAlignment="Right" VerticalAlignment="Top"/>
                        </Grid>
                        <Border Grid.Row="1" x:Name="TabPanelBorder" Background="Transparent">
                            <Rectangle x:Name="TabPanelBorderRectangle" Fill="{DynamicResource TabPanelBorderBrush}" Height="2"/>
                        </Border>
                        <Border Grid.Row="2" Background="{StaticResource TabControlBackground}"/>
                        <ContentPresenter Grid.Row="2" Name="PART_SelectedContentHost" ContentSource="SelectedContent"/>
                    </Grid>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

I want to bind the TabPanelBorderRectangle's Fill color to the TabControl 's SelectedItem 's Foreground .
So I wrote the following:

<Rectangle x:Name="TabPanelBorderRectangle" Fill="{Binding SelectedItem.Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}" Height="2"/>

And it works.

Now, I have another style, BasedOn the above.
In the BasedOn style, I want to put the line above, but when I do it doesnt work.

Here's my BasedOn Style:

<Style x:Key="CustomizedMetroTabControl" TargetType="{x:Type local:MetroTabControl}" BasedOn="{StaticResource {x:Type local:MetroTabControl}}">
    <Style.Resources>
        <SolidColorBrush x:Key="TabPanelBorderBrush" Color="{Binding SelectedItem.Foreground, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}"/>
    </Style.Resources>
</Style>

When I change the Color to anything else (green, blue etc...) it works.
Whats the problem with my binding? why it doesn't work in the BasedOn style but it does in the original?

It's funny how you say that you didn't have an errors in the Output Window in Visual Studio because when I added your code to a new project and ran it, I got the following error:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.TabControl', AncestorLevel='1''. BindingExpression:Path=SelectedItem.Foreground; DataItem=null; target element is 'SolidColorBrush' (HashCode=16700594); target property is 'Color' (type 'Color')

Of course I swapped your local:MetroTabControl for a plain old TabControl , but the error would have been the same. You're getting this error because you have a TabControl that is looking for a property on another TabControl that is an ancestor of this one .

Had you tried to use the TemplatedParent RelativeSource Binding that you used on the Rectangle in the ControlTemplate you would have go the following error:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=SelectedItem.Foreground; DataItem=null; target element is 'SolidColorBrush' (HashCode=56437836); target property is 'Color' (type 'Color')

This error is more helpful because it basically tells you that you can't access an element from a ControlTemplate from outside that template, or more accurately as Rohit mentioned in his comment, you can't access an element that is not in the connected visual tree.

So, to answer your question, your TemplatedParent Binding worked in the main Style not because it was simply in the main Style , but because it was in the ControlTemplate in the Style . Therefore your BasedOn Style didn't work because it was not in the ControlTemplate . If you had defined the ControlTemplate again in your BasedOn Style then it would have worked, but clearly you wouldn't want to do that.

A better idea to fulfil your requirement would be to Bind the TabControl.SelectedIndex property to an int property in your view model and then Binding to that same int property and use a simple IntegerToColorConverter for your Rectangle.Fill property.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM