I have a table that includes integers that are ids linking to another table. For example, one field may be called StatusId, has a value of 4 and looks at tblStatuses to find the matching record.
I created a WPF DataGrid to put this data into, all working.
I created a CollectionViewSource to store the records from tblStatuses, all working.
I created a CellTemplate and CellEditingTemplate to show the field and when editing, show a dropdown with the current status which can then be changed. All working.
Where I am now stuck is to show the current status in its lookup text value in the column in the celltemplate, instead of just the id. i.e. display 'Current' instead of 4.
I have tried using the same ComboBox method in CellTemplate and modifying the ComboBox Template to show a label but it shows the wrong value. I'm not sure what else to try at the moment and google/so aren't helping, mostly because this is a difficult one to search.
<DataGrid Name="grdLearners" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Surname}" Header="Surname" />
<DataGridTemplateColumn Header="Status">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding StatusID}"></TextBlock> // displays id i.e. 4, need to display text i.e. 'Current'
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding StatusID}" SelectedValuePath="Status_ID" DisplayMemberPath="Status" ItemsSource="{Binding Source={StaticResource StatusesList}}"></ComboBox> // displays list of statuses and correctly shows/sets the id in the row
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Hoping someone can shed some light on this or point me in the right direction. Let me know if you need any other code posted.
Code for Collection
<Window.Resources>
<CollectionViewSource x:Key="StatusesList" CollectionViewType="ListCollectionView"/>
</Window.Resources>
Code-behind for setting data/collection:
AppDb db = new AppDb();
var learners = db.Learners.AsNoTracking().Take(40).ToList();
var stats = db.StudentStatuses.AsNoTracking().ToList();
CollectionViewSource itemCollectionViewSource;
itemCollectionViewSource = (CollectionViewSource)(FindResource("StatusesList"));
itemCollectionViewSource.Source = stats;
var grid = grdLearners as DataGrid;
grid.ItemsSource = learners;
If you want to display the text, you should store it in your data object. You are currently only storing the id in the StatusID
property. If you add a Status
property to your data object, you could bind the SelectedItem
property of the ComboBox
in the CellEditingTemplate
to this one:
<TextBlock Text="{Binding Status.Status}"/>
...
<ComboBox SelectedItem="{Binding Status}" DisplayMemberPath="Status" ItemsSource="{Binding Source={StaticResource StatusesList}}" />
If you don't want to add another property to your data object, you could use a converter that looks up the value in the StatusesList
:
public class StatusConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
int statusId = (int)values[0];
IEnumerable<TheStatus> statuses = (IEnumerable<TheStatus>)values[1];
return statuses.FirstOrDefault(x => x.Status_ID == statusId)?.Status;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML:
<DataGridTemplateColumn Header="Status">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding>
<MultiBinding.Converter>
<local:StatusConverter />
</MultiBinding.Converter>
<Binding Path="StatusID" />
<Binding Path="SourceCollection" Source="{StaticResource StatusesList}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding StatusID}" SelectedValuePath="Status_ID" DisplayMemberPath="Status"
ItemsSource="{Binding Source={StaticResource StatusesList}}"></ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
Note that you need to change TheStatus
to whatever the name of your status type is in the converter.