Retaining selected item in sublist in DataTemplate

2019-09-18 10:09发布

问题:

I have generated an expandable Listview in Windows Phone 8.1. I'm switching templates on item selection changed and item click.

    <ListView Name="FiltersListview" ItemContainerStyle="{StaticResource StretchItemStyle}" ItemTemplate="{StaticResource CollapsedTemplate}" SelectionChanged="FiltersListview_SelectionChanged" IsItemClickEnabled="True" ItemClick="FiltersListview_ItemClick" Grid.Row="1" Grid.ColumnSpan="2"/>

<DataTemplate x:Name="CollapsedTemplate">
            <Grid Height="50">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="3*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding Name}" VerticalAlignment="Center" Style="{StaticResource PageTextStyle}"/>
                <Image Margin="10" Grid.Column="1" Source="/Images/arrow-down.png"/>
                <Rectangle Fill="Black" VerticalAlignment="Bottom" Height="1" Grid.ColumnSpan="2"/>
            </Grid>
        </DataTemplate>
        <DataTemplate x:Name="ExpandedTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="3*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="50"/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <TextBlock Text="{Binding Name}" VerticalAlignment="Center" Style="{StaticResource PageTextStyle}"/>
                <Image Margin="10" Grid.Column="1" Source="/Images/arrow-up.png"/>
                <ListView Margin="20,0" Grid.Row="1" RequestedTheme="Light" Grid.ColumnSpan="2" ItemsSource="{Binding SubList}" SelectionMode="Multiple">
                    <ListView.ItemContainerStyle>
                        <Style TargetType="ListViewItem">
                            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                            <Setter Property="FontSize" Value="22"/>
                            <Setter Property="VerticalContentAlignment" Value="Center"/>
                            <Setter Property="Foreground" Value="Black"/>
                        </Style>
                    </ListView.ItemContainerStyle>
                </ListView>
            </Grid>
        </DataTemplate>

and then template changing

DataTemplate dtSmall, dtLarge;
private void FiltersListview_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                if (e.RemovedItems.Count > 0)
                {
                    foreach (var item in e.RemovedItems)
                    {
                        ((ListViewItem)(sender as ListView).ContainerFromItem(item)).ContentTemplate = dtSmall;
                    }
                }
                if (e.AddedItems.Count > 0)
                {
                    foreach (var item in e.AddedItems)
                    {
                        ((ListViewItem)(sender as ListView).ContainerFromItem(item)).ContentTemplate = dtLarge;
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
        }

        private void FiltersListview_ItemClick(object sender, ItemClickEventArgs e)
        {
            try
            {
                if ((sender as ListView).SelectedItem != null)
                {
                    if ((sender as ListView).SelectedItem.Equals(e.ClickedItem))
                        (sender as ListView).SelectedItem = null;
                    else
                        (sender as ListView).SelectedItem = e.ClickedItem;
                }
                else
                    (sender as ListView).SelectedItem = e.ClickedItem;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
        }

Now when expandable list is opened I want to retain the selected item status in sublist but as the template is changed and a new listview is created it is not retaining the selected items. Can somebody help?

回答1:

Wow. You are sort of cracking nuts with a steamroller here. Instead of switching templates, why not create a sophisticated Data Template that when selected shows secondary content?

If you derive from ListView, you can override PrepareContainer:

public class MyListView : Windows.UI.Xaml.Controls.ListView
{
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        var item = element as Windows.UI.Xaml.Controls.ListViewItem;
        base.PrepareContainerForItemOverride(element, item);
    }
}

In here, you have access to the IsSelected property which you can bind to your model (just create a property) and surface in your data template. Using this value, you can switch between content in your data template.

I would use behaviors so I wouldn't have to think very hard about this. Something like this:

<Grid>
    <Interactivity:Interaction.Behaviors>
        <Core:DataTriggerBehavior Binding="{Binding IsSelected}" Value="True">
            <Core:ChangePropertyAction TargetObject="{Binding ElementName=view1}" PropertyName="Visibility" Value="Visible"/>
            <Core:ChangePropertyAction TargetObject="{Binding ElementName=view2}" PropertyName="Visibility" Value="Collapsed"/>
        </Core:DataTriggerBehavior>
        <Core:DataTriggerBehavior Binding="{Binding IsSelected}" Value="False">
            <Core:ChangePropertyAction TargetObject="{Binding ElementName=view1}" PropertyName="Visibility" Value="Visible"/>
            <Core:ChangePropertyAction TargetObject="{Binding ElementName=view2}" PropertyName="Visibility" Value="Collapsed"/>
        </Core:DataTriggerBehavior>
    </Interactivity:Interaction.Behaviors>
</Grid>

Since your context never really changes, neither will your List index.

Best of luck!