views:

1251

answers:

3

I want to style my ListBox and displaying some Border around it, i want to hide this Border when ListBox gets focus,

<Trigger Property="IsFocused" Value="True">
  <Setter Property="Visibility" TargetName="border" Value="Collapsed"/>
</Trigger>

Same thing i m using in TextBox also and it is working properly, why this Trigger not working for ListBox?

Edit:

i am having this Style for my ListBox

<ControlTemplate TargetType="{x:Type local:ListBox}">
  <Border SnapsToDevicePixels="true" x:Name="Bd" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="1">
    <Grid>
      <local:ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
      </local:ScrollViewer>
      <Border CornerRadius="5" Background="Red" x:Name="border">
        <TextBlock VerticalAlignment="Center" FontWeight="Bold" Foreground="White" Text="{TemplateBinding Message}" FontFamily="Courier New" />
      </Border>
    </Grid>
  </Border>
</DockPanel>
<ControlTemplate.Triggers>
  <Trigger Property="IsFocused" Value="True">
    <Setter Property="Visibility" TargetName="border" Value="Collapsed"/>
  </Trigger>
  <Trigger Property="IsEnabled" Value="false">
    <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
  </Trigger>
  <Trigger Property="IsGrouping" Value="true">
    <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
  </Trigger>
</ControlTemplate.Triggers>

+1  A: 

I was also having trouble getting your example to work properly. I've concluded that if you click on a ListBoxItem, the IsFocused property is going to be False for the ListBox, because it's really the ListBoxItem that has the focus. You'll see the commented XAML style below trying to achieve your desired effect, which didn't work.

I would imagine that the commented XAML would work if you clicked somewhere within the ListBox where there were no items (i.e. non-ListBoxItem white-space inside the ListBox). Edit: Just tried this, doesn't work either for some reason.

What did work, though, was creating a style for all ListBoxItem objects within the ListBox. That style basically has EventSetters that sets the BorderBrush property of MyListBox appropriately when fired.

XAML:

<ListBox Name="MyListBox" DockPanel.Dock="Top" BorderThickness="2">
    <!--<ListBox.Style>
        <Style TargetType="{x:Type ListBox}">
            <Style.Triggers>
                <Trigger Property="IsFocused" Value="True">
                    <Setter Property="BorderBrush" Value="Red"/>
                    <Setter Property="BorderThickness" Value="2"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </ListBox.Style>-->
    <ListBox.Resources>
        <Style TargetType="{x:Type ListBoxItem}">
            <EventSetter Event="GotFocus" Handler="ListBoxItem_GotFocus"/>
            <EventSetter Event="LostFocus" Handler="ListBoxItem_LostFocus"/>
        </Style>
    </ListBox.Resources>
    <ListBoxItem>Item 1</ListBoxItem>
    <ListBoxItem>Item 2</ListBoxItem>
    <ListBoxItem>Item 3</ListBoxItem>
    <ListBoxItem>Item 4</ListBoxItem>
</ListBox>

Code-Behind:

private void ListBoxItem_GotFocus(object sender, RoutedEventArgs e) {
    MyListBox.BorderBrush = Brushes.Red;
}

private void ListBoxItem_LostFocus(object sender, RoutedEventArgs e) {
    MyListBox.BorderBrush = Brushes.Black;
}

Hope this helped a little!

EDIT: I wasn't satisfied with my original answer (above), because I like doing things declaratively when I code in WPF (no code-behind). I came up with a solution that uses simple color animations that triggers off of the GotFocus and LostFocus routed events.

Here it is:

<ListBox Name="MyListBox" DockPanel.Dock="Top" BorderThickness="2" Height="200">
        <ListBox.BorderBrush>
            <SolidColorBrush Color="Black"/>
        </ListBox.BorderBrush>
        <ListBox.Style>
            <Style TargetType="{x:Type ListBox}">
                <Style.Resources>
                    <Storyboard x:Key="FadeBlack">
                        <ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" 
                                        To="Black" Duration="0:0:0.1"/>
                    </Storyboard>
                    <Storyboard x:Key="FadeRed">
                        <ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" 
                                        To="Red" Duration="0:0:0.1"/>
                    </Storyboard>
                </Style.Resources>
                <Style.Triggers>
                    <EventTrigger RoutedEvent="GotFocus">
                        <BeginStoryboard Storyboard="{StaticResource FadeRed}"/>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="LostFocus">
                        <BeginStoryboard Storyboard="{StaticResource FadeBlack}"/>
                    </EventTrigger>
                </Style.Triggers>
            </Style>
        </ListBox.Style>
        <ListBoxItem>Item 1</ListBoxItem>
        <ListBoxItem>Item 2</ListBoxItem>
        <ListBoxItem>Item 3</ListBoxItem>
        <ListBoxItem>Item 4</ListBoxItem>
    </ListBox>

Happy coding!

EDIT 2: I looked at your updated code, and saw what you were trying to do (I think). I found this neat-o animation at Lester's WPF Blog. You can try putting this in your <ControlTemplate.Triggers> collection:

<EventTrigger RoutedEvent="ListBox.GotFocus">
    <BeginStoryboard>
        <Storyboard>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="border">
                    <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
    </BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="ListBox.LostFocus">
    <BeginStoryboard>
        <Storyboard>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="border">
                <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}" />
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
    </BeginStoryboard>
</EventTrigger>
Pwninstein
i have posted my ControlTemplate which i am using inside my Style for ListBox, can you please tell me what is the problem with my listbox?
viky
Please see my "Edit 2" section of my answer. Hope that helps!
Pwninstein
this is not working for me, How can i get IsFocused property working?
viky
A: 

For ListBox IsFocused not updating because focus does not goes to list box but it goes to area covered by listbox means the ItemsPresenter which contains ListBoxItems. I have got a workaround to this problem. In MouseDown event handler of the ListBox, I call Focus() method. It sets the IsFocused property to true and make my trigger working.

viky
A: 

Pwninstein, why don't you use setters instead of raping that poor animation in your edit 2:

<EventTrigger RoutedEvent="ListBox.GotFocus">
    <Setter TargetName="border" Property="Visibility" Value="Collapsed" />
</EventTrigger>
<EventTrigger RoutedEvent="ListBox.LostFocus">
    <Setter TargetName="border" Property="Visibility" Value="Visible" />
</EventTrigger>

You removed the essential part of the animation found at Lester's which is the opacity changing. Therefore, this is no longer an animation, just a visibility setter.

TWiStErRob