1

I have TextBoxes and FakeTextBoxes in my application. FakeTextBoxes acts as TextBoxes, but they have more functionality as they have buttons, and/or images inside it. XAML for a FakeTextBox looks something like this:

                <Border BorderThickness="1">
                    <StackPanel Orientation="Horizontal">
                        <TextBox BorderThickness="0" />
                        <Button>I'm a button inside textbox</Button>
                    </StackPanel>
                </Border>

TextBox in my project have a custom styling that changes its BorderBrush depending on its IsMouseOver and GotFocus properties. The generic style comes from mahapps.metro and you can find it here : https://github.com/MahApps/MahApps.Metro/blob/develop/MahApps.Metro/Styles/Controls.TextBox.xaml

The problem is that I can't apply the same behaviour for the border of my FakeTextBox. I want to have the exactly same behavior on my custom Border so that it'll look like exactly the same as other TextBoxes.

What I've tried and didn't work for Border:

  • Binding to BorderBrush property of inner TextBox.
  • Binding to IsFocused property of TextBox : IsFocused has no setter.
  • Creating a hidden TextBox and binding to its BorderBrush

Is there a generic and/or easy solution to it?

U. Bulle
  • 1,075
  • 9
  • 20
  • is `FakeTextBox` derived from `TextBox`? can you show custom TextBox style as well? – ASh Jul 18 '16 at 09:31
  • It's not actually. It's just a code piece in a view / user control. Here is the custom style for TextBox https://github.com/MahApps/MahApps.Metro/blob/develop/MahApps.Metro/Styles/Controls.TextBox.xaml. – U. Bulle Jul 18 '16 at 10:26
  • Could you show us the code (xaml too) making up the FakeTextBox? – Logan Jul 18 '16 at 13:22

2 Answers2

2

Since you want to copy Border behaviour, lets look for BorderBrushes in the TextBox Style en how they're implemented. Found three, to get their Keys a visit to the Colors section.

<Border BorderThickness="1">
    <Border.Resources>
        <Color x:Key="BlackColor">#FF000000</Color>
        <Color x:Key="Gray2">#FF7F7F7F</Color>
        <Color x:Key="Gray6">#FFCCCCCC</Color>
        <SolidColorBrush x:Key="TextBoxBorderBrush" Color="{StaticResource Gray6}" />
        <SolidColorBrush x:Key="TextBoxMouseOverBorderBrush" Color="{StaticResource Gray2}" />
        <SolidColorBrush x:Key="TextBoxFocusBorderBrush" Color="{StaticResource BlackColor}" />
    </Border.Resources>
    <Border.Style>
        <Style TargetType="{x:Type Border}">
            <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorderBrush}" />
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="BorderBrush" Value="{StaticResource TextBoxMouseOverBorderBrush}" /> 
                </Trigger>
                <EventTrigger RoutedEvent="Control.GotFocus">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" To="White" Duration="0:0:0.250"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </Border.Style>
    <StackPanel>
        <TextBox BorderThickness="0" />
        <Button>I'm a button inside textbox</Button>
    </StackPanel>
</Border>

The IsFocused BorderBrush is tricky because it's the TextBox's IsFocused property you're after. Doing it right you would want to declare an Attached Property IsFocused on the Border and bind it to the TextBox's IsFocused or make it a Custom Border all together.

Funk
  • 10,976
  • 1
  • 17
  • 33
  • Thank you Funk, I think I'll go for this way. Just a question to get this working with other themes too : I change `To="White"` to `To="{StaticResource BlackColor}"` it does not work. `BlackColor` is defined in `MahApps` though :\. Any ideas? **Edit :** I've just realised that this code changes the color of every single border in the WPF view, even though I only want to change the border of the `FakeTextBox`. – U. Bulle Jul 19 '16 at 16:16
  • @U.Bulle You're welcome. The Style is only applied to the outher border. For a Style to apply to all instances, it would have to be declared in Resources. What you're experiencing is that the Keys of the colors are overwritten in Border.Resources. You can take them out one by one and see what happens. – Funk Jul 19 '16 at 22:41
0

I have had countless problems with this one.

The solution for me was to create three different borders.

  • FocusBorder
  • MouseOverBorder
  • NormalBorder

FocusBorder stays on the top, MouseOverBorder stays in the middle layer, and NormalBorder in the lowest level.

Visibility of FocusBorderis decided by Control.GotFocus and Control.LostFocus event triggers. Same behavior for the MouseOverBorder for Control.MouseEnter and Control.MouseLeave events.

<UserControl.Triggers>
        <EventTrigger RoutedEvent="Control.GotFocus">
            <BeginStoryboard>
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames
                                        Storyboard.TargetName="FocusBorder"
                                        Storyboard.TargetProperty="Visibility"
                                        Duration="1">
                        <DiscreteObjectKeyFrame KeyTime="0">
                            <DiscreteObjectKeyFrame.Value>
                                <Visibility>Visible</Visibility>
                            </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="Control.LostFocus">
            <BeginStoryboard>
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames
                                        Storyboard.TargetName="FocusBorder"
                                        Storyboard.TargetProperty="Visibility"
                                        Duration="1">
                        <DiscreteObjectKeyFrame KeyTime="0">
                            <DiscreteObjectKeyFrame.Value>
                                <Visibility>Collapsed</Visibility>
                            </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="Control.MouseEnter">
            <BeginStoryboard>
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames
                                        Storyboard.TargetName="MouseOverBorder"
                                        Storyboard.TargetProperty="Visibility"
                                        Duration="1">
                        <DiscreteObjectKeyFrame KeyTime="0">
                            <DiscreteObjectKeyFrame.Value>
                                <Visibility>Visible</Visibility>
                            </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="Control.MouseLeave">
            <BeginStoryboard>
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames
                                        Storyboard.TargetName="MouseOverBorder"
                                        Storyboard.TargetProperty="Visibility"
                                        Duration="1">
                        <DiscreteObjectKeyFrame KeyTime="0">
                            <DiscreteObjectKeyFrame.Value>
                                <Visibility>Collapsed</Visibility>
                            </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </UserControl.Triggers>
    <Grid>
        <Border x:Name="FocusBorder" BorderBrush="{DynamicResource ComboBoxMouseOverInnerBorderBrush}"
                Canvas.ZIndex="3" BorderThickness="1" Visibility="Collapsed" />
        <Border x:Name="MouseOverBorder" BorderBrush="{DynamicResource TextBoxMouseOverBorderBrush}"
                Canvas.ZIndex="2" BorderThickness="1" Visibility="Collapsed" />
        <Border BorderBrush="{DynamicResource TextBoxBorderBrush}"
                Canvas.ZIndex="1"  BorderThickness="1" />
        <TextBox BorderThickness="0"></TextBox>
    </Grid>
U. Bulle
  • 1,075
  • 9
  • 20