Search code examples
c#wpfdata-bindingdatagrid

Binding class data on DataGrid


I am having trouble showing the Address portion of my Customer class, i have made an Location property that show the whole address but when i run the application the address is missing. As you can see in the image the Customer binds to the data grid.

enter image description here

If i can not find a solution i will just add the address properties to my Customer class, but i would like to solve if possible.

Thanks in advance.

Example instance:

var customer = new Customer
        {
            FirstName = fNameTxt.Text, LastName = lNameTxt.Text, Email = emailTxt.Text, Phone = phTxt.Text,
            Address = new Address { Street = streetTxt.Text, Suburb = suburbTxt.Text, City = cityTxt.Text, Country = countryTxt.Text }
        };

XAML: (datagrid)

<DataGrid x:Name="customerDataGrid" HorizontalAlignment="Left" Height="205" Margin="10,10,0,0" Grid.Row="1" VerticalAlignment="Top" Width="780" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Id" Binding="{Binding Id}"/>
            <DataGridTextColumn Header="Full Name" Binding="{Binding FullName}"/>
            <DataGridTextColumn Header="Phone" Binding="{Binding Phone}"/>
            <DataGridTextColumn Header="Email" Binding="{Binding Email}"/>
            <DataGridTextColumn Header="Address" Binding="{Binding Location}"/>
        </DataGrid.Columns>
    </DataGrid>

Classes:

public class Customer
{
    public int Id { get; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName { get { return FirstName + " " + LastName; } }
    public string Phone { get; set; }
    public string Email { get; set; }
    public Address Address { get; set; }

    private static int counter = 0;
    public Customer()
    {
        this.Id = System.Threading.Interlocked.Increment(ref counter);
    }
}

public class Address
{
    public string Street { get; set; }
    public string Suburb { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public string Location { get { return string.Format($"{Street}, {Suburb}, {City}, {Country}"); } }
}

Solution

  • <DataGridTextColumn Header="Email" Binding="{Binding Email}"/>
    <DataGridTextColumn Header="Address" Binding="{Binding Location}"/>
    

    Email is a property of Customer class, so binding path Email in binding {Binding Path=Email} is resolved succesfully and email is shown.

    But here {Binding Path=Location} binding path Location is wrong. Location is a property of Address class. Customer has only Address property of type Address. This makes Location a nested property. Binding should be changed:

    <DataGridTextColumn Header="Email" Binding="{Binding Email}"/>
    <DataGridTextColumn Header="Address" Binding="{Binding Address.Location}"/>
    

    compare it with c# code:

    var c = new Customer();
    string location = c.Location; // ! won't compile
    string location = c.Address.Location; // will compile, but give NullReferenceException, because Address wasn't initialized
    

    as a last note: Visual Studio should have written multiple binding errors in Output window about Location property not found in Customer object. always check Output if binding doesn't work