为什么 DataGridTextColumn 的绑定 ObservableCollection 没有更新?

Why is DataGridTextColumn's bound ObservableCollection is not updated?

在我的 XAML 中,我定义了一个包含 DataGridTextXolumns 的 DataGrid。所有 simple 列都能很好地更新源 (ObservableCollection),但不是 List<string> 字段的源字段。我在 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>

更新列 'Op' 工作正常但 'DetailParams' 不行。

这里是使用的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);
    }
}

UserControl的DataSource定义如下:

    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();
    }
    ...
}

Notification.DetailParams 的类型为 List<string> 并且您想将其转换为单个 string 以进行显示和编辑时,转换器应如下所示:

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(','));
    }
}

如果将 属性 类型更改为 IEnumerable<string>,则可以将 ConvertBack 方法简化为直接 return string[] return 由 String.Split:

public object ConvertBack(
    object value, Type targetType, object parameter, CultureInfo culture)
{
    return ((string)value).Split(',');
}