Другой шаблон элемента для выбранных и обычных элементов в элементе списка - PullRequest
0 голосов
/ 15 октября 2011

Я хочу отобразить ListBox, элемент которого при выборе будет отображать кнопку, которая выполняет определенное действие с выбранным элементом данных.Для этого я использую два DataTemplates, один из которых NormalTemplate (у которого нет кнопки), а другой - SelectedTemplate (у которого есть кнопка, свойство Tag которой связано с данными, которая используется вобработчик события нажатия кнопки).Когда элемент в Listbox выбран, я хочу назначить SelectedTemplate.

Для этого я использовал пользовательский ControlTemplate, который имеет VisualStateManager, который выбирает соответствующий шаблон на основе VisualState (т. Е. Selected & Unselected).Проблема этого решения заключается в том, что мне приходится создавать новый ControlTemplate каждый раз, когда мне нужно использовать разные DataTemplate.Я пытаюсь найти решение, в котором вы указываете шаблоны для обычных и выбранных элементов и используете общий код для изменения таблицы данных на основе визуального состояния.

Ниже приведен мой шаблон данных для невыбранных и выбранных элементов:

<DataTemplate x:Key="NormalItemTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"    />
            </Grid.ColumnDefinitions>

            <StackPanel Grid.Column="1" Margin="8,0,0,3" VerticalAlignment="Center">
                <TextBlock Text="{Binding Name}" FontWeight="Bold" FontFamily="Arial" FontSize="14"/>
                <TextBlock Text="{Binding Description}" />
            </StackPanel>
        </Grid>
    </Border>
</DataTemplate>

<DataTemplate x:Key="SelectedItemTemplate">
    <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"    />
                <ColumnDefinition Width="65"/>
            </Grid.ColumnDefinitions>

            <StackPanel Grid.Column="1" Margin="8,0,0,3">
                <TextBlock Text="{Binding Name}" FontWeight="Bold" FontFamily="Arial" FontSize="14"/>
                <TextBlock Text="{Binding Description}" />
            </StackPanel>

            <Border Grid.Column="2" Grid.RowSpan="2" VerticalAlignment="Stretch">
                <Button Content="Process" Tag={Binding} OnClick="Process_Clicked" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Border>
        </Grid>
    </Border>
</DataTemplate>

Ниже приведен стиль, определяющий пользовательский ControlTemplate, который использует VisualStateManager для отображения или скрытия соответствующих ContentPresenters, ContentTemplate которого назначен NormalItemTemplate & SelectedItemTemplate

<Style TargetType="ListBoxItem" x:Key="ActiveGamesItemContainerStyle">
    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <Grid Background="{TemplateBinding Background}">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" />
                        </VisualStateGroup>

                        <VisualStateGroup x:Name="SelectionStates">
                            <VisualState x:Name="Unselected">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="SelectedContentPresenter" Storyboard.TargetProperty="Visibility">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Collapsed</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="UnSelectedContentPresenter" Storyboard.TargetProperty="Visibility">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>

                            <VisualState x:Name="Selected">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="SelectedContentPresenter" Storyboard.TargetProperty="Visibility">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="UnSelectedContentPresenter" Storyboard.TargetProperty="Visibility">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Collapsed</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>

                    <ContentPresenter
                                x:Name="SelectedContentPresenter"
                                Content="{TemplateBinding Content}"
                                ContentTemplate="{StaticResource NormalItemTemplate}"
                                HorizontalAlignment="Stretch"
                                Margin="{TemplateBinding Padding}"
                                Visibility="Collapsed"/>

                    <ContentPresenter
                                x:Name="UnSelectedContentPresenter"
                                Content="{TemplateBinding Content}"
                                ContentTemplate="{StaticResource SelectedItemTemplate}"
                                HorizontalAlignment="Stretch"
                                Margin="{TemplateBinding Padding}"
                                Visibility="Visible"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Проблемы с этим решением:

  1. Для каждого нового ListBoxItem, который должен использовать разные DataTemplates, мне нужно создать стиль с ControlTemplate, который такой же, как и выше, но просто нужно изменить ContentTemplate ContentPresenter.Таким образом, много повторяющегося кода / XAML.

  2. Поскольку я использую кнопку в SelectedItemTemplate, мне нужно определить стили в том же классе UserControl, где определен обработчик события Click,Если UserControl использует более одного ListBox, то для каждого ListBoxes будет объявлено огромное определение стиля.

Я пытался решить эту проблему с помощью прикрепленных свойств, но он не работает.Как, я не могу получить Selected ListBoxItem (вместо этого я получаю связанные данные).Идея состояла в том, чтобы завладеть ListBoxItem, получить его ContentPresenter и установить для его ContentTemplate значение SelectedItemTemplate.

Есть ли лучший способ сделать это?

Спасибо и С уважением, Sunil

1 Ответ

1 голос
/ 15 октября 2011

Нет необходимости в двух отдельных шаблонах, просто используйте один и переключите видимость с помощью DataTrigger.

  1. Создайте модель представления вашего элемента, которая имеет свойство IsSelected,Добавьте события NotifyPropertyChanged.

  2. Установите ItemContainerStyle, чтобы привязать свойство ListBoxItem.IsSelected к свойству IsSelected в вашей модели представления.

  3. Тогда в вашем DataTemplate есть DataTrigger, который изменяет Visibility кнопки, когда IsSelected равен True.

В качестве примера вышеописанного взгляните на ответ на этот вопрос StackOverflow.

...