首页 > 技术文章 > WPF DataGrid的Converter获得每行的数据

Lulus 2020-06-04 20:33 原文

前端写法
获得每行的数据类对象,比如Employee

<Path Data="{Binding DataContext, RelativeSource={RelativeSource AncestorType=DataGridRow}, Converter={StaticResource MmsDataToPathConverter}}" />

获得DataGridRow

<Path Data="{Binding ., RelativeSource={RelativeSource AncestorType=DataGridRow}, Converter={StaticResource MmsDataToPathConverter}}" />

后端写法

/// <summary>
/// 设置操作列
/// </summary>
/// <param name="input"></param>
private void SetOperations()
{
    DataGridTemplateColumn dataGridTemplateColumn = new DataGridTemplateColumn();
    dataGridTemplateColumn.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
    dataGridTemplateColumn.Header = "操作";

    FrameworkElementFactory gridFactory = new FrameworkElementFactory(typeof(Grid));
    
    //修改按钮
    AddButton(gridFactory, 0, "修改", ModifyData, new ModifyVisibilityConverter());
    //删除按钮
    AddButton(gridFactory, 1, "删除", DeleteData, new DeleteVisibilityConverter());

    DataTemplate cellTemplate1 = new DataTemplate();
    cellTemplate1.VisualTree = gridFactory;
    dataGridTemplateColumn.CellTemplate = cellTemplate1;
    dataGrid.Columns.Add(dataGridTemplateColumn);
}

private static void AddButton(FrameworkElementFactory gridFactory, int i, string content, RoutedEventHandler routedEventHandler, IValueConverter valueConverter)
{
    FrameworkElementFactory col1 = new FrameworkElementFactory(typeof(ColumnDefinition));
    col1.SetValue(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Star));
    gridFactory.AppendChild(col1);

    //https://stackoverflow.com/questions/47401286/how-to-pro-gramatically-add-click-event-to-frameworkelementfactory
    FrameworkElementFactory btn1Factory = new FrameworkElementFactory(typeof(Button));
    btn1Factory.SetValue(Button.ContentProperty, content);
    btn1Factory.AddHandler(Button.ClickEvent, routedEventHandler);
    //绑定数据源
    var bind = new Binding("DataContext");
    //绑定每一行的数据
    //https://stackoverflow.com/questions/39873228/how-to-bind-to-wpf-datagrid-row-class-instance-and-not-its-property
    bind.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor) { AncestorType = typeof(DataGridRow) };
    //设置成自定义Converter
    bind.Converter = valueConverter;
    //判断该按钮是否应该存在
    btn1Factory.SetBinding(Button.VisibilityProperty, bind);

    btn1Factory.SetValue(Grid.ColumnProperty, i);
    gridFactory.AppendChild(btn1Factory);
}

在Converter中获得数据

public class DeleteVisibilityConverter : IValueConverter
{
    //当值从绑定源传播给绑定目标时,调用方法Convert
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var data = value as FakeDatabase;
        if (data.Id % 2 == 0)
        {
            return Visibility.Visible;
        }
        return Visibility.Collapsed;
    }
    //当值从绑定目标传播给绑定源时,调用此方法ConvertBack
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new Exception("");
    }
}

效果是单行只有删除按钮,双行只有修改按钮

示例代码

Converters

参考资料

How to bind to WPF DataGrid row class instance and not it's property?

推荐阅读