Я хочу отобразить 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>
Проблемы с этим решением:
Для каждого нового ListBoxItem, который должен использовать разные DataTemplates, мне нужно создать стиль с ControlTemplate, который такой же, как и выше, но просто нужно изменить ContentTemplate ContentPresenter.Таким образом, много повторяющегося кода / XAML.
Поскольку я использую кнопку в SelectedItemTemplate, мне нужно определить стили в том же классе UserControl, где определен обработчик события Click,Если UserControl использует более одного ListBox, то для каждого ListBoxes будет объявлено огромное определение стиля.
Я пытался решить эту проблему с помощью прикрепленных свойств, но он не работает.Как, я не могу получить Selected ListBoxItem (вместо этого я получаю связанные данные).Идея состояла в том, чтобы завладеть ListBoxItem, получить его ContentPresenter и установить для его ContentTemplate значение SelectedItemTemplate.
Есть ли лучший способ сделать это?
Спасибо и С уважением, Sunil