Почему связанная с DataGridTextColumn привязка ObservableCollection не обновляется? - PullRequest
0 голосов
/ 06 января 2019

В моем XAML я определил DataGrid, содержащий DataGridTextXolumns. Все простые столбцы корректно обновляют источник (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 определяется следующим образом:

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

1 Ответ

0 голосов
/ 06 января 2019

Когда 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 для непосредственного возврата string[], возвращаемого String.Split:

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