Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a ListBox with items that expand when selected (Accordion)

Tags:

c#

xaml

listbox

uwp

There's solutions to this problem for older XAML based UI frameworks (WPF/SL) but they're not easily adaptable to the Universal Windows Platform.

I'm trying to create a list of items that show only limited details in default state and expands, when it's selected, to quickly edit some data.
I have not found a way to create a that expanding behavior, though it is similar to what the Windows 10 Mail app does, with conversations. When a message of a conversation is selected, the other messages of that conversation kind of drop down or slide down.

Below is an example of a list where I'd like to display only the name at first.

<ListBox ItemsSource="{x:Bind Persons}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate x:DataType="src:Person">
            <StackPanel HorizontalAlignment="Stretch" Width="Auto">
                <TextBlock Text="{x:Bind Path=Name, Mode=OneWay}" Margin="12, 15, 12, 0" FontSize="18.667" />
                <TextBox HorizontalAlignment="Stretch" Margin="12, 12, 12, 0" FontSize="18.667" Text="{x:Bind Path=Name, Mode=TwoWay}" />
                <TextBlock Text="Date of birth" Margin="12, 15, 12, 0" />
                <DatePicker Margin="12, 5, 12, 0" Date="{x:Bind Path=DateOfBirth, Mode=TwoWay}" />
                <TextBlock Text="Domicile" Margin="12, 15, 12, 0" />
                <TextBox Margin="12, 5, 12, 0" Text="{x:Bind Path=Domicile, Mode=OneWay}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

In WPF, such behavior could be achieved with triggers Style.Triggers but they're not available anymore.

Original Source Code on GitHub

like image 862
Gabriel Koch Avatar asked Nov 09 '22 20:11

Gabriel Koch


1 Answers

Here's what you want to do. You want to use the ListViewItem.IsSelected property that is natively set by the ListView. Then, you want to react to that value change and set a visual state that reveals or hides your details.

Like this:

class MyModel
{
    public bool IsSelected { get; set; }
}

class MyList : Windows.UI.Xaml.Controls.ListView
{
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        var model = item as MyModel;
        var listViewItem = element as Windows.UI.Xaml.Controls.ListViewItem;

        var binding = new Windows.UI.Xaml.Data.Binding
        {
            Source = model,
            Mode = Windows.UI.Xaml.Data.BindingMode.TwoWay,
            Path = new PropertyPath(nameof(model.IsSelected)),
        };
        listViewItem.SetBinding(Windows.UI.Xaml.Controls.ListViewItem.IsSelectedProperty, binding);
        base.PrepareContainerForItemOverride(element, item);
    }
}

Funny enough but this code is somewhat based on the code used for variable sized wrap grids. You can read the original article here.

http://blog.jerrynixon.com/2012/08/windows-8-beauty-tip-using.html

If you want to learn more about the Visual States, you might read over the blog article I wrote on the same subject.

http://blog.jerrynixon.com/2013/11/windows-81-how-to-use-visual-states-in.html

Something like this:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Interactivity:Interaction.Behaviors>
        <Core:DataTriggerBehavior Binding="{Binding IsSelected}" Value="True">
            <Core:GoToStateAction StateName="BigVisualState"/>
        </Core:DataTriggerBehavior>
        <Core:DataTriggerBehavior Binding="{Binding IsSelected}" Value="False">
            <Core:GoToStateAction StateName="LittleVisualState"/>
        </Core:DataTriggerBehavior>
    </Interactivity:Interaction.Behaviors>

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="VisualStateGroup">
            <VisualState x:Name="BigVisualState"/>
            <VisualState x:Name="LittleVisualState"/>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

</Grid>

If you would like to learn more about XAML behaviors in Windows apps, you can read the article I wrote on the subject.

http://blog.jerrynixon.com/2013/10/everything-i-know-about-behaviors-in.html

I also recorded a course you might like.

https://mva.microsoft.com/en-US/training-courses/designing-your-xaml-ui-with-blend-jump-start-8260?l=p2dPykKy_5104984382

I hope this helps.

Best of luck!

like image 70
Jerry Nixon Avatar answered Nov 14 '22 21:11

Jerry Nixon