Home > Back-end >  Display all properties of a Class with XAML
Display all properties of a Class with XAML

Time:09-29

I am new to WPF and spent hours of searching a solution for that, but I cannot find anything.

I want to display all properties of a class with a DataTemplate:

<ItemsControl ItemsSource="{Binding Car}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
public class Car
{
    public int Axes { get; set; }
    public int Seats { get; set; }
    public int Doors { get; set; }
    public VehicleProperties.Car.Type Type { get; set; }
    public int MaxWeight { get; set; }
    public Fuel Fuel { get; set; }
    public double ConsumptionPer100km { get; set; }
    public bool Childseat { get; set; }
    public string Brand { get; set; }
    public string Model { get; set; }
    public int FirstRegistration { get; set; }
    public int Mileage { get; set; }
    public Transmission Transmission { get; set; }
    public int Power { get; set; }
    public bool Tempomat { get; set; }
    public SolidColorBrush Color { get; set; }
    public int PollutionClass { get; set; }
    public int EnvironmentalBadge { get; set; }
}

How can I at least display the name and bind the ItemsSource and the TextBlock correctly? I need that, because after this, I will design the DataTemplates with the DataType property.

CodePudding user response:

If you are only interested in the property names of a concrete type, you could create a custom markup extension that receives a type and uses reflection to get its property infos and returns the property names as enumerable.

public class PropertyNamesExtension : MarkupExtension
{
   public Type Type { get; set; }

   public PropertyNamesExtension(Type type)
   {
      Type = type;
   }

   public override object ProvideValue(IServiceProvider serviceProvider)
   {
      return Type?.GetProperties().Select(propertyInfo => propertyInfo.Name);
   }
}

In XAML you can use the markup extension with the type Car as ItemsSource.

<ItemsControl ItemsSource="{local:PropertyNamesExtension local:Car}">
   <ItemsControl.ItemTemplate>
      <DataTemplate>
         <TextBlock Text="{Binding}" />
      </DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>

If you want more information, e.g. the type of each property, return the PropertyInfos instead.

public override object ProvideValue(IServiceProvider serviceProvider)
{
   return Type?.GetProperties();
}
<ItemsControl ItemsSource="{local:PropertyNamesExtension local:Car}">
   <ItemsControl.ItemTemplate>
      <DataTemplate>
         <TextBlock>
            <Run Text="{Binding Name, Mode=OneWay}"/>
            <Run Text="{Binding PropertyType, Mode=OneWay}"/>
         </TextBlock>
      </DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>

I need that, because after this, I will design the DataTemplates with the DataType-Property.

I do not know exactly what you goal is, but I think you are trying to achieve something different. Let's suppose you want to display a single instance of a Car. Then expose that instance through a property and bind it as Content of a ContentControl with a DataTemplate.

public Car Car { get; }
<ContentControl Content="{Binding Car}">
   <ContentControl.ContentTemplate>
      <DataTemplate DataType="{x:Type local:Car}">
         <StackPanel>
            <TextBlock Text="{Binding Brand}"/>
            <TextBlock Text="{Binding Axes}"/>
            <!-- ...other markup. -->
         </StackPanel>
      </DataTemplate>
   </ContentControl.ContentTemplate>
</ContentControl>

If you want to show a list of Cars, expose them as any collection, e.g. a List<Car> or an ObservableCollection<Car> if the collection is changed at runtime (otherwise added or removed items will not be updated in the user interface). Then use an ItemsControl or ListBox or ListView depending on your requirements and add an ItemsTemplate.

public ObservableCollection<Car> Cars { get; }
<ItemsControl ItemsSource="{Binding Cars}">
   <ItemsControl.ItemTemplate>
      <DataTemplate>
         <StackPanel>
            <TextBlock Text="{Binding Brand}"/>
            <TextBlock Text="{Binding Axes}"/>
            <!-- ...other markup. -->
         </StackPanel>
      </DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>

CodePudding user response:

C# code

Car car = new();
itemControl.ItemsSource = car.GetType().GetProperties();
  • Related