In my XAML I have definde a DataGrid containing DataGridTextXolumns. All of the simple columns updates the source (ObservableCollection) well, but not the source field which is a List<string>
field. What am I missing to define in the XAML?
<UserControl x:Class="MyTool.MyTabItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<DataGrid x:Name="notificationsGrid" ItemsSource="{Binding}"
AlternatingRowBackground="LightBlue" AutoGenerateColumns="False" CanUserAddRows="True" IsReadOnly="False"
SelectionMode="Single" BorderThickness="3" Unloaded="DataGrid_Unloaded" >
<DataGrid.Columns>
<DataGridTextColumn Header="Op" Binding="{Binding Mode=TwoWay, Path=Notification.Op}">
<DataGridTextColumn Header="DetailParams" Binding="{Binding Path=Notification.DetailParams, Mode=TwoWay,
Converter={StaticResource StringListConverter}, UpdateSourceTrigger=LostFocus}">
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
</Grid>
</UserControl>
Updating of column 'Op' works fine but 'DetailParams' not.
Here's the code of the used StringToListConverter:
public class StringToListConverter : IValueConverter
{
/// <summary>
/// Converts a comma separated string into a List<string>.
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if( value is string)
{
return value;
}
Console. WriteLine("DetailParams: " + string.Join(",", ((List<string>)value)));
return string.Join(",", (List<string>)value);
}
/// <summary>
/// Converts a List<string> into a comma separated string.
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
Console.WriteLine(string.Join(",", value));
return string.Join(",", value);
}
}
The DataSource of the UserControl is defined as follows:
public partial class RawNotificationTabItem : UserControl//, INotifyPropertyChanged
{
private ObservableCollection<RawNotificationRowViewModel> _notifications { get; set; }
//public StringToBoolConverter StringToBoolConverter {
// get { return StringToBoolConverter; }
// set { StringToBoolConverter = value; }
//}
public RawNotificationTabItem(ObservableCollection<RawNotificationRowViewModel> rnvm)
{
_notifications = rnvm == null ? _notifications = new ObservableCollection<RawNotificationRowViewModel>() : rnvm;
this._notifications = rnvm;
DataContext = _notifications;
InitializeComponent();
}
...
}
When Notification.DetailParams
is of type List<string>
and you want to convert it to a single string
for display and editing, the converter should look like this:
public class StringListToStringConverter : IValueConverter
{
public object Convert(
object value, Type targetType, object parameter, CultureInfo culture)
{
return string.Join(",", (IEnumerable<string>)value);
}
public object ConvertBack(
object value, Type targetType, object parameter, CultureInfo culture)
{
return new List<string>(((string)value).Split(','));
}
}
If you change the property type to IEnumerable<string>
, you can simplify the ConvertBack method to directly return the string[]
returned by String.Split
:
public object ConvertBack(
object value, Type targetType, object parameter, CultureInfo culture)
{
return ((string)value).Split(',');
}