1
votes

I have a DataGrid, with only one column (for the sake of this example). This column is a DataGridTemplateColumn:

<DataGrid x:Name="grdMainGrid">
    <DataGridTemplateColumn Header="Room" CanUserSort="True" SortMemberPath="DisplayText" >
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox ItemsSource="{Binding Path=AllRooms, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" Height="20" SelectedValuePath="Code" SelectedValue="{Binding Path=RoomCode, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="DisplayText" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
</DataGrid>

The DataGrid's ItemsSource is set to a List:

public class InsertableRecord
{
    public int RoomCode { get; set; }
}

The ComboBox's ItemsSource in the DataGridTemplateColumn is bound to a property in my Window:

public List<Room> AllRooms
{
    get;
    private set;
}

Here is the definition of the class "Room":

public partial class Room
{
    public string ID { get; set; }

    public string Description { get; set; }

    public string DisplayText
    {
        get
        {
            return this.ID + " (" + this.Description + ")";
        }
    }
}

Notice that I have my SortMemberPath set to DisplayText, which is a property of "Room", and not of "InsertableRecord". So obviously, I get a binding error when I try to sort this column saying the property "DisplayText" does not exist in the object "InsertableRecord".

How would I go about sorting the column based on the current Text of the ComboBox (or the DisplayText property of the "Room" object, both would work)?

1

1 Answers

1
votes

Ok, temporarly, I have created a small hack: I have created a new Property inside InsertableRecord called SelectedDisplayText.

public class InsertableRecord
{
    public int RoomCode { get; set; }
    public string SelectedDisplayText { get; set; }
}

I then changed my DataGrid column definition to:

<DataGrid x:Name="grdMainGrid">
    <DataGridTemplateColumn Header="Room" CanUserSort="True" **SortMemberPath="SelectedDisplayText"** >
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox ItemsSource="{Binding Path=AllRooms, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" Height="20" SelectedValuePath="Code" SelectedValue="{Binding Path=RoomCode, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="DisplayText" **Text="{Binding Path=SelectedDisplayText, Mode=OneWayToSource}"** />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
</DataGrid>

And now with this, every time I change the selection of my comboboxes, the new "Selected Text" of the combobox gets populated in the "SelectedDisplayText" of the InsertableRecord object, and the datagrid can then use it to sort according to that value.

Now this works, but it still feels like a hack. I would except that there could be a way to build a custom Sort that would somehow, through the data context of the row being processed, that I could get the related ComboBox of that row and extract its current text value... But that doesn't seem to be an option...

Any other proposition would be appreciated, as this is a pattern that I will be reusing through-out my application, and I would llike to make it as clean as possible to avoid having to rewrite repetetive code...