В WPF как поставить рамку вокруг части окна, которая имеет фокус? - PullRequest
4 голосов
/ 24 июня 2010

У меня есть окно с двумя основными областями.Один - это TextBox внутри ScrollViewer, а другой - TabControl.Я хочу иметь красную рамку вокруг части, которая в данный момент имеет фокус, поэтому я написал следующий код, чтобы сделать это

Xaml

<ScrollViewer BorderBrush="Red" 
              BorderThickness="0"
              GotFocus="Border_GotFocus"  
              LostFocus="Border_LostFocus">
    <TextBox/>
</ScrollViewer>
<TabControl BorderBrush="Red" 
            BorderThickness="0"
            GotFocus="Border_GotFocus"  
            LostFocus="Border_LostFocus">
</TabControl>

Код

private void Border_LostFocus(object sender, RoutedEventArgs e)
{
    var control = sender as Control;
    if (control != null)
    {
        control.BorderThickness = new Thickness(0);
    }
}

private void Border_GotFocus(object sender, RoutedEventArgs e)
{
    var control = sender as Control;
    if (control != null)
    {
        control.BorderThickness = new Thickness(2);
    }
}

Проблема в том, что, если я нажимаю на TextBox, он не обновляет границу вокруг ScrollViewer.Если я нажимаю на вкладку в TabControl, она обновляет границу, чтобы я мог видеть границу, но не «удаляет» ее, когда я щелкаю где-то еще.Есть ли лучший способ сделать это?

Ответы [ 2 ]

6 голосов
/ 24 июня 2010

Во-первых, я настоятельно рекомендую не использовать код и хранить все это в XAML.

Во-вторых, я бы также рекомендовал использовать Border для этого.

В-третьих, я бы использовал IsKeyboardFocusedWithin в вашем триггере стиля.

<Window.Resources>
    <Style x:Key="FocusedBorder" TargetType="Border">
        <Setter Property="BorderThickness" Value="2"></Setter>
        <Setter Property="BorderBrush" Value="Transparent"></Setter>
        <Style.Triggers>
            <Trigger Property="IsKeyboardFocusWithin" Value="True">
                <Setter Property="BorderBrush" Value="Red"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<StackPanel Width="400">
    <ScrollViewer>
        <Border Style="{StaticResource FocusedBorder}">
            <TextBox>
            </TextBox>
        </Border>
    </ScrollViewer>
    <TabControl>
        <TabItem Header="Foo">
            <Border Style="{StaticResource FocusedBorder}">
                <TextBox></TextBox>
            </Border>
        </TabItem>
        <TabItem Header="Bar">
            <Border Style="{StaticResource FocusedBorder}">
                <TextBox></TextBox>
            </Border>
        </TabItem>
    </TabControl>
</StackPanel>
0 голосов
/ 30 августа 2011

Принятый ответ не работает для меня. Однако я придумала способ без использования рамки и все еще получаю тот же эффект.

Ниже приведен стиль, используемый для текстового поля.

<Style x:Key="DefaultTextbox" TargetType="{x:Type TextBox}">
    <Setter Property="FontSize" Value="14" />
    <Setter Property="VerticalAlignment" Value="Center" />
    <Setter Property="Margin" Value="5 2 10 2" />
    <Setter Property="FontFamily" Value="Arial" />
    <Setter Property="FontStyle" Value="Normal" />
    <Setter Property="BorderThickness" Value="2" />
    <Setter Property="BorderBrush" Value="Transparent" />
    <Style.Triggers>
        <Trigger Property="IsFocused" Value="True" >
            <Setter Property="BorderBrush" Value="#4E82EC" />
        </Trigger>
    </Style.Triggers>
</Style>

Я столкнулся с некоторыми проблемами со стилем. Первоначально я объявил толщину границы и цвет в триггере. Проблема в том, что когда в поле был текст, казалось, что он прыгнул. Чтобы обойти эффект прыжка, нужно объявить толщину границы по умолчанию и установить прозрачную границу, чтобы при изменении цвета фокуса эффект прыжка отсутствовал.

Тогда вам просто нужно установить стиль для вашего текстового поля:

<TextBox Style="{StaticResource DefaultTextbox}" />

И этот эффект вы увидите.

Sample of what a focused and non focused textbox looks like

...