Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically bind the ItemSource of a ListView which has ItemTemplateSelector containing Multiple DataTemplates which have Different DataTypes?

I have an ItemTemplateSelector which contains Multiple DataTemplates which have Different DataTypes. I thus have multiple ItemSources based on Module Selected. How to bind my ListView with multiple ItemSources based on the module selected?

Explanation:

1)ViewModel_A is my ItemSource and DataTemplateA is my DataTemplate when my Module A is Selected

2)ViewModel_B is my ItemSource DataTemplateB is my DataTemplate when my Module B is Selected

I tried Implementing a BaseViewModel and tried binding the BaseViewModel Type in my ItemSource But this doesn't allow the access of derived class properties.

How to Dynamically Select My ItemSource?

like image 245
Prithvi Avatar asked Sep 18 '25 20:09

Prithvi


1 Answers

Step 1

First Create a UserControl which contains your ListView in your Xaml and two DependancyProperty for ItemSource and DataTemplate

DataList.Xaml

<UserControl
x:Class="MultipleDataTemplate.DataList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>

   <Grid>
   <ListView ItemsSource="{x:Bind ItemsSource,Mode=OneWay}"></ListView>
   </Grid>
</UserControl>

DataList.xaml.cs

public sealed partial class DataList : UserControl
{
    public DataList()
    {
        this.InitializeComponent();
    }
    #region ItemsSource
    public object ItemsSource
    {
        get { return (object)GetValue(ItemsSourceProperty); }
        set {  SetValue(ItemsSourceProperty, value); }
    }              
    public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(nameof(ItemsSource), typeof(object), typeof(DataList), new PropertyMetadata(null));
    #endregion
    #region ItemTemplate
    public DataTemplate ItemTemplate
    {
        get { return (DataTemplate)GetValue(ItemTemplateProperty); }
        set { SetValue(ItemTemplateProperty, value); }
    }

    public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register(nameof(ItemTemplate), typeof(DataTemplate), typeof(DataList), new PropertyMetadata(null));
    #endregion
}

Step 2

Now you can you this usercontrol with any multiple DataTemplate's and multiple itemsource as below

MainPage.xaml

<Page
    x:Class="MultipleDataTemplate.Cars"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:controls="using:MultipleDataTemplate">
    <Page.Resources>
        <DataTemplate x:Key="CarKey" x:DataType="controls:Car">
            <Grid>
                <TextBlock Text="{x:Bind carprop1}"></TextBlock>
                <TextBlock Text="{x:Bind carprop2}"></TextBlock>

            </Grid>
        </DataTemplate>
        <DataTemplate x:Key="BikeKey" x:DataType="controls:Bike">
            <Grid>
                <TextBlock Text="{x:Bind Bikeprop1}"></TextBlock>
                <TextBlock Text="{x:Bind Bikeprop2}"></TextBlock>

            </Grid>
        </DataTemplate>
    </Page.Resources>
    <Grid>        
        <controls:DataList ItemsSource="{x:Bind ItemSource,Mode=OneWay}" ItemTemplate="{x:Bind ItemTemplate}"></controls:DataList>
        <StackPanel>
            <Button Content="Cars" Click="CarsClick"/>
            <Button Content="Bike" Click="BikeClick"/>
        </StackPanel>
    </Grid>
</Page>

MainPage.xaml.cs

public sealed partial class Cars : Page, INotifyPropertyChanged
{
    public object _ItemSource { get; set; }

    public object ItemSource
    {
        get { return _ItemSource; }
        set
        {
            _ItemSource = value;
            this.OnPropertyChanged();
        }
    }
    public DataTemplate _itemTemplate { get; set; }

    public DataTemplate ItemTemplate
    {
        get { return _itemTemplate; }
        set
        {
            _itemTemplate = value;
            this.OnPropertyChanged();
        }
    }
    public Cars()
    {
        this.InitializeComponent();
    }
    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged;


    private void CarsClick(object sender, RoutedEventArgs e)
    {
        ItemSource = new List<Car>() { new Car() { carprop1 = "1", carprop2 = "2" } };
        ItemTemplate = this.Resources["CarKey"] as DataTemplate;
    }

    private void BikeClick(object sender, RoutedEventArgs e)
    {
        ItemSource = new List<Bike>() { new Bike() { Bikeprop1 = "1", Bikeprop2 = "2" } };
        ItemTemplate = this.Resources["BikeKey"] as DataTemplate;
    }
}
public class Car
{
    public string carprop1 { get; set; }
    public string carprop2 { get; set; }
}
public class Bike
{
    public string Bikeprop1 { get; set; }
    public string Bikeprop2 { get; set; }
}
like image 60
Vignesh Avatar answered Sep 20 '25 11:09

Vignesh