简体   繁体   中英

Only highlight currently selected item in ListBox

I have a ListBox being populated with images from isolated storage. The user is allowed to select the image to perform some action upon it. To notify the user of the currently selected image in the list, I simply have placed a border around the selected item. However, when a new image is selected in the list, the border is placed around that image as well, so now both images have a border. I would like to find a way to remove the previously selected image's border so that only the currently selected image is highlighted.

What I have so far is as follows:

MainPage.xaml

 <ListBox x:Name="Recent" ItemsSource="{Binding Pictures}" Margin="8" 
                     SelectionChanged="recent_SelectionChanged" toolkit:TiltEffect.IsTiltEnabled="True">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <toolkit:WrapPanel Orientation="Horizontal" />
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
                <ListBox.ItemTemplate>
                    <DataTemplate>                            
                        <Border>
                            <Image x:Name="recentImage" Source="{Binding Source}" Margin="12" Width="115"/>
                        </Border>
                    </DataTemplate>
                </ListBox.ItemTemplate>
</ListBox>

MainPage.xaml.cs

private void recent_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        //Place border round currently selected image
        var lb = sender as ListBox;
        var lbi = lb.ItemContainerGenerator.ContainerFromItem(lb.SelectedItem) as ListBoxItem;

        lbi.BorderThickness = new Thickness(2, 2, 2, 2);
        lbi.BorderBrush = new SolidColorBrush((Color)Application.Current.Resources["PhoneAccentColor"]);

        //Where and how to remove border from previously selected image?
    }

So, I am not sure of what exactly to do to accomplish this. How might I detect the previously selected image item in the ListBox, or determine which item has the border and remove it before adding the border to the currently selected item? Any thoughts or references?

You need just edit ItemContainer style of your ListBox .
Like this:

<phone:PhoneApplicationPage.Resources>
<Style x:Key="MyStyle" TargetType="ListBoxItem">
  <Setter Property="Background" Value="Transparent"/>
  <Setter Property="BorderThickness" Value="0" />
  <Setter Property="Padding" Value="0" />
  <Setter Property="HorizontalContentAlignment" Value="Left"/>
  <Setter Property="VerticalContentAlignment" Value="Top"/>
  <Setter Property ="Foreground" Value="White" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ListBoxItem">
        <Border x:Name="LayoutRoot" Background="{TemplateBinding Background}" 
                HorizontalAlignment="{TemplateBinding HorizontalAlignment}" 
                VerticalAlignment="{TemplateBinding VerticalAlignment}" 
                BorderBrush="{TemplateBinding BorderBrush}" 
                BorderThickness="{TemplateBinding BorderThickness}">
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
               <VisualState x:Name="Normal"/>
              <VisualState x:Name="MouseOver" />
              <VisualState x:Name="Disabled">
                <Storyboard>
                  <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Background">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TransparentBrush}"/>
                  </ObjectAnimationUsingKeyFrames>
                  <DoubleAnimation Storyboard.TargetName="ContentContainer" Storyboard.TargetProperty="Opacity" Duration="0" To=".5" />
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
            <VisualStateGroup x:Name="SelectionStates">
              <VisualState x:Name="Unselected"/>
              <VisualState x:Name="Selected">
                  <Storyboard>
                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="brd"
                                    Storyboard.TargetProperty="BorderThickness">
                          <DiscreteObjectKeyFrame KeyTime="0" Value="2" />
                      </ObjectAnimationUsingKeyFrames>
                  </Storyboard>
              </VisualState>
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
                    <Border x:Name="brd" CornerRadius="10" BorderBrush="White" Width="Auto" BorderThickness="{TemplateBinding BorderThickness}">
                         <Image x:Name="recentImage" Source="{Binding Source}" Margin="12" Width="115"/>
                    </Border>
                </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
</phone:PhoneApplicationPage.Resources>

And your ListBox will be:

<ListBox x:Name="Recent" ItemsSource="{Binding Pictures}" Margin="8" 
                 SelectionChanged="recent_SelectionChanged" toolkit:TiltEffect.IsTiltEnabled="True" ItemContainerStyle="{StaticResource MyStyle}">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <toolkit:WrapPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>

Instead of highlighting selected item from code behind, why not set style for selected item in client side.

What I mean to say is, you can use <Style.Triggers> to set the style for selected item in your listbox. (Assuming only one item can be selected at a time)

Sample code- (this sets background of selected item to white . You can apply your style here)

  <Style x:Name="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
        <Style.Triggers>
            <Trigger Property="Selector.IsSelected" Value="True">
                <Setter Property="Background" Value="White" />
            </Trigger>
        </Style.Triggers>
    </Style>

You may do something like this. (This is just a skeleton. you will have to implement the class properly)

    public class MyImage
    {
        public string ImagePath { get; set; }
        public bool IsSelected { get; set; }
    }

Set a collection of this class as the source of your listbox. When you select an item Mark

     IsSelected=true; 

Remember this property should be "false" for all unselected items.

Now your borders visibility can be set based on IsSelected property.Hope this helps.

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