XAML TemplateSelector 似乎有点延迟

XAML TemplateSelector seems kind of delayed

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

对我当前情况的粗略描述,我正在开发一个简单的 UWP 应用程序,该应用程序具有嵌套列表视图以显示按固定属性分组的一些项目。这些项目应该可以通过将视图从“ViewMode”切换到“EditMode”来编辑。通过启用“EditView”,第一个 ListView 不会更新为 EditView 模板...?!但为什么?我制作了一个完整的演示示例,其中包括视图用户控件、主页和演示模型 类,如下所示(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;
        }
    }
}

这是结果,window 在“ViewMode”后面,window 在前面:“EditView”:

XAML TemplateSelector seems kind of delayed

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

请找到第 36 行 EditMode 设置方法调用 _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>
 ......