Frage

Ich habe ein UserControl mit einem Grid das abonniert ist Holding Ereignis.Das Problem ist, dass die Holding Das Ereignis wird für den Gegenstand ausgelöst, den ich anvisiert habe, sowie für einige andere Gegenstände im ListView.Ich verwende das Steuerelement übrigens als DataTemplate.

<ListView ItemsSource="{Binding ...}" Margin="0, 0, 0, 0">
    ...
    <ListView.ItemTemplate>
        <DataTemplate>
            <local:MyUserControl/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Code-Behind für die Benutzersteuerung:

    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;
        }
    }

Inhalte der Benutzerkontrolle:

<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>

Ich konnte Storyboards nicht für Elemente verwenden, die in einem DataTemplate enthalten waren, sodass ich gezwungen war, den Inhalt in ein UserControl zu verschieben.

Hat dieses Problem mit der Virtualisierung zu tun?Wie kann ich das beheben?

Alternativen reichen aus.

AKTUALISIEREN:

Einige SO-Beiträge deuteten darauf hin, dass der Recyclingmodus dazu führte, dass Gegenstände wiederverwendet wurden.Ich habe hinzugefügtVirtualizingStackPanel.VirtualizationMode="Standard" zu meiner ListView, aber das Problem bleibt überraschenderweise weiterhin bestehen.

Jetzt muss ich also einen Weg finden, um zu verhindern, dass andere Elemente denselben Deckkraftwert wiederholen (der nicht datengebunden ist, da er über ein Storyboard festgelegt wird).

UPDATE 2:

Jetzt verschwindet die Beschreibung, die beim Halten des angezeigten Elements eingeblendet wird, vollständig, wenn es nicht mehr sichtbar ist:

<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <VirtualizingStackPanel/>
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
War es hilfreich?

Lösung

Mir gefällt, wie Sie es hier versuchen.Für Touchscreen-Geräte haben wir keine MouseOver Ereignis, daher ist dies eine der Möglichkeiten, wenn Sie zusätzliche Informationen anzeigen möchten, ohne die Benutzeroberfläche durcheinander zu bringen.

Eine viel sauberere Lösung wäre jedoch die Schaffung eines wiederverwendbaren Produkts Behavior das die gesamte UI-Logik und Animationen kapselt.

Dazu müssen Sie zunächst die Referenz angeben Behaviors SDK (XAML).

Der Behavior Die Umsetzung ist unkompliziert.Der AssociatedObject wäre das Grid das die Berührungsereignisse empfängt, und dann müssen Sie ein erstellen DependencyProperty TextBlockName um die Beschreibung abzurufen TextBlock Beispiel.Sobald Sie die Instanz haben, müssen Sie nur noch die Animationen dafür in C# schreiben.

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;
    }
}

Das Behavior kann dann an Ihr angeschlossen werden DataTemplate's höchstes Niveau Grid.Beachten Sie, dass Sie keine benötigen UserControl um es noch mehr einzupacken.

Stellen Sie außerdem sicher, dass Sie eine Hintergrundfarbe für haben Grid sodass es Berührungsereignisse empfangen kann.Das Letzte, was ich getan habe, war, das zu ändern ListView'S ItemContainerStyle'S HorizontalContentAlignment Zu Stretch also die Grid wird ganz nach rechts gestreckt.

<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>

Andere Tipps

Ich habe eine Problemumgehung gefunden;Ich habe eine Eigenschaft namens hinzugefügt DescriptionLayerOpacity zu meinem Modell und setze es auf einen Standardwert von 0 wenn ich einen neuen Artikel zu meinem hinzufüge ObservableCollection in meinem Ansichtsmodell.

Ich habe auch eine bidirektionale Bindung hinzugefügt, um die Quelleigenschaft zu ändern (DescriptionLayerOpacity), damit die Ansicht mit den von den Storyboards vorgenommenen Änderungen aktualisiert wird:

<Grid ... Opacity="{Binding DescriptionLayerOpacity, Mode=TwoWay}">
    <TextBlock .../>
</Grid>

Kurz gesagt: Alle Daten des UserControl mussten datengebunden sein, um eine Wiederholung in den anderen Elementen in der ListView zu vermeiden.

Dies ist wirklich keine elegante Lösung und wurde noch nicht vollständig getestet.Bis ich eine echte Lösung finde, wird das ausreichen.

Aktualisieren:Funktioniert nicht vollständig

Ich habe kürzlich festgestellt, dass einige Elemente nicht reagieren, wenn andere Elemente ausgewählt werden.Damit diese Elemente reagieren, muss ich vor dem Tippen+Halten-Ereignis tippen (übrigens sind beides Ereignisse, die sich gegenseitig ausschließen).

Update 2:

Nach dem Entfernen scheint alles gut zu funktionieren if Anweisungen im CodeBehind.Aber die Bindung an eine Opazitätseigenschaft im Modell, damit es funktioniert, ist immer noch eine stinkende Lösung.

Schauen Sie sich hier die Lösung an: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/95f49050-368e-4ddb-962e-6be62e7e3d57/context-menus-in-listview-windows-phone-81?forum=wpdevelop

Ich bin mir nicht sicher, ob das genau Ihr Problem ist, aber es hört sich so an UserControl empfängt das Hold-Ereignis nicht, da es von der absorbiert wird ListView?Die obige Lösung beschreibt die Notwendigkeit, das zu verpacken DataTemplates Grid in einem ListViewItem, und ein Hold-Ereignis daran anhängen.Vielleicht hilft das?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top