列表框项中选定项和普通项的不同项模板

时间:2011-10-15 08:32:30

标签: c#-4.0 silverlight-4.0

我想显示一个ListBox,其选中的项目将显示一个按钮,该按钮对所选数据项执行特定操作。为此,我使用两个DataTemplates,一个是 NormalTemplate (没有按钮),另一个是 SelectedTemplate (它有一个按钮,其Tag属性绑定到数据,这是用于按钮单击事件处理程序)。当选择列表框中的项目时,我想分配SelectedTemplate。

为此,我使用自定义ControlTemplate,它具有VisualStateManager,它根据VisualState选择适当的模板(即,Selected和ampselected)。这个解决方案的问题是我每次需要使用不同的DataTemplates时都要创建新的ControlTemplate。我正在尝试找到一个解决方案,您可以在其中指定普通模板和模板。选择项目并使用通用代码根据visualstate更改datatemplate。

以下是我的DataTemplate for Unselected&选定项目:

<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来显示或隐藏其ContentTemplate被分配给NormalItemTemplate&amp;的适当ContentPresenters。 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. 对于需要使用不同DataTemplates的每个新ListBoxItem,我需要使用ControlTemplate创建一个与上面相同的样式,但只需要更改ContentPresenter的ContentTemplate。因此,很多重复的代码/ XAML。

  2. 因为我正在使用SelectedItemTemplate中的按钮,所以我需要在同一个UserControl类中定义样式,其中定义了Click事件处理程序。如果UserControl使用多个ListBox,则会为每个ListBox声明一个巨大的Style定义。

  3. 我尝试使用附加属性解决此问题,但它无法正常工作。因为,我无法获得Selected ListBoxItem(相反,我得到了绑定数据)。我们的想法是获取ListBoxItem获取其ContentPresenter并将其ContentTemplate设置为SelectedItemTemplate。

    有没有更好的方法呢?

    谢谢&amp;问候, 苏尼

1 个答案:

答案 0 :(得分:1)

无需使用两个单独的模板,只需使用一个模板并使用DataTrigger切换可见性。

  1. 创建具有IsSelected属性的项目的视图模型。添加NotifyPropertyChanged事件。

  2. 设置ItemContainerStyle以将ListBoxItem.IsSelected属性绑定到您的viewmodel上的IsSelected属性。

  3. 然后在DataTemplateDataTrigger VisibilityIsSelected True {{1}}时会更改{{1}}。

  4. 有关如何执行上述操作的示例,请查看answer to this StackOverflow question.