Changing ListViewItemTemplate on user click

BitSmithy 1,751 Reputation points
2024-03-07T12:56:35.4366667+00:00

Hello,

I have a ListView with item template selector. Now user clicks on any item, DataTemplate of clicked item should change, without reading items source again. How to improve my code to meet such task.

<Page
...
 >     <Page.Resources>
        <DataTemplate x:Key="XKSimpleDataTemplate" x:DataType="local:MyData">
            <StackPanel Orientation="Horizontal">
                <SymbolIcon x:Name="siInfo" Symbol="More"                           
                            PointerPressed="ChangeLinkDataTemplate_PointerPressed"                            
                            ></SymbolIcon>
                <TextBlock Text="{x:Bind data1}"></TextBlock>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="XKFullDataTemplate" x:DataType="local:MyData">
            <StackPanel Orientation="Vertical">
                <SymbolIcon x:Name="siInfo" Symbol="More"                           
                            PointerPressed="ChangeLinkDataTemplate_PointerPressed"                            
                            ></SymbolIcon>
                <TextBlock Text="{x:Bind data1}"></TextBlock>
                <TextBlock Text="{x:Bind data2}"></TextBlock>
                <TextBlock Text="{x:Bind data3}"></TextBlock>
            </StackPanel>
        </DataTemplate>
    </Page.Resources>

    <StackPanel>
        <Button Content="Retrieve" Click="Retrieve_Click"></Button>
        <ListView x:Name="lvMydata"
 HorizontalAlignment="Stretch"
                      HorizontalContentAlignment="Stretch"
                  >
            <ListView.ItemTemplateSelector>
                <local:MyDataTemplateSelector 
                        SimpleDataTemplate="{StaticResource XKSimpleDataTemplate}"
                        FullDataTemplate="{StaticResource XKFullDataTemplate}"/>
            </ListView.ItemTemplateSelector>
        </ListView>

    </StackPanel>
</Page>

Code Behind:

 namespace ChangeDataTemplate_Test {

    public sealed partial class MainPage : Page
    {
        ObservableCollection<MyData> ocMayData = new ObservableCollection<MyData>();

        public MainPage()
        {
            this.InitializeComponent();

            ocMayData.Add(new MyData("AAA", "BBB", "CCC"));
            ocMayData.Add(new MyData("XXX", "YYY", "ZZZ"));

            lvMydata.ItemsSource = ocMayData;

        }

        private void ChangeLinkDataTemplate_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            if (sender is SymbolIcon si)
                if (si.Name == "siInfo")
                {
                    //get item container
                    DependencyObject dpo = VisualTreeHelper.GetParent(si);
                    dpo = VisualTreeHelper.GetParent(dpo);
                    ListViewItem lvi = (ListViewItem)VisualTreeHelper.GetParent(dpo);

                    //set
                    if (lvMydata.ItemFromContainer(lvi) is MyData md)
                    {
                        md.IsOpened = !md.IsOpened;
                        //lvMydata.ItemTemplateSelector.SelectTemplate(lvi);

                        //alternative code
                        //if(lvMydata.ItemTemplateSelector is MyDataTemplateSelector mdts)
                            //mdts.SwitchTemplate(md);
                    }
                }
        }

        private void Retrieve_Click(object sender, RoutedEventArgs e)
        {
            lvMydata.ItemsSource = null;
            lvMydata.ItemsSource = ocMayData;
        }
    }

    public class MyData : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public string data1;
        public string data2;
        public string data3;

        private bool isOpened = false;
        public bool IsOpened
        {
            get { return isOpened; }
            set
            {
                if (value != isOpened && this.PropertyChanged != null)
                {
                    isOpened = value;

                    this.PropertyChanged(this, new PropertyChangedEventArgs("IsOpened"));
                }
                else
                    isOpened = value;
            }
        }

        public MyData(string data1 = null, string data2 = null, string data3 = null)
        {
            this.data1 = data1 ?? string.Empty;
            this.data2 = data2 ?? string.Empty;
            this.data3 = data3 ?? string.Empty;
        }
    }//End MyData

    public class MyDataTemplateSelector : DataTemplateSelector
    {
        public DataTemplate SimpleDataTemplate { get; set; }
        public DataTemplate FullDataTemplate { get; set; }
        
        protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
        {
            if (item is MyData md)
                if (md.IsOpened == false)
                    return SimpleDataTemplate;
                else
                    return FullDataTemplate;
            else
                return SimpleDataTemplate;
        }

        public void SwitchTemplate(object item)
        {
            if (item is MyData md)
                if (md.IsOpened == false)
                    md.IsOpened = true;
                else
                    md.IsOpened = false;
                                           
            SelectTemplateCore(item);
        }     } }
Universal Windows Platform (UWP)
0 comments No comments
{count} votes

Accepted answer
  1. Junjie Zhu - MSFT 14,831 Reputation points Microsoft Vendor
    2024-03-08T06:47:14.4933333+00:00

    Hello @BitSmithy ,

    Welcome to Microsoft Q&A!

    I'd modify the code to suit your needs, but it doesn't seem possible. Because when the isOpened value changes, SelectTemplateCore cannot be triggered, even if you force the call in ChangeLinkDataTemplate_PointerPressed.

    There are two possible solutions now. One is to reload data in ChangeLinkDataTemplate_PointerPressed, or reload ContentTemplateSelector in SelectTemplateCore. Reloading data in pointerpressed seems to be smoother.

    Thank you.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful