سؤال

انا املك UserControl مع Grid الذي تم الاشتراك فيه Holding حدث.المشكلة هي أن Holding يتم تشغيل الحدث للعنصر الذي استهدفته بالإضافة إلى بعض العناصر الأخرى في ListView.أنا أستخدم عنصر التحكم باعتباره DataTemplate، بالمناسبة.

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

كود تحكم المستخدم خلف:

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

محتويات تحكم المستخدم:

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

لم أتمكن من استخدام القصص المصورة على العناصر الموجودة في DataTemplate، لذلك أجبرني ذلك على استخدام نقل محتوياتها إلى UserControl.

هل هذه المشكلة لها علاقة بالمحاكاة الافتراضية؟كيف يمكنني اصلاح هذا؟

البدائل سوف تفعل.

تحديث:

اقترحت بعض منشورات SO أن وضع إعادة التدوير تسبب في إعادة استخدام العناصر.لقد اضفتVirtualizingStackPanel.VirtualizationMode="Standard" إلى ListView الخاص بي ولكن المشكلة لا تزال قائمة بشكل مدهش.

لذا فأنا الآن بحاجة إلى اكتشاف طريقة لمنع العناصر الأخرى من تكرار نفس قيمة العتامة (والتي ليست مرتبطة بالبيانات لأنه تم تعيينها عبر لوحة العمل).

تحديث 2:

الآن يختفي الوصف الذي يتلاشى عند الضغط على العنصر المعروض تمامًا عندما يصبح خارج نطاق العرض:

<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <VirtualizingStackPanel/>
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
هل كانت مفيدة؟

المحلول

أنا أحب الطريقة التي تحاول القيام بها هنا.بالنسبة للأجهزة التي تعمل باللمس، ليس لدينا MouseOver الحدث، لذا فهذه إحدى الطرق التي تريد من خلالها عرض بعض المعلومات الإضافية دون العبث بواجهة المستخدم.

ومع ذلك، فإن الحل الأكثر نظافة هو إنشاء مادة قابلة لإعادة الاستخدام Behavior الذي يلخص كل منطق واجهة المستخدم والرسوم المتحركة.

للقيام بذلك، سوف تحتاج أولا إلى تضمين المرجع 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;
    }
}

هذا Behavior ويمكن بعد ذلك أن تعلق على الخاص بك DataTemplateالمستوى الأعلى Grid.لاحظ أنك لا تحتاج إلى UserControl لتغليفها بعد الآن.

تأكد أيضًا من أن لديك لون خلفية للملف Grid حتى يتمكن من استقبال أحداث اللمس.آخر شيء فعلته هو تغيير ListViewItemContainerStyleHorizontalContentAlignment ل Stretch لذلك 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>

نصائح أخرى

لقد وجدت حلاً بديلاً؛لقد أضفت خاصية تسمى DescriptionLayerOpacity إلى النموذج الخاص بي وقم بتعيينه على القيمة الافتراضية لـ 0 عندما أقوم بإضافة عنصر جديد إلى بلدي ObservableCollection في نموذج العرض الخاص بي

لقد أضفت أيضًا ربطًا ثنائي الاتجاه لتغيير خاصية المصدر (DescriptionLayerOpacity) بحيث يتم تحديث العرض بالتغييرات التي أجرتها القصص المصورة:

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

باختصار، يجب أن تكون جميع بيانات UserControl مرتبطة بالبيانات لتجنب تكرارها في العناصر الأخرى في ListView.

هذا ليس حلاً أنيقًا حقًا ولم يتم اختباره بالكامل.وإلى أن أجد حلاً حقيقياً، فهذا سيكون كافياً.

تحديث:لا تعمل بشكل كامل

لقد اكتشفت مؤخرًا أن بعض العناصر لا تستجيب عند تحديد عناصر أخرى.لكي تستجيب هذه العناصر، لا بد لي من النقر قبل حدث النقر + الاستمرار (كلاهما حدثان متنافيان، بالمناسبة).

التحديث 2:

يبدو أن كل شيء يعمل بشكل جيد بعد إزالة الملف if البيانات في codebehind.لكن الارتباط بخاصية العتامة في النموذج لتشغيله لا يزال يمثل حلاً كريه الرائحة.

ألقِ نظرة على الحل هنا: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/95f49050-368e-4ddb-962e-6be62e7e3d57/context-menus-in-listview-windows-phone-81?forum=wpdevelop

لست متأكدًا مما إذا كانت هذه هي مشكلتك بالضبط، ولكن يبدو أن UserControl لا يتلقى حدث التعليق لأنه يتم استيعابه بواسطة ListView؟يصف الحل أعلاه الحاجة إلى التفاف الملف DataTemplates Grid في ListViewItem, ، وإرفاق حدث Hold لذلك.ربما هذا سوف يساعد؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top