1
votes

I have a WPF app that uses an Entity Framework Model. One of the Entities is an Employee Type. This entity has a LastName and FirstName property among others. But in my xaml, I want to display a full name in my DataGrid. So I created this Partial Class to return the full name and I display this property in the DataGrid. This works great. The FullName is displayed in the DataGrid as expected.

public partial class Employee
{
    public string FullName
    {
        get { return LastName.Trim() + ", " + FirstName.Trim(); }
    }
}

The problem I have is that my edit form has textboxes bound to the LastName and FirstName properties. When I update values such as CompanyName, LastName, FirstName, HireDate, etc... all the columns in the DataGrid that were changed get updated correctly, but the FullName property does NOT get updated.

Why doesn't my FullName partial class get updated while the rest of the DataGrid properties do get updated? How do I correct this?

Here is my editform xaml.

<TextBox Grid.Column="1" Name="txtCompany" Text="{Binding SelectedEmployee.Company, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Grid.Column="1" Name="txtFirstName" Text="{Binding SelectedEmployee.FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Grid.Column="1" Name="txtLastName" Text="{Binding SelectedEmployee.LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Grid.Column="1" Name="txtFullName" Grid.Row="2"  Margin="2" Text="{Binding SelectedEmployee.FullName" />    -- Also show as column in DataGrid
2
are you using property changed events?Kevin

2 Answers

2
votes

The change notification in WPF is done with the INotifyPropertyChanged interface.

It works out of the box with Entity Framework because the generated entities (by the default edmx template) implement this interface and the generated property setters fire the PropertyChanged event.

Your new property is not raising this event, but because it's calculated from LastName and FirstName when those two change you need to raise the PropertyChanged event.

Luckily EF will generate a partial method into each property setter with the name OnSomePropertyChanged from where you can raise the event:

public partial class Employee
{
    public string FullName
    {
        get { return LastName.Trim() + ", " + FirstName.Trim(); }
    }

    partial void OnLastNameChanged()
    {
         base.OnPropertyChanged("FullName");
    }

    partial void OnFirstNameChanged()
    {
         base.OnPropertyChanged("FullName");
    }
}
1
votes

Using a MultiBinding with an appropriate StringFormat would avoid any additional code behind and would be a more general solution in that it does not rely on what EF does. Note the funny notation of the format string with leading {}, which enables curly braces in a string in XAML:

<TextBlock Name="fullNameTextBlock">
    <TextBlock.Text>
        <MultiBinding StringFormat="{}{1}, {0}">
            <Binding Path="FirstName"/>
            <Binding Path="LastName"/>
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

A bit more complicated, but even more general approach would be to use a MultiBinding in conjunction with a IMultiValueConverter. You would create a MultiBinding like this:

<TextBlock Name="fullNameTextBlock">
    <TextBlock.Text>
        <MultiBinding Converter="{StaticResource FullNameConverter}">
            <Binding Path="FirstName"/>
            <Binding Path="LastName"/>
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

The converter would basically look like this:

public class FullNameConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((string)values[1]).Trim() + ", " + ((string)values[0]).Trim();
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}