Domanda

Ho un UserControl con un Grid che è iscritto a a Holding evento.Il problema è che il Holding l'evento si attiva per l'oggetto che ho preso di mira e per alcuni altri elementi nel file ListView.A proposito, sto utilizzando il controllo come DataTemplate.

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

Controllo utente code-behind:

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

Contenuti del controllo utente:

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

Non sono riuscito a utilizzare gli storyboard sugli elementi contenuti in un DataTemplate, quindi questo mi ha costretto a spostarne il contenuto in un UserControl.

Questo problema ha a che fare con la virtualizzazione?Come posso risolvere questo problema?

Le alternative basteranno.

AGGIORNAMENTO:

Alcuni post di SO suggerivano che la modalità di riciclaggio comportasse il riutilizzo degli articoli.ho aggiuntoVirtualizingStackPanel.VirtualizationMode="Standard" al mio ListView ma il problema sorprendentemente persiste.

Quindi ora devo trovare un modo per impedire ad altri elementi di ripetere lo stesso valore di opacità (che non è associato a dati perché è impostato tramite uno storyboard).

AGGIORNAMENTO 2:

Ora la descrizione che appare quando si tiene premuto l'elemento visualizzato scompare completamente quando scompare dalla vista:

<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <VirtualizingStackPanel/>
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
È stato utile?

Soluzione

Mi piace come stai cercando di comportarti qui.Per i dispositivi touch screen, non abbiamo MouseOver evento, quindi questo è uno dei modi in cui vuoi mostrare alcune informazioni extra senza rovinare l'interfaccia utente.

Tuttavia, una soluzione molto più pulita sarebbe quella di creare un file riutilizzabile Behavior che incapsula tutta la logica e le animazioni dell'interfaccia utente.

Per fare ciò, dovrai prima includere il riferimento Behaviors SDK (XAML).

IL Behavior l'implementazione è semplice.IL AssociatedObject sarebbe il Grid che riceve gli eventi touch e quindi è necessario creare un file DependencyProperty TextBlockName per recuperare la descrizione TextBlock esempio.Una volta ottenuta l'istanza, è sufficiente scriverne le animazioni in 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;
    }
}

Questo Behavior può quindi essere allegato al tuo DataTemplateè il livello più alto Grid.Tieni presente che non è necessario un file UserControl per avvolgerlo più.

Inoltre, assicurati di avere un colore di sfondo per il file Grid in modo che possa ricevere eventi touch.L'ultima cosa che ho fatto è stata cambiare il file ListView'S ItemContainerStyle'S HorizontalContentAlignment A Stretch così il Grid si allunga completamente a destra.

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

Altri suggerimenti

Ho trovato una soluzione alternativa; Ho aggiunto una proprietà chiamata DescriptionLayerOpacity al mio modello e impostalo su un valore predefinito di 0 quando aggiungo un nuovo oggetto al mio ObservableCollection nel mio ViewModel.

Ho anche aggiunto vincolante a 2 vie per modificare la proprietà di origine (DescriptionLayerOpacity) in modo che la vista venga aggiornata con le modifiche apportate dagli storyboard:

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

In breve, tutti i dati di UserControl dovevano essere il databorn per evitare di essere ripetuti negli altri elementi nella Vista.

Questa non è una soluzione elegante e non è stata completamente testata. Fino a quando trovo una soluzione reale, questo sarà sufficiente.

Aggiornamento: non funzionante completamente

Ho scoperto di recente che alcuni articoli non rispondono quando sono selezionati altri elementi. Per ottenere quegli articoli per rispondere, devo toccare prima dell'evento TAP + HOLD (entrambi sono eventi reciprocamente esclusivi, a proposito).

Aggiornamento 2:

Tutto sembra funzionare bene dopo aver rimosso le dichiarazioni if nel codice. Ma vincolante per una proprietà di opacità nel modello per farlo funzionare è ancora una soluzione puzzolente.

Dai un'occhiata alla soluzione qui: http://social.msdn.microsoft.com/forums/windowapps/en-us/95f49050-368e-4ddb-962e-6be62e7e3d57/Context-Menus-in-ListView-Windows-Phone-81? Forum= WpDevelop

Non sono sicuro che questo sia esattamente il tuo problema, ma suona come il UserControl non riceve l'evento di attesa perché è assorbito dal ListView? La soluzione sopra descritta deve essere necessaria per avvolgere il DataTemplates Grid in un ListViewItem e allegando un evento di attesa a quello.Forse questo aiuterà?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top