如何更改单击的 ListView 项 (UWP) 的内容?就像邮件应用程序一样 [英] How can I change the contents of the ListView item(UWP) that is clicked? Like Mail App does

查看:28
本文介绍了如何更改单击的 ListView 项 (UWP) 的内容?就像邮件应用程序一样的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常简单的 ListView,它有一个 dataTemplate,它在页面代码中绑定到一个 ObservableCollection.我想在单击后立即更改列表视图中单个项目的高度.

<块引用>

这种行为应该模仿标准的邮件和 Wifi-Ui Windows 10 界面.

折叠视图

扩展视图

可能的解决方案:- 我在 Xaml 中定义了两个数据模板作为资源,并在单击事件中更改了列表视图的 ItemTemplateSelector 属性.但问题是 listview 中的每个项目都会将自身更改为该数据模板,顺便说一下,这是有道理的.但这不是我想要实现的.我只想在单击时更改列表视图中单个项目的高度,甚至可能带有一些动画.

可能的第二种解决方案:我在我的 Xaml 中只定义了一个包含网格的数据模板.现在我正在做的是将网格的高度绑定到 C# 代码中的公共属性.在 Itemclick 事件中,我得到了 e.ClickedItem,然后将属性的高度更改为不同的值.这应该可以工作,但绑定到 Grid Height 的值确实会发生变化,但不会反映在 UI 中.和{Bind statement}有关系吗,需要用{x:Bind}吗?

我想为折叠视图和展开视图之间的过渡设置动画.

解决方案

可能的解决方案 1

您可以拥有两个共享一些 UI 的数据模板,一个比另一个包含更多元素.您将遇到的问题是如何通过即时点击更新到不同的模板.

我最近回答了一个问题

希望这会有所帮助!

I have a very simple ListView that has a dataTemplate, which is bound to a ObservableCollection in page code. I want to change the height of a single Item in listview as soon as it gets clicked.

This behaviour shopuld mimic the standard Mail and Wifi-Ui Windows 10 interfaces.

Callapsed View

Expanded View

Possible Solution:- I have defined two datatemplate in Xaml as a resource and in a click event I am changing the ItemTemplateSelector property of listview. But the problem is that every item in listview changes itself to that datatemplate, which by the way makes sense. But this is not what I want to implement. I just want to change the height of a single item in listview when clicked maybe even with some animations.

Posssible Second Solution: I am defining just one datatemplate in my Xaml that contains a grid. Now what I am doing is binding height of grid to a public property in c# code. And in Itemclick event I am getting the e.ClickedItem and then changing the height of the property to something different. This is supposed to work but the value which is bound to Grid Height does changes but is not reflected in UI. Does it has somthing to do with {Bind statement}, do I need to use {x:Bind}?

I want to animate the transition between collapsed and expanded views.

解决方案

Possible Solution 1

You can have two data templates which share some UI, and one has some more elements than the other. The issue you will have is how to update to a different template on click on the fly.

I recently answered a question here which solves this issue by subscribing to the IsSelected property and manually reset the ContentTemplateSelector to force updating the template.

But swapping the full template to me is an overkill, and I lean towards your second solution too.

Possible Solution 2

Looks like you are trying to update the Height via a property in your ViewModel, this could work. But to me, this kind of UI logic is better put in the code-behind, where you can easily obtain your Grid inside the ItemClick callback and just assign a different Height to it.

But then what if you needed a similar ListView elsewhere with similar requirements? You'd end up with a lot of duplicate code-behind code. This is why I'd actually extend the ListViewItem functionality to cater for expanding some parts of UI inside its ItemTemplate. So here is how -

First, let's create an ExtendedListViewItem that inherits from the ListViewItem. This extended control does two things -

  1. Create an attached property called IsExpandable which will later be attached to some UI element inside the ListView's data template.
  2. Since every time when a ListViewItem is clicked, the IsSelected property gets updated, we can monitor it to show and hide the IsExpandable element(s) accordingly.


public class ExtendedListViewItem : ListViewItem
{
    public ExtendedListViewItem()
    {
        // This could be set in its default style in Generic.xaml instead.
        HorizontalContentAlignment = HorizontalAlignment.Stretch;

        RegisterPropertyChangedCallback(IsSelectedProperty, (s, e) =>
        {
            // Children() is available at
            // https://github.com/JustinXinLiu/Continuity/blob/0cc3d7556c747a060d40bae089b80eb845da84fa/Continuity/Extensions/UtilExtensions.cs#L25
            foreach (var child in this.Children())
            {
                if (GetIsExpandable(child))
                {
                    child.Visibility = IsSelected ? Visibility.Visible : Visibility.Collapsed;
                }
            }
        });
    }

    public static void SetIsExpandable(DependencyObject element, bool value) =>
        element.SetValue(IsExpandableProperty, value);
    public static bool GetIsExpandable(DependencyObject element) =>
        (bool)element.GetValue(IsExpandableProperty);
    public static readonly DependencyProperty IsExpandableProperty = DependencyProperty.RegisterAttached(
        "IsExpandable",
        typeof(bool),
        typeof(ExtendedListViewItem),
        new PropertyMetadata(default(bool), (s, e) =>
            {
                var element = (UIElement)s;
                element.Visibility = (bool)e.NewValue ? Visibility.Collapsed : Visibility.Visible;
            }));
}


Next, we also need to extend the ListView control to take our ExtendedListViewItem control as its child instead of the default ListViewItem.


public class ExtendedListView : ListView
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new ExtendedListViewItem();
    }
}


Finally, it's time to attach the IsExpandable flag to the right element. For example, I only want the texts to show when the item is clicked -


<DataTemplate x:Key="MyItemTemplate">
    <StackPanel Margin="24">
        <Image HorizontalAlignment="Left" Source="{Binding Property3}" Width="48" Height="48" />

        <StackPanel Margin="12" local:ExtendedListViewItem.IsExpandable="True">
            <TextBlock Text="{Binding Property1}" Style="{StaticResource TitleTextBlockStyle}" />
            <TextBlock Text="{Binding Property2}" Style="{StaticResource CaptionTextBlockStyle}" />
        </StackPanel>
    </StackPanel>
</DataTemplate>

<local:ExtendedListView ContainerContentChanging="OnMyListViewContainerContentChanging" 
                        ItemTemplate="{StaticResource MyItemTemplate}" 
                        ItemsSource="{Binding Groups}" />


Bonus

Noticed the ExtendedListView control is subscribing to an event called ContainerContentChanging? This is the place where you can create implicit offset animations for your items to make layout changes more interesting.


    private void OnMyListViewContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
    {
        var containerVisual = ElementCompositionPreview.GetElementVisual(args.ItemContainer);

        if (args.InRecycleQueue)
        {
            containerVisual.ImplicitAnimations = null;
        }
        else
        {
            // EnableImplicitAnimation() is available at
            // https://github.com/JustinXinLiu/Continuity/blob/0015a96897c138e09d8604267df46da936b66838/Continuity/Extensions/CompositionExtensions.Implicit.cs#L144
            containerVisual.EnableImplicitAnimation(VisualPropertyType.Offset, 400.0f);
        }
    }


Outcome

Hope this helps!

这篇关于如何更改单击的 ListView 项 (UWP) 的内容?就像邮件应用程序一样的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆