диспетчер визуального состояния списка в шаблоне элемента (WinRT, Metro, XAML)

Я пытаюсь получить список для отображения списка элементов, состоящих из текстовых блоков... когда щелкнут элемент списка, я хотел бы вместо этого показать список, состоящий из текстовых полей...

Ниже то, что я придумал, это не работает. У меня есть две сетки в шаблонах, и я надеялся просто показать и скрыть сетки в зависимости от того, выбран ли элемент списка. Где я ошибся?

Я вырвал эти визуальные состояния из самого шаблона списка, но я должен признать, что не уверен, как они работают или как они должны запускаться. Должен ли быть какой-то код для этого?

    <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>

Большое спасибо, Кохан


person 4imble    schedule 06.07.2012    source источник


Ответы (2)


Вы настраиваете анимацию раскадровки вне визуализируемых элементов. Цели, которые вы указываете, не только выходят за рамки внешней страницы, но и потенциально еще не существуют. В результате раскадровку нельзя настроить при отображении страницы.

Вот что вы хотите сделать.

Создайте пользовательский элемент управления, который будет представлять нужный вам макет в элементе ListView. Когда вы определяете ListView, не забудьте включить UserControl в DataTemplate, например:

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

Теперь о VisualStates. Вам нужно настроить состояния внутри файла UserControl. Это означает состояние для редактирования и состояние для просмотра. Состояние должно быть локализовано таким образом. Подумайте об элементе управления Button. Состояния кнопки определяются в каждом Button, а не в каком-то общем месте.

Когда вы будете готовы изменить состояние одного из элементов, вам нужно связать его с вашим кодом. В вашем коде вам нужно перебрать элементы в вашем ListView и вызвать созданный вами метод, что-то вроде MakeStateEdit() и MakeStateView(). Это будет ваша реализация тех методов, которые задают состояния пользовательского элемента управления. Внешний код просто верит, что это произойдет.

Это означает, что вам нужно вызвать VisualStateManager.GoToState(this, "Edit", true); (или любое другое состояние, которое вы создаете) внутри вашего UserControl в коде программной части. И наоборот, вы можете установить состояние «Просмотр» при вызове MakeStateView().

Для итерации свойства ListView Items необходимо использовать подобный метод (http://blog.jerrynixon.com/2012/09/how-to-access-named-control-inside-xaml.html). Вы обнаружите, что как только вы начнете идти по этому пути, это действительно не очень сложно. Вы можете быть разочарованы тем, что не можете сделать все это в XAML. Вы не можете. Но это может быть сделано!

Удачи!

person Jerry Nixon    schedule 08.05.2013

Я не знаю, распространяются ли изменения визуального состояния, поэтому, возможно, ваше решение должно каким-то образом работать, но вместо этого я бы отредактировал визуальные состояния в шаблоне ListViewItem (через ItemContainerStyle).

person Filip Skakun    schedule 06.07.2012
comment
Мне удалось заставить его работать, извлекая шаблон listviewitem в blend и используя состояния внутри него. но это кажется немного лишним. В настоящее время я изучаю использование ItemTemplateSelector, который, надеюсь, позволит мне динамически выбирать шаблон. - person 4imble; 09.07.2012
comment
Нет, селектор не позволит вам выбирать динамически, извините - person Jerry Nixon; 30.08.2012
comment
Не могли бы вы объяснить, как заставить его работать? Я редактирую ItemContainerStyle, где я могу найти VisualStates, а затем я ссылаюсь на сетку моего шаблона, например, в вашем примере «Редактирование», но я получил сообщение об ошибке, говорящее, что он не найден: \ - person Vando; 30.01.2013