选择项目时,UWP ListView 修改数据模板中的控件

UWP ListView modifycontrols in datatemplate when item is selected

我有 ListView,它的 DataTemplate ItemTemplate 看起来像这样>

<DataTemplate>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="4"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Rectangle Fill="Black"/>
        <TextBlock Text="{Binding Title}"/>
    </Grid>
</DataTemplate>

当 ListView 中的项目被选中时,我希望 Rectangle 的 Fill 值为 Whilte。

对于 WPF,我可以使用触发器,但在 UWP 上,我发现没有任何触发器。

我不想用C#监听ListView的ItemSelected事件,然后把所有item的颜色都改成黑色,再把SelectedItem的颜色设置成白色,因为ListView里的item太多了

最简单的方法是自定义 ListView.ItemContainerStyle。 你会发现很多有用的细节 here.

想法是为列表项创建自定义布局。布局将在左侧包含您的黑色矩形,在右侧包含您的模板(文本框)。

基本上,listview 声明变为(为清楚起见,删除了一些代码):

<ListView x:Name="list" SelectionMode="Single">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:Data">
                <TextBlock Text="{x:Bind Title}" />
            </DataTemplate>
        </ListView.ItemTemplate>

        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalAlignment" Value="Stretch" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListViewItem">
                             <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="8" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>

                                <Rectangle x:Name="sideRect" Fill="Black" />

                                <Grid
                                    x:Name="ContentPresenterGrid"
                                    Margin="0,0,0,0"
                                    Background="Transparent"
                                    Grid.Column="1">
                                    <Grid.RenderTransform>
                                        <TranslateTransform x:Name="ContentPresenterTranslateTransform" />
                                    </Grid.RenderTransform>
                                    <ContentPresenter
                                        x:Name="ContentPresenter"
                                        Margin="{TemplateBinding Padding}"
                                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                        Content="{TemplateBinding Content}"
                                        ContentTemplate="{TemplateBinding ContentTemplate}"
                                        ContentTransitions="{TemplateBinding ContentTransitions}" />
                                </Grid>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>

然后您必须更新视觉状态以将矩形颜色设置为您想要的每种状态的颜色,例如:(为清楚起见,我删除了一些动画)

<VisualState x:Name="Selected">
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="sideRect" Storyboard.TargetProperty="Fill">
            <DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualState>

完整代码:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ListView x:Name="list" SelectionMode="Single">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:Data">
                <TextBlock Text="{x:Bind Title}" />
            </DataTemplate>
        </ListView.ItemTemplate>

        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalAlignment" Value="Stretch" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListViewItem">
                            <Grid
                                x:Name="ContentBorder"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">

                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="CommonStates">
                                        <VisualState x:Name="Normal">
                                            <Storyboard>
                                                <PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="PointerOver">
                                            <Storyboard>

                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Pressed">
                                            <Storyboard>

                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <PointerDownThemeAnimation TargetName="ContentPresenter" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Selected">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
                                                </ObjectAnimationUsingKeyFrames>

                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="sideRect" Storyboard.TargetProperty="Fill">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
                                                </ObjectAnimationUsingKeyFrames>

                                                <PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="PointerOverSelected">
                                            <Storyboard>


                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
                                                </ObjectAnimationUsingKeyFrames>

                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="sideRect" Storyboard.TargetProperty="Fill">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="Green" />
                                                </ObjectAnimationUsingKeyFrames>

                                                <PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="PressedSelected">
                                            <Storyboard>



                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
                                                </ObjectAnimationUsingKeyFrames>

                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="sideRect" Storyboard.TargetProperty="Fill">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="Yellow" />
                                                </ObjectAnimationUsingKeyFrames>


                                                <PointerDownThemeAnimation TargetName="ContentPresenter" />
                                            </Storyboard>
                                        </VisualState>
                                    </VisualStateGroup>
                                    <VisualStateGroup x:Name="DisabledStates">
                                        <VisualState x:Name="Enabled" />
                                        <VisualState x:Name="Disabled">
                                            <Storyboard>
                                                <DoubleAnimation
                                                    Storyboard.TargetName="ContentBorder"
                                                    Storyboard.TargetProperty="Opacity"
                                                    To="{ThemeResource ListViewItemDisabledThemeOpacity}"
                                                    Duration="0" />
                                            </Storyboard>
                                        </VisualState>
                                    </VisualStateGroup>
                                    <VisualStateGroup x:Name="MultiSelectStates">
                                        <VisualState x:Name="MultiSelectDisabled">
                                            <Storyboard>


                                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenterTranslateTransform" Storyboard.TargetProperty="X">
                                                    <EasingDoubleKeyFrame KeyTime="0:0:0" Value="32" />
                                                    <SplineDoubleKeyFrame
                                                        KeySpline="0.1,0.9,0.2,1"
                                                        KeyTime="0:0:0.333"
                                                        Value="0" />
                                                </DoubleAnimationUsingKeyFrames>

                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="MultiSelectEnabled">
                                            <Storyboard>


                                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenterTranslateTransform" Storyboard.TargetProperty="X">
                                                    <EasingDoubleKeyFrame KeyTime="0:0:0" Value="-32" />
                                                    <SplineDoubleKeyFrame
                                                        KeySpline="0.1,0.9,0.2,1"
                                                        KeyTime="0:0:0.333"
                                                        Value="0" />
                                                </DoubleAnimationUsingKeyFrames>


                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenterGrid" Storyboard.TargetProperty="Margin">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="32,0,0,0" />
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                    </VisualStateGroup>
                                </VisualStateManager.VisualStateGroups>

                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="8" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>

                                <Rectangle x:Name="sideRect" Fill="Black" />


                                <Grid
                                    x:Name="ContentPresenterGrid"
                                    Margin="0,0,0,0"
                                    Background="Transparent"
                                    Grid.Column="1">
                                    <Grid.RenderTransform>
                                        <TranslateTransform x:Name="ContentPresenterTranslateTransform" />
                                    </Grid.RenderTransform>
                                    <ContentPresenter
                                        x:Name="ContentPresenter"
                                        Margin="{TemplateBinding Padding}"
                                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                        Content="{TemplateBinding Content}"
                                        ContentTemplate="{TemplateBinding ContentTemplate}"
                                        ContentTransitions="{TemplateBinding ContentTransitions}" />
                                </Grid>
                            </Grid>
                        </ControlTemplate>

                    </Setter.Value>
                </Setter>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>
</Grid>

有一种非常简单的方法可以解决 UWP 应用程序的这个问题。 如您所知,UWP 应用程序不支持像 WPF 应用程序这样的触发器。 总是当我遇到这种情况时,我更喜欢使用行为。

您可以在选择项目时使用自定义行为进行监听,并更改模型中某些 属性 的颜色值。

示例:

<Rectangle Fill="{Binding MyColor,Mode=TwoWay}"/>

在您的行为的事件处理程序中,只需更改 属性(MyColor) 的颜色即可。