简体   繁体   中英

How to programatically select an item in a data bound ListBox control

I have a custom styled ListBox:

<phone:PhoneApplicationPage.Resources>
    <Style x:Key="LayoutsListItemStyle" TargetType="ListBoxItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <Grid Height="170" Width="170" Margin="0,0,20,20">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="LayoutStates">
                                <VisualState x:Name="BeforeUnloaded"/>
                                <VisualState x:Name="BeforeLoaded"/>
                                <VisualState x:Name="AfterLoaded"/>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="SelectionStates">
                                <VisualState x:Name="Unselected"/>
                                <VisualState x:Name="Selected">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderThickness)" Storyboard.TargetName="border">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Thickness>4</Thickness>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="SelectedUnfocused"/>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Border x:Name="border" Width="170" Height="170" BorderBrush="{StaticResource PhoneAccentBrush}">
                            <Grid>
                                <Image Source="{Binding ThumbnailPath}" Width="170" Height="170" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                            </Grid>
                        </Border>

                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</phone:PhoneApplicationPage.Resources>

and

<ListBox x:Name="LayoutsList" ItemContainerStyle="{StaticResource LayoutsListItemStyle}" ItemsSource="{Binding}">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <toolkit:WrapPanel Orientation="Horizontal" MaxWidth="410" />
         </ItemsPanelTemplate>
     </ListBox.ItemsPanel>
 </ListBox>

which displays a border over the selected listbox item (when selected manually). I would like the items in the listbox to act like radio buttons and the first item in the listbox to be selected by default.

I'm trying to set the SelectedIndex of the listbox like this:

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    // Loads a list of available Layouts to a ListBox

    XDocument layoutSummary = XDocument.Load("Content/LayoutSummary.xml");

    var layouts =
        from elem in layoutSummary.Descendants("ComicLayout")
        select new ComicLayout
        {
            Name = (string)elem.Attribute("Name").Value,
            FriendlyName = (string)elem.Attribute("FriendlyName").Value,
            ThumbnailPath = "Content/LayoutIcons/" + (string)elem.Attribute("Name").Value + ".png"
        };

    LayoutsList.DataContext = layouts;

    LayoutsList.SelectedIndex = 1;
}

but it doesn't seem to be doing anything.

How can I programatically select the first (or any other) item in a data bound ListBox?

EDIT

It turns out that SelectedIndex actually works and I can control it and pull the data out of the ListBox as I wish.

So I guess the question would be:

How to I trigger VisualState change on the listbox item programatically?

I've managed to achieve this by hooking up to LayoutUpdated event on the ListBox control

<ListBox x:Name="LayoutsList" ItemContainerStyle="{StaticResource LayoutsListItemStyle}" ItemsSource="{Binding}" LayoutUpdated="LayoutsList_LayoutUpdated">

and the LayoutsList_LayoutUpdated() :

private void LayoutsList_LayoutUpdated(object sender, EventArgs e)
{
    if ((ListBoxItem)LayoutsList.ItemContainerGenerator.ContainerFromIndex(LayoutsList.SelectedIndex) != null)
    {
        ListBoxItem selectedItem = (ListBoxItem)LayoutsList.ItemContainerGenerator.ContainerFromIndex(LayoutsList.SelectedIndex);

        VisualStateManager.GoToState(selectedItem, "Selected", true);

    }
}

Seems a little bit like a brute-force to me but it works and it will keep looping until it can find the element it needs.

Hope that helps someone

In WPF you should never get or set the SelectedIndex manually. Instead, set the current item of the ListCollectionView which is bound to the control. The selected index is bound to the current item of the collection view.

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