【问题标题】:XAML ListView - Change Image Source for selected itemXAML ListView - 更改所选项目的图像源
【发布时间】:2013-01-27 20:17:04
【问题描述】:

我正在使用带有自定义模板的 ListView,如下所示:

<ListView.ItemTemplate>
    <DataTemplate>
        <Grid HorizontalAlignment="Center" Width="220" Height="220">
            <Image x:Name="image" Stretch="UniformToFill" 
                    Source="{Binding Brand.Image, 
                             ConverterParameter=transparent, 
                             Converter={StaticResource LogoToUriConverter}}"/>
            <StackPanel VerticalAlignment="Bottom">
                <TextBlock Text="{Binding Name}" 
                            Foreground="{StaticResource ApplicationColor}" 
                            Style="{StaticResource TitleTextStyle}" 
                            Height="30" Margin="15,0,15,0"/>
                <TextBlock Text="{Binding Name}" 
                            Foreground="{StaticResource ApplicationColor}" 
                            Style="{StaticResource CaptionTextStyle}" 
                            TextWrapping="NoWrap" Margin="15,0,15,10"/>
            </StackPanel>
        </Grid>
    </DataTemplate>
</ListView.ItemTemplate>

现在选择项目时,我希望将所选项目的图像源更改为新的图像。

Brand.Image 不是 DependencyProperty,因为它来自外部 DataObject。

所以,我认为在 WPF 中我可以使用触发器来手动更改它。

但由于在 winRT 中它不再起作用,我研究了 VSM,但我不知道如何才能做到这一点。

有人可以给我一个真实的例子吗?

谢谢

【问题讨论】:

    标签: xaml listview windows-8 windows-runtime


    【解决方案1】:

    我能够以一种棘手的方式解决这个问题,但我得到了它的工作:

    1. 使用 ExtendedVisualStateManager,(通过 ExpressionBlend dll 可用于 .NET,但不适用于 WinRT,所以我从这里得到它:http://nroute.codeplex.com/SourceControl/changeset/69480#nRoute5/nRoute.Framework.Metro/Components/ExtendedVisualStateManager.cs

    2. 我只是捕获了一个 OnSelected 事件并使用新的 VisualStateManager 来执行此操作:

      ExtendedVisualStateManager.GoToElementState(sender as Grid, "Selected2", true);

    这是 ItemTemplate 的完整 XAML:

    <DataTemplate>
    <Grid x:Name="ItemGrid" HorizontalAlignment="Center" Width="220" Height="220" PointerPressed="GridItemTapped">
        <Image x:Name="image" Stretch="UniformToFill" Source="{Binding Brand.Name, ConverterParameter=white, Converter={StaticResource LogoToUriConverter}}"/>
        <Image x:Name="image_colored" Stretch="UniformToFill" Visibility="Collapsed" Source="{Binding Brand.Name, ConverterParameter=colored, Converter={StaticResource LogoToUriConverter}}"/>
        <StackPanel VerticalAlignment="Bottom">
            <TextBlock Text="{Binding Name}" Foreground="White" Style="{StaticResource TitleTextStyle}" Height="30" Margin="15,0,15,0"/>
            <TextBlock Text="{Binding Name}" Foreground="White" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
        </StackPanel>
        <VisualStateManager.CustomVisualStateManager>
            <vsm:ExtendedVisualStateManager/>
        </VisualStateManager.CustomVisualStateManager>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="SelectionStates">
                <VisualState x:Name="Selected2">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="image" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="00:00:00.0000000">
                                <DiscreteObjectKeyFrame.Value>
                                    Collapsed
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="image_colored" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="00:00:00.0000000">
                                <DiscreteObjectKeyFrame.Value>
                                    Visible
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
    

    希望这可以帮助任何有同样问题的人。

    如果您有更好、更简单的方法在 WinRT 中实现相同的结果,请提出您的解决方案。

    谢谢

    【讨论】:

    • 你指的 OnSelected 事件是什么?
    【解决方案2】:

    您可以为您的 ListViewItem 创建一个样式,其中包含用于触发器的控件模板和用于数据绑定的数据模板,如下所示:

       <Style x:Key="FocusedContainer" TargetType="{x:Type ListViewItem}">
            <EventSetter Event="GotKeyboardFocus" Handler="OnListBoxItemContainerFocused" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListViewItem}">
                        <Border x:Name="backgroundBorder">
                            <ContentPresenter Content="{TemplateBinding Content}">
                                <ContentPresenter.ContentTemplate>
                                    <DataTemplate>
                                         <Grid HorizontalAlignment="Center" Width="220" Height="220">
                                    <Image x:Name="image" Stretch="UniformToFill" Source="{Binding Brand.Image, ConverterParameter=transparent, Converter={StaticResource LogoToUriConverter}}"/>
                                    <StackPanel VerticalAlignment="Bottom">
                                        <TextBlock Text="{Binding Name}" Foreground="{StaticResource ApplicationColor}" Style="{StaticResource TitleTextStyle}" Height="30" Margin="15,0,15,0"/>
                                        <TextBlock Text="{Binding Name}" Foreground="{StaticResource ApplicationColor}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
                                    </StackPanel>
                                </Grid>
                                    </DataTemplate>
                                </ContentPresenter.ContentTemplate>
                            </ContentPresenter>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="True">
                                <Setter TargetName="image" Property="Source" Value="{**Insert your alternate binding here**}"
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    然后像这样配置您的 ListView:

    <ListView ItemContainerStyle="{StaticResource FocusedContainer}"/>
    

    您会看到该样式有一个 EventSetter:它的目的是即使您在某个控件内单击(而不是直接在背景上),也可以选择正确的项目。您需要在后面的代码中创建处理程序,只需几行:

        private void OnListBoxItemContainerFocused(object sender, System.Windows.RoutedEventArgs e)
        { (sender as ListViewItem).IsSelected = true; }
    

    希望这有帮助,问候!

    【讨论】:

    • 感谢您的回答,但我认为 WPF 确实如此,但 WinRT 触发器不再起作用:\ 还有其他建议吗?谢谢!
    • 我没有 WinRT 方面的经验,但如果 Visual State Manager 仍在工作,您可以尝试这种方式。当他们停止支持这些事情时,这很烦人......
    • 如何使用 Visual State Manager 实现相同的结果?
    • 我真的没有这方面的经验,我总是设法使用触发器完成所有工作。也许您可以编辑您的问题并指定您需要 VSM 解决方案。一些研究也不会伤害你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-03
    • 2015-01-07
    • 2018-09-01
    • 2011-10-03
    • 1970-01-01
    相关资源
    最近更新 更多