'Property MyObject[] display in DataGrid
I have a DataGrid
. The DataGrid
gets filled with MyObject and displays its properties automatically. For most properties this works fine.
As an example, MyObject looks like this:
public class Transaction
{
public string Reference { get; set; }
public double Amount { get; set; }
public MainCategory ThisPropertyWorksFine { get; set; }
public TransactionTag[] ThisPropertyDoesnt { get; set; }
}
Notice that MainCategory
has an override .ToString()
. It gets displayed properly in the DataGrid
:
public override string ToString()
{
return this.Name;
}
TransactionTag
also has an override .ToString()
method but the DataGrid
only shows it's type:
The data has been added as such:
List<Transaction> TransactionList = fillMyList();
this.ImportPreview.AutoGenerateColumns = true;
this.ImportPreview.ItemsSource = TransactionList;
How can I make it, so that the DataGrid
shows the array content, for example separated by ,
?
Solution 1:[1]
How can I make it, so that the DataGrid shows the array content, for example separated by ,?
You could create a custom collection type that overrides ToString()
:
public class FormattableCollection<T> : ReadOnlyCollection<T>
{
public FormattableCollection(IList<T> list)
: base(list) { }
public override string ToString() =>
string.Join(",", this);
}
...and change the type of your property:
public FormattableCollection<TransactionTag> BindToThisOne { get; }
...
BindToThisOne = new FormattableCollection<TransactionTag>(ThisPropertyDoesnt);
Solution 2:[2]
The ThisPropertyDoesnt
property is of type TransactionTag[]
which is an array of TransactionTag
objects. You overrode the ToString
method of TransactionTag
, but not the array type, which you cannot change, see How to override ToString() in [] array? for reference.
You can create a custom value converter that concatenates the result of ToString()
of a collection of object
s using a predefined separator. The following converter exposes the separator as a property, which is useful to reuse a single instance with the same separator. You could alternatively pass it in as parameter
.
public class ConcatenateToStringConverter : IValueConverter
{
public string Separator { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return !(value is IEnumerable<object> objects) || Separator is null
? Binding.DoNothing
: string.Join(Separator, objects);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Without auto-generating columns, you would specify the converter in the Binding
of the column.
<DataGrid ItemsSource="{Binding Transactions}" AutoGenerateColumns="False">
<DataGrid.Resources>
<local:ConcatenateToStringConverter x:Key="ConcatenateStringConverter" Separator=", "/>
</DataGrid.Resources>
<!-- ...other columns. -->
<DataGrid.Columns>
<DataGridTextColumn Header="Transaction Tags" Binding="{Binding ThisPropertyDoesnt, Converter={StaticResource ConcatenateStringConverter}}"/>
</DataGrid.Columns>
</DataGrid>
With auto-generating columns, you would have to add a handler for the AutoGeneratingColumn
event and adapt column generation. You would identify the target column, get its binding and add the converter.
<DataGrid ItemsSource="{Binding Transactions}" AutoGenerateColumns="True" AutoGeneratingColumn="OnAutoGeneratingColumn"/>
private void OnAutoGeneratingColumn(object? sender, DataGridAutoGeneratingColumnEventArgs e)
{
if ( /* ...identify the target column here. */)
{
var dataGridTextColumn = (DataGridTextColumn)e.Column;
var binding = (Binding)dataGridTextColumn.Binding;
// It is favorable to reuse the same converter instance if you can.
binding.Converter = new ConcatenateToStringConverter { Separator = ", " };
}
}
Alternatively, you could create a separate model type that implements IEnumerable<TransactionTag>
and override ToString
there, but that is up to you and your requirements. For display only purposes, value converters are useful.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | mm8 |
Solution 2 |