stil
stil

Reputation: 5556

Set border color of editable ComboBox on focus

What I want to do, is set BorderBrush of editable ComboBox. I'm using slightly modified default WPF templates. They are structured like below:

<ControlTemplate x:Key="ComboBoxEditableTemplate" TargetType="{x:Type ComboBox}">
    ...
    <Grid x:Name="templateRoot" ...>
        ...
        <ToggleButton x:Name="toggleButton" ... />
        <Border x:Name="border" ...>
            <TextBox x:Name="PART_EditableTextBox" ... />
            <!-- textbox with IsFocused property which should be focus trigger -->
        </Border>
    </Grid>
    ...
</ControlTemplate>

ToggleButton template:

<ControlTemplate TargetType="{x:Type ToggleButton}">
    <Border x:Name="templateRoot" ...> <!-- first border brush I want to set on focus -->
        <Border x:Name="innerBorder" ...> <!-- second border brush I want to set on focus -->
            <Border x:Name="splitBorder" ...>
                <Path x:Name="arrow" ... />
            </Border>
        </Border>
    </Border>
</ControlTemplate>

And now, what should happen.

When PART_EditableTextBox.IsFocused is equal to true then set templateRoot.BorderBrush and innerBorder.BorderBrush to another color (for example [removed: red] red and blue).

It would be very simple if there was only one BorderBrush to set, because I could use TemplateBinding to bind this property to ToggleButton element.

For me, the problem are nested templates. I don't know how to refer to inside of another template.

Upvotes: 1

Views: 2397

Answers (3)

stil
stil

Reputation: 5556

Finally, I found the solution by myself. I extended ToggleButton class so it holds additional InnerBorderBrush property.

So now, I'm able to set both outer and inner border with Setter:

<Trigger SourceName="PART_EditableTextBox" Property="IsFocused" Value="True">
    <Setter Property="BorderBrush" Value="Red" TargetName="toggleButton">
    <Setter Property="InnerBorderBrush" Value="Blue" TargetName="toggleButton"></Setter>
</Trigger>

This is how I extended ToggleButton class:

public class ComboBoxToggleButton : ToggleButton
{
    // Dependency Property
    public static readonly DependencyProperty InnerBorderBrushProperty =
     DependencyProperty.Register("InnerBorderBrush", typeof(Brush),
         typeof(ComboBoxToggleButton), new FrameworkPropertyMetadata(Brushes.Transparent));

    // .NET Property wrapper
    public Brush InnerBorderBrush
    {
        get
        {
            return (Brush)GetValue(InnerBorderBrushProperty);
        }
        set
        {
            SetValue(InnerBorderBrushProperty, value);
        }
    }
}

Upvotes: 0

Amit Raz
Amit Raz

Reputation: 5536

You could Use TemplateBinding in the ToggleButton parts and bind them to the same property. and then change it inside the trigger:

 <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Border x:Name="templateRoot" BorderBrush="{TemplateBinding BorderBrush}" >
                            <!-- first border brush I want to set on focus -->
                            <Border x:Name="innerBorder" BorderBrush="{TemplateBinding BorderBrush}">
                                <!-- second border brush I want to set on focus -->
                                <Border x:Name="splitBorder" >
                                    <Path x:Name="arrow"  />
                                </Border>
                            </Border>
                        </Border>
                    </ControlTemplate>

And then in your trigger inside combobox set the the borderbrush of the togglebutton:

<ControlTemplate TargetType="{x:Type ComboBox}">
                        <Grid x:Name="templateRoot" >
                            <ToggleButton x:Name="toggleButton"  />
                            <Border x:Name="border" >
                                <TextBox x:Name="PART_EditableTextBox"  />
                                <!-- textbox with IsFocused property which should be focus trigger -->
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger SourceName="PART_EditableTextBox" Property="IsFocused" Value="True">
                                <Setter Property="BorderBrush" Value="Red" TargetName="toggleButton"></Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>

UPDATE You can change the ControlTemplate of the ToggleButton to look like this:

<ControlTemplate TargetType="{x:Type ToggleButton}">
                    <Border x:Name="templateRoot" BorderBrush="{TemplateBinding BorderBrush}" >
                        <!-- first border brush I want to set on focus -->
                        <Border x:Name="innerBorder" BorderBrush="{Binding ElementName=templateRoot, Path=BorderBrush, Converter={SomeColorConverter}}">
                            <!-- second border brush I want to set on focus -->
                            <Border x:Name="splitBorder" >
                                <Path x:Name="arrow"  />
                            </Border>
                        </Border>
                    </Border>
                </ControlTemplate>

This way you can trigger the binding once BorderBrush is changed through the trigger and use the converter to set a different color.

Upvotes: 1

user853710
user853710

Reputation: 1767

A trigger can take care of this for you

<UserControl x:Class="Sample2.ContactSearchControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="75" Width="300">
    <Border>
        <Border.Style>
            <Style TargetType="Border">
                <Setter Property="Background" Value="White" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsFocused, ElementName=txtSearch}" Value="true">
                        <Setter Property="Background" Value="Black" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Border.Style>
        <StackPanel>
            <TextBox x:Name="txtSearch" Text="Search" />
            <TextBox Text="Other" />
        </StackPanel>
    </Border>
</UserControl>

Upvotes: 0

Related Questions