Search code examples
c#wpfdatatemplate

WPF - Templatize List of Objects Based on Their Type


I have a list objects (PropertyBase is the base type with a Key and a Value property) that I want to display to users in some sort of form format. Based on object type I want to switch between different controls. Let's say int, double values are presented with Labels, where as string values will be editable through TextBox. Similarly, I want to display a ComboBox for enum values.

So far I have read about DataTemplates, ContentPresenters and come up with the following xaml code piece. However, the template below displays object's type (PropertyBase[Int64], PropertyBase[String]) rather than it's value. What's wrong with that?

<ItemsControl ItemsSource="{Binding Path=Properties}">
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="models:PropertyBase">
            <Grid Margin="0,0,0,5">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Label Grid.Column="0" Content="{Binding Key}" />
                <ContentPresenter Grid.Column="1" Content="{Binding}">
                    <ContentPresenter.Resources>
                        <DataTemplate DataType="{x:Type system:Int64}">
                            <Label Content="{Binding}" />
                        </DataTemplate>
                        <DataTemplate DataType="{x:Type system:String}">
                            <TextBox Text="{Binding Value, Mode=TwoWay}" />
                        </DataTemplate>
                    </ContentPresenter.Resources>
                </ContentPresenter>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Solution

  • The problem was the data binding. ContentPresenter wasn't binded properly. <ContentPresenter Grid.Column="1" Content="{Binding}"> binds to the current source (ref). Current source is PropertyBase class that holds Key and Value. ContentPresenter was trying to display the PropertyBase class by calling ToString method rather than using Value I'd like to present.

    Using <ContentPresenter Grid.Column="1" Content="{Binding Path=Value}"> solves the issue.