listview visual state manager in item template (Wi

2019-04-10 05:28发布

问题:

I am trying to get a listview to display a list of items made up of textblocks... when the listview item is clicked i would like to show instead a list made up of textboxes...

Below is what i have come up with, it does not work. I have two grids within the templates and was hoping to simply show and hide the grids depending on if the listview item is selected. Where have i gone wrong?

I ripped these visual states from the listview's template itself but i must admit im not sure how they work, or how they are meant to be triggered. Should there be some code behind to do this?

    <ListView Grid.Row="2" ItemsSource="{Binding Lines}" HorizontalAlignment="Stretch">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid Name="Readonly">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="3*"/>
                        </Grid.ColumnDefinitions>

                        <TextBlock Text="{Binding One}" Grid.Column="0"/>
                        <TextBlock Text="{Binding Two}" Grid.Column="1"/>
                    </Grid>
                    <Grid Name="Editing" Visibility="Collapsed">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="3*"/>                            
                        </Grid.ColumnDefinitions>

                        <TextBox Text="{Binding One}" Grid.Column="0"/>
                        <TextBox Text="{Binding Two}" Grid.Column="1"/>
                    </Grid>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="SelectionStates">
                            <VisualState x:Name="Selected">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Editing" Storyboard.TargetProperty="Visibility">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Readonly" Storyboard.TargetProperty="Visibility">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

Many thanks, Kohan

回答1:

You are setting the Storyboard Animation up outside the Items that are being rendered. The targets you are specifying are not only out of the scope of the outer page, but they potentially do not exist yet. As a result, the Storyboard cannot be setup when the page is rendered.

Here's what you want to do.

Create a user control that will represent the layout you want in your ListView item. When you define your ListView, be sure to include your UserControl in your DataTemplate, like this:

<ListView>
        <ListView.ItemTemplate>
            <DataTemplate>
                <local:MyUserControl />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView.ItemsPanel>
</ListView>

Now, for the VisualStates. You need to set the states up inside the UserControl. That means a state for Edit and a state for View. A state needs to be localized like this. Think of the Button control. The states in a button are defined in each Button not some shared location.

When you are ready to change the state of one of the items, you need to wire it to your code behind. In your code behind, you need to loop through the items in your ListView and call a method you create, something like MakeStateEdit() and MakeStateView(). It will be your implementation of those methods that sets the states of the user control. The outside code just trusts it to happen.

This means you need to call VisualStateManager.GoToState(this, "Edit", true); (or whatever state you create) inside your UserControl, in the code-behind. Conversely you might set the "View" state when the MakeStateView() is called.

To iterate a ListView Items property, you need to use a technique like this (http://blog.jerrynixon.com/2012/09/how-to-access-named-control-inside-xaml.html). You'll find that once you start down this path, it really isn't very complicated. You might be disappointed that you can't do all of this in XAML. You can't. But it can be done!

Best of luck!



回答2:

I don't know if visual state changes propagate, so maybe your solution should somehow work, but I would edit the visual states in the ListViewItem template instead (through ItemContainerStyle).