在ListView中触发事件触发未触摸的项目

pcn*_*ird 5 c# xaml windows-phone windows-phone-8.1

我有UserControl一个Grid被订阅的Holding事件.问题是该Holding事件触发了我所定位的项目以及该项目中的其他一些项目ListView.顺便说一下,我正在使用控件作为DataTemplate.

<ListView ItemsSource="{Binding ...}" Margin="0, 0, 0, 0">
    ...
    <ListView.ItemTemplate>
        <DataTemplate>
            <local:MyUserControl/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
Run Code Online (Sandbox Code Playgroud)

用户控制代码隐藏:

    private bool isDescriptionVisible = false;

    private void Grid_Holding(object sender, HoldingRoutedEventArgs e)
    {
        if (!isDescriptionVisible)
        {
            DescriptionFadeIn.Begin();
            isDescriptionVisible = true;
        }
    }

    private void Grid_Tapped(object sender, TappedRoutedEventArgs e)
    {
        if (isDescriptionVisible)
        {
            DescriptionFadeOut.Begin();
            isDescriptionVisible = false;
        }
    }
Run Code Online (Sandbox Code Playgroud)

用户控制内容:

<Grid.Resources>
    <Storyboard x:Name="FadeIn">
            <DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DescriptionLayer"
                             Duration="0:0:0.3" To=".8"/>
        </Storyboard>

        <Storyboard x:Name="FadeOut">
            <DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DescriptionLayer"
                             Duration="0:0:0.3" To="0"/>
        </Storyboard>
</Grid.Resources>

<Grid Margin="0, 0, 0, 48" Holding="Grid_Holding" Tapped="Grid_Tapped">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="1*"/>
    </Grid.RowDefinitions>
    <Image Source="{Binding Img}" Stretch="UniformToFill" Height="240" Width="450"/>
    <Grid x:Name="DescriptionLayer" Background="Black" Opacity="0">
        <TextBlock Text="{Binding Description}" FontSize="16" TextWrapping="Wrap" Margin="0, 9, 0, 0" MaxHeight="170" TextTrimming="CharacterEllipsis"/>
    </Grid>
    <StackPanel Grid.Row="1" Margin="12">
        <TextBlock Text="{Binding Author}" FontSize="16"/>
        <TextBlock Text="{Binding Title}" FontSize="18"/>
    </StackPanel>
</Grid>
Run Code Online (Sandbox Code Playgroud)

我无法在DataTemplate中包含的项目上使用故事板,因此强制我使用将其内容移动到UserControl.

这个问题与虚拟化有关吗?我怎样才能解决这个问题?

替代方案会做.

更新:

一些SO帖子表明回收模式导致物品被重复使用.我已添加 VirtualizingStackPanel.VirtualizationMode="Standard"到我的ListView,但问题出乎意料地持续存在.

所以现在我需要找出一种方法来防止其他项重复相同的不透明度值(这不是数据绑定,因为它是通过故事板设置的).

更新2:

现在,当显示项目退出视图时,保持显示项目完全消失的描述:

<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <VirtualizingStackPanel/>
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
Run Code Online (Sandbox Code Playgroud)

Jus*_* XL 1

我喜欢你在这里尝试做的事情。对于触摸屏设备,我们没有MouseOver事件,因此当您想要显示一些额外信息而不弄乱 UI 时,这是方法之一。

然而,一个更简洁的解决方案是创建一个可重用的Behavior封装所有 UI 逻辑和动画的解决方案。

为此,您首先需要包含引用Behaviors SDK (XAML)

实施过程Behavior非常简单。这AssociatedObject将是Grid接收触摸事件的实例,然后您需要创建一个DependencyProperty TextBlockName来检索描述TextBlock实例。获得实例后,您只需用 C# 为其编写动画即可。

public class ShowHideDescriptionBehavior : DependencyObject, IBehavior
{
    public string TextBlockName
    {
        get { return (string)GetValue(TextBlockNameProperty); }
        set { SetValue(TextBlockNameProperty, value); }
    }

    // Using a DependencyProperty as the backing store for TextBlockName.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TextBlockNameProperty =
        DependencyProperty.Register("TextBlockName", typeof(string), typeof(ShowHideDescriptionBehavior), new PropertyMetadata(string.Empty));

    public DependencyObject AssociatedObject { get; set; }

    public void Attach(DependencyObject associatedObject)
    {
        this.AssociatedObject = associatedObject;
        var panel = (Panel)this.AssociatedObject;

        panel.Holding += AssociatedObject_Holding;
        panel.Tapped += AssociatedObject_Tapped;
    }

    private void AssociatedObject_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
    {
        var animation = new DoubleAnimation
        {
            Duration = TimeSpan.FromMilliseconds(300),
            To = 0
        };
        Storyboard.SetTarget(animation, this.DescriptionTextBlock);
        Storyboard.SetTargetProperty(animation, "Opacity");

        var storyboard = new Storyboard();
        storyboard.Children.Add(animation);
        storyboard.Begin();
    }

    private void AssociatedObject_Holding(object sender, Windows.UI.Xaml.Input.HoldingRoutedEventArgs e)
    {
        var animation = new DoubleAnimation
        {
            Duration = TimeSpan.FromMilliseconds(300),
            To = 0.8
        };
        Storyboard.SetTarget(animation, this.DescriptionTextBlock);
        Storyboard.SetTargetProperty(animation, "Opacity");

        var storyboard = new Storyboard();
        storyboard.Children.Add(animation);
        storyboard.Begin();
    }

    private TextBlock _descriptionTextBlock;
    private TextBlock DescriptionTextBlock
    {
        get
        {
            if (_descriptionTextBlock == null)
            {
                var panel = (Panel)this.AssociatedObject;
                // todo: add validation
                _descriptionTextBlock = (TextBlock)panel.FindName(this.TextBlockName);
            }

            return _descriptionTextBlock;
        }
    }

    public void Detach()
    {
        var panel = (Panel)this.AssociatedObject;

        panel.Holding -= AssociatedObject_Holding;
        panel.Tapped -= AssociatedObject_Tapped;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后可以将其Behavior附加到您的DataTemplate顶层Grid。请注意,您不再需要 aUserControl来包装它。

另外,请确保您有背景颜色,以便Grid它可以接收触摸事件。我做的最后一件事是将ListView'ItemContainerStyle更改HorizontalContentAlignmentStretch,这样 'Grid就一直延伸到右侧。

<Page.Resources>
    <DataTemplate x:Key="GroupTemplate">
        <Grid Background="Transparent" Margin="12">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Interactivity:Interaction.Behaviors>
                <local:ShowHideDescriptionBehavior TextBlockName="Description" />
            </Interactivity:Interaction.Behaviors>
            <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
                <Image Source="{Binding Img}" Height="110" Width="110"/>
            </Border>
            <StackPanel Grid.Column="1" Margin="10,0,0,0">
                <TextBlock Text="{Binding Author}" Style="{StaticResource TitleTextBlockStyle}"/>
                <TextBlock x:Name="Description" Opacity="0" Text="{Binding Description}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
            </StackPanel>
        </Grid>
    </DataTemplate>
</Page.Resources>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" DataContext="{Binding Source={StaticResource SampleDataSource}}">
    <ListView ItemTemplate="{StaticResource GroupTemplate}" ItemsSource="{Binding Groups}">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>
</Grid>
Run Code Online (Sandbox Code Playgroud)