我有一个非常简单的 ListView,它有一个 dataTemplate,它绑定到页面代码中的 ObservableCollection。我想在单击后立即更改列表视图中单个项目的高度。
这种行为应该模仿标准的 Mail 和 Wifi-Ui Windows 10 界面。


可能的解决方案:- 我在 Xaml 中定义了两个数据模板作为资源,并在单击事件中更改列表视图的 ItemTemplateSelector 属性。但问题是 listview 中的每个项目都会将自身更改为该数据模板,顺便说一下,这是有道理的。但这不是我想要实现的。我只想在单击时更改列表视图中单个项目的高度,甚至可能带有一些动画。
可能的第二种解决方案:我在我的 Xaml 中只定义了一个包含网格的数据模板。现在我正在做的是将网格的高度绑定到 C# 代码中的公共属性。在 Itemclick 事件中,我得到了 e.ClickedItem,然后将属性的高度更改为不同的值。这应该可以工作,但绑定到 Grid Height 的值确实会发生变化,但不会反映在 UI 中。是否与{Bind statement}有关,是否需要使用{x:Bind}?
我想为折叠视图和展开视图之间的过渡设置动画。
你可以有两个共享一些 UI 的数据模板,一个比另一个有更多的元素。您将遇到的问题是如何即时更新到不同的模板。
我最近在这里回答了一个问题,该问题通过订阅该IsSelected属性并手动重置ContentTemplateSelector以强制更新模板来解决此问题。
但是将完整模板交换给我是一种矫枉过正,我也倾向于您的第二个解决方案。
看起来您正在尝试Height通过ViewModel 中的属性更新,这可以工作。但是对我来说,这种 UI 逻辑最好放在代码隐藏中,在那里您可以轻松获取Grid内部ItemClick回调并为其分配不同Height的内容。
但是,如果您在ListView其他地方需要具有类似要求的类似产品怎么办?你最终会得到很多重复的代码隐藏代码。这就是为什么我实际上会扩展ListViewItem功能以适应在其ItemTemplate. 所以这里是如何 -
首先,让我们创建一个ExtendedListViewItem继承自ListViewItem. 这个扩展控件做了两件事——
IsExpandable,稍后将附加到ListView的数据模板内的某个 UI 元素。ListViewItem点击a 时,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;
            }));
}
接下来,我们还需要扩展ListView控件以将我们的ExtendedListViewItem控件作为其子控件而不是默认的ListViewItem.
public class ExtendedListView : ListView
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new ExtendedListViewItem();
    }
}
最后,是时候将IsExpandable标志附加到正确的元素上了。例如,我只希望在单击项目时显示文本 -
<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}" />
注意到ExtendedListView控件正在订阅一个名为ContainerContentChanging? 您可以在此处为项目创建隐式偏移动画,以使布局更改更有趣。
    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);
        }
    }
希望这可以帮助!