Sometimes you’ll need to create instances of your own types—or other .NET Framework, non-WPF types—directly within XAML. This is common when working with data binding scenarios, such as value converters (which I’ll cover in an upcoming article).
When you bind or place a custom class inside a WPF control like a Label, you might see the namespace and class name appear instead of readable text.
That’s because WPF’s rendering order works like this:
1️⃣ Use a matching DataTemplate (if one exists) — I’ll cover this in a future article.
2️⃣ If not, call ToString() on the bound object.
3️⃣ If not overridden, call the default ToString() from the base Object class.
When no DataTemplate is defined, WPF calls the object’s ToString() method to render it as text. If you don’t override it, the default behavior displays the class name.
🎬 Watch the Demo
Here’s a quick demo showing how overriding ToString() affects what’s displayed in a Label.
Here’s the source code used in the demo:
🧱 Project Setup
WpfCookbookDemo/
├── WpfCookbookDemo.csproj
├── App.xaml
├── MainWindow.xaml
├── MainWindow.xaml.cs
└── Person.cs
💻 Person.cs
namespace WpfCookbookDemo
{
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string PhoneNumber { get; set; }
public override string ToString()
=> $"{Name}, {Age} years old, Phone: {PhoneNumber}";
}
}
🪄 MainWindow.xaml
Here we add a Person object directly inside a Label.
<Window x:Class="WpfCookbookDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCookbookDemo"
Title="WPF Cookbook #1"
Height="200" Width="300"
Background="#F3F3F3">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Label FontSize="18" HorizontalAlignment="Center">
<local:Person Name="Daniel"
Age="30"
PhoneNumber="123-456-7890" />
</Label>
</Grid>
</Window>