简体   繁体   English

如何更改单击的 ListView 项 (UWP) 的内容? 就像邮件应用程序一样

[英]How can I change the contents of the ListView item(UWP) that is clicked? Like Mail App does

I have a very simple ListView that has a dataTemplate, which is bound to a ObservableCollection in page code.我有一个非常简单的 ListView,它有一个 dataTemplate,它绑定到页面代码中的 ObservableCollection。 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.这种行为应该模仿标准的 Mail 和 Wifi-Ui Windows 10 界面。

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.可能的解决方案:- 我在 Xaml 中定义了两个数据模板作为资源,并且在单击事件中我正在更改列表视图的 ItemTemplateSelector 属性。 But the problem is that every item in listview changes itself to that datatemplate, which by the way makes sense.但问题是 listview 中的每个项目都会将自身更改为该数据模板,顺便说一下,这是有道理的。 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.可能的第二种解决方案:我在我的 Xaml 中只定义了一个包含网格的数据模板。 Now what I am doing is binding height of grid to a public property in c# code.现在我正在做的是将网格的高度绑定到 C# 代码中的公共属性。 And in Itemclick event I am getting the e.ClickedItem and then changing the height of the property to something different.在 Itemclick 事件中,我得到了 e.ClickedItem,然后将属性的高度更改为不同的值。 This is supposed to work but the value which is bound to Grid Height does changes but is not reflected in UI.这应该可以工作,但绑定到 Grid Height 的值确实会发生变化,但不会反映在 UI 中。 Does it has somthing to do with {Bind statement}, do I need to use {x:Bind}?是否与{Bind statement}有关,是否需要使用{x:Bind}?

I want to animate the transition between collapsed and expanded views.我想为折叠视图和展开视图之间的过渡设置动画。

Possible Solution 1可能的解决方案 1

You can have two data templates which share some UI, and one has some more elements than the other.你可以有两个共享一些 UI 的数据模板,一个比另一个有更多的元素。 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.我最近在这里回答了一个问题,该问题通过订阅IsSelected属性并手动重置ContentTemplateSelector以强制更新模板来解决此问题。

But swapping the full template to me is an overkill, and I lean towards your second solution too.但是将完整模板交换给我是一种矫枉过正,我也倾向于您的第二个解决方案。

Possible Solution 2可能的解决方案 2

Looks like you are trying to update the Height via a property in your ViewModel , this could work.看起来您正在尝试通过ViewModel 中的属性更新Height ,这可以工作。 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.但对我来说,这种 UI 逻辑最好放在代码隐藏中,您可以在其中轻松获取ItemClick回调中的Grid并为其分配不同的Height

But then what if you needed a similar ListView elsewhere with similar requirements?但是,如果您在其他地方需要具有类似要求的类似ListView怎么办? 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 .这就是为什么我实际上会扩展ListViewItem功能以适应在其ItemTemplate扩展 UI 的某些部分。 So here is how -所以这里是如何 -

First, let's create an ExtendedListViewItem that inherits from the ListViewItem .首先,让我们创建一个从ListViewItem继承的ExtendedListViewItem 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.创建一个名为IsExpandable附加属性,该属性稍后将附加到ListView数据模板内的某个 UI 元素。
  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.由于每次单击ListViewItem时, IsSelected属性都会更新,因此我们可以监视它以相应地显示和隐藏IsExpandable元素。

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 .接下来,我们还需要扩展ListView控件以将我们的ExtendedListViewItem控件作为其子控件,而不是默认的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.最后,是时候将IsExpandable标志附加到正确的元素上。 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 ?注意到ExtendedListView控件订阅了一个名为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!希望这有帮助!

Okay, sorry about that, I understand now.好吧,对不起,我现在明白了。 First of all you need to set the name and original height of the list view in your xaml.首先,您需要在 xaml 中设置列​​表视图的名称和原始高度。

<ListView x:Name="GenericName" height="x"></ListView>

Next, you want to have a code behind about the button being clicked.接下来,您希望有一个关于被点击的按钮的代码。 within this.这其中。 you need to put in a statement that will set the height to a different value.您需要放入一个语句,将高度设置为不同的值。 It's actually pretty simple.其实很简单。

    private void Button_Click (object sender, RoutedEventArgs e)
{
        GenericName.Height = NewValue;
}

And that should work.这应该有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使StackPanel更改UWP中的ListView项目之类的背景? - How to make StackPanel to change background like ListView item in UWP? 如何强制ListView忽略单击/不突出显示单击的项目? - How can I force a ListView to disregard clicking/not highlight a clicked item? 如何使我的 UWP 应用程序像 Microsoft UWP 应用程序(邮件、Groove 音乐)一样快? - How can I make my UWP app Fast as Microsoft UWP apps(Mail, Groove Music)? 如何在UPF等WPF应用中使用关联动画 - How can I Use Connected Animation in WPF App like UWP 如何更改UWP中所选ListView项的突出显示颜色(Windows 10) - How to change Highlight color of the selected ListView item in UWP (Windows 10) uwp:如何根据listview项的值更改listview项的背景颜色? - uwp: how to change background color of listview item based on its value? 如何在UWP应用中检测何时将项目添加到ListView或从ListView中删除? - How to detect when a item is added to or removed from a ListView in UWP app? 如何在 UWP 中将 ListView 项与 model 之外的数据绑定? - How can I bind a ListView Item with data outside from model in UWP? 如何更改 ListView 控件中单个子项的前景色? - How can I change the ForeColor of a single sub item in a ListView control? 如何更改单个Listview的项目ItemTemplate? - How can i change single Listview's item ItemTemplate?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM