【问题标题】:XAML TemplateSelector seems kind of delayedXAML TemplateSelector 似乎有点延迟
【发布时间】:2021-10-24 03:25:06
【问题描述】:

目前我正面临一个非常奇怪的问题。我的模板选择器似乎有些延迟。

对我目前情况的粗略描述,我正在开发一个带有嵌套列表视图的简单 UWP 应用程序,以显示一些按固定属性分组的项目。通过将视图从“ViewMode”切换到“EditMode”,这些项目应该是可编辑的。通过启用“EditView”,第一个 ListView 不会更新为 EditView 模板...?!但为什么?我做了一个完整的 Demo 示例,它由 View User Control、Main Page 和一个 Demo Model 类组成如下(github 上的完整演示:https://github.com/tzdlr/SODemo):

UWP 页面:

<Page
    x:Class="UWPTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWPTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <CommandBar Grid.Row="0">
            <AppBarToggleButton Icon="Edit" Label="Bearbeitungs-Ansicht" IsChecked="{x:Bind EditMode, Mode=TwoWay}" />
        </CommandBar>
        <local:ListViewControl Grid.Row="1" MyListCollection="{x:Bind MyList}"></local:ListViewControl>
    </Grid>
</Page>

UWP 用户控件

<UserControl
    x:Class="UWPTest.ListViewControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWPTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">
    <UserControl.Resources>
        <DataTemplate x:Key="DTView" x:DataType="local:Model">
            <Grid>
                <TextBlock Text="{x:Bind Text}"></TextBlock>
            </Grid>
        </DataTemplate>

        <DataTemplate x:Key="DTEdit" x:DataType="local:Model">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                    <ColumnDefinition Width="auto"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBox Grid.Column="0" Text="{x:Bind Text,Mode=TwoWay}"></TextBox>
                <Button Grid.Column="1" Content="Delete"></Button>
            </Grid>
        </DataTemplate>

        <local:ModelSelector x:Key="tplSelector"
            ViewTemplate="{StaticResource DTView}"
            EditTemplate="{StaticResource DTEdit}" />


    </UserControl.Resources>

    <ListView x:Name="list" ItemsSource="{x:Bind MyListCollection, Mode=TwoWay}">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:ListModel">
                <ListView ItemsSource="{x:Bind ModelList,Mode=TwoWay}" ItemTemplateSelector="{StaticResource tplSelector}"></ListView>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

</UserControl>

我的模型和其他课程:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace UWPTest
{
    public class Model
    {
        public string Text;

        public Model(string t) { Text = t; }
    }

    public class ListModel
    {
        public List<Model> ModelList = new List<Model>();
    }

    public class ModelSelector : DataTemplateSelector
    {
        public DataTemplate ViewTemplate { get; set; }
        public DataTemplate EditTemplate { get; set; }

        protected override DataTemplate SelectTemplateCore(object item)
        {
            return StaticHelper.EditView ? EditTemplate : ViewTemplate;
        }

        protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
        {
            return StaticHelper.EditView ? EditTemplate : ViewTemplate;
        }
    }
    static class StaticHelper
    {
        public static bool EditView { get; set; } = false;
    }

    public class DataService
    {
        private List<ListModel> _cache = new List<ListModel>();

        public void LoadData()
        {
            _cache.Clear();
            for (var i = 0; i < 5; i++)
            {
                ListModel nl = new ListModel();
                for (var k = 0; k < 10; k++)
                {
                    nl.ModelList.Add(new Model(i + "-" + k));
                }
                _cache.Add(nl);
            }
        }

        public List<ListModel> getCachedEntries()
        {
            return _cache;
        }
    }
}

这是结果,“ViewMode”中的窗口,前面的窗口:“EditView”:

【问题讨论】:

  • 以下操作有效吗?此线程有任何更新吗?

标签: c# xaml uwp-xaml


【解决方案1】:

XAML TemplateSelector 似乎有点延迟

在测试上述代码示例期间。它看起来嵌套的列表视图缓存导致了这个问题。您只需清除父项源。但不清除嵌套。

请找到第36行EditModeset方法调用_ds.LoadData()清除嵌套

public bool EditMode
{
    get { return (bool)GetValue(EditViewProperty); }
    set
    {
        StaticHelper.EditView = value;
        Task.Run(() => { _ds.LoadData(); BuildSource(); });
        SetValue(EditViewProperty, value);
    }
}

更新

<ListView x:Name="list" ItemsSource="{x:Bind MyListCollection, Mode=TwoWay}">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
 ......

【讨论】:

  • Hrm,这是个好主意,但是收集所有数据非常耗时,这就是为什么我在我的数据服务中实现了缓存:-/ 没有办法更新第一个列表视图吗?只是第一个,后面的都是正确生成的
  • 好的,另一种解决方法是禁用列表视图可视化。您可以使用上面的代码在案例更新的情况下禁用父级的可视化。
  • 多次测试会发现不仅第一个listview没有更新模板,有时第三个listview也有问题。
  • 更新似乎在演示中有效,目前我无法在生产项目中进行测试,因为这里缺少项目,稍后会回来!但是,我个人理解的一个问题是,ItemsPanelTemplate 会干扰什么?
  • 在我看来,关键是可视化,如果禁用它,它会在加载数据时呈现所有项目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多