0

Currently i'm facing a really weird problem. My template selector seems to be some kind of delayed.

Really rough description of my current situation, i'm devolping a simple UWP application with a nested listview to display some items grouped by fixed properties. These Items should be editable by switching the View from "ViewMode" to "EditMode". By enabling the "EditView" the First ListView isn't updated to the EditView template...?! But Why? I Made a complete Demo example which consists of the View User Control, the Main Page and a Demo Model classes as follows (the complete demo on github: https://github.com/tzdlr/SODemo):

UWP Page:

<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

<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>

My models and other classes:

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;
        }
    }
}

And here is the result, window behind in "ViewMode", window in Front: "EditView":

enter image description here

TinoZ
  • 560
  • 1
  • 5
  • 17

1 Answers1

1

XAML TemplateSelector seems kind of delayed

During testing above code sample. it looks nested listview cache cause this problem. you just clear the parent item source. but not clear the nested.

Please find line 36 EditMode set method call _ds.LoadData() to clear nested

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

Update

<ListView x:Name="list" ItemsSource="{x:Bind MyListCollection, Mode=TwoWay}">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
 ......
Nico Zhu
  • 32,367
  • 2
  • 15
  • 36
  • Hrm, that's a neat Idea, but collecting all data is very time consuming, thats why i implemented a cache in my dataservice :-/ is there no way to update the first listview? It's just the first, every following ones are generated correctly – TinoZ Aug 24 '21 at 07:56
  • 1
    Ok, the other workaround is disable listview visualization. you could disable the parent's visualization with above code where in the case update. – Nico Zhu Aug 24 '21 at 08:14
  • If you test multiple times, you will find that not only the first listview does not update the template, but sometimes the third listview also has problems. – Nico Zhu Aug 24 '21 at 08:25
  • the update seems to work in the demo, currently i'm unable to test in productive project because of missing project here, will come back later! But, one question for my personal understanding, what does the ItemsPanelTemplate interfer with? – TinoZ Aug 24 '21 at 09:41
  • 1
    in my opinion, the key point is visualization, if you disable it, it will render all the item when load the data. – Nico Zhu Aug 24 '21 at 09:55