如何为 DataGrid 中动态创建的列创建绑定?

问题描述 投票:0回答:1

我正在从事 WPF 应用程序开发。我们的对话框之一有一个 DataGrid。此 DataGrid 应显示有关某些 3D 点的信息。对于这一点,我们有一个 PointViewModel 类,它具有 4 个必需的主要属性 - Name、X、Y、Z:

public class PointViewModel : ViewModelBase
{
    public string Name
    {
        get => _name;
        set
        {
            _name = value;
            NotifyPropertyChanged(nameof(Name));
        }
    }

    public double X
    {
        get => _x;
        set
        {
            _x = value;
            NotifyPropertyChanged(nameof(X));
        }
    }

    public double Y
    {
        get => _y;
        set
        {
            _y = value;
            NotifyPropertyChanged(nameof(Y));
        }
    }

    public double Z
    {
        get => _z;
        set
        {
            _z = value;
            NotifyPropertyChanged(nameof(Z));
        }
    }

    public ObservableCollection<PointCustomPropViewModel> CustomProperties => _customProperties;

    public PointViewModel(string name, double x, double y, double z)
    {
        // in the real code this collection is empty at the beginning, but for the test I added 2 custom properties where I just "know" their names and values.
        _customProperties = new ObservableCollection<PointCustomPropViewModel>()
        {
            new PointCustomPropViewModel("Test Prop 1", "Hello"),
            new PointCustomPropViewModel("Test Prop 2", "World"),
        };

        Name = name;
        X = x;
        Y = y;
        Z = z;
    }

    private readonly ObservableCollection<PointCustomPropViewModel> _customProperties;
    private string _name;
    private double _x;
    private double _y;
    private double _z;


}

每个点还可以有一些自定义属性。当应用程序刚启动时,我们不知道有关这些属性的任何信息,因此应该动态创建它们。对于这些自定义属性,每个点都有一个 CustomProperties 集合。每个 PointCustomPropViewModel 都有有关属性名称和属性值的信息,仅此而已:

public class PointCustomPropViewModel : ViewModelBase
{
    public string PropName
    {
        get => _propName;
        set
        {
            _propName = value;
            NotifyPropertyChanged(nameof(PropName));
        }
    }

    public string PropValue
    {
        get => _propValue;
        set
        {
            _propValue = value;
            NotifyPropertyChanged(nameof(PropValue));
        }
    }

    public PointCustomPropViewModel(string propName, string propValue)
    {
        PropName = propName;
        PropValue = propValue;
    }

    private string _propName;
    private string _propValue;
}

在这里,我为主对话框创建了一个测试视图模型,它仅创建具有一些随机参数的点的集合:

public class MainWindowViewModel : ViewModelBase
{
    public ObservableCollection<PointViewModel> Points => _points;

    public ICollectionView PointsView => _pointsView;

    public MainWindowViewModel()
    {
        _points = new ObservableCollection<PointViewModel>();
        _pointsView = CollectionViewSource.GetDefaultView(_points);

        Initialize();
    }

    private void Initialize()
    {
        var _random = new Random();

        for (int _i = 0; _i < 3; _i++)
        {
            double _randomX = _random.NextDouble();
            double _randomY = _random.NextDouble();
            double _randomZ = _random.NextDouble();

            _points.Add(new PointViewModel($"Point {_i}", _randomX, _randomY, _randomZ));
        }

        NotifyPropertyChanged(nameof(PointsView));
    }

    private readonly ObservableCollection<PointViewModel> _points;
    private readonly ICollectionView _pointsView;
}

所以这里我创建了3个测试点,每个点还有2个自定义属性。当用户在对话框上执行某些操作时,可以随时添加或删除自定义属性。在开始的任何时候,我们都不知道这些自定义属性的实际数量、名称和值。

但是我们的 DataGrid 应该显示有关所有点的信息,包括有关自定义属性的信息,并且可以编辑每个主要或自定义属性的值。因此,例如,我有一些测试 XAML 代码,其中创建了一个 DataGrid,添加了与 PointsView 属性的 ItemSource 的绑定,以及 PointViewModel 对象中主要 4 列和主要属性之间的绑定:

<DataGrid AutoGenerateColumns="False"
          ItemsSource="{Binding PointsView}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name"
                            Width="150"
                            Binding="{Binding Name}"/>
        <DataGridTextColumn Header="X"
                            Width="75"
                            Binding="{Binding X}"/>
        <DataGridTextColumn Header="Y"
                            Width="75"
                            Binding="{Binding Y}"/>
        <DataGridTextColumn Header="Z"
                            Width="75"
                            Binding="{Binding Z}"/>
    </DataGrid.Columns>
</DataGrid>

它给了我下一个对话框:

但是如何基于集合生成新列,并为每个点绑定到 CustomProperties 集合中的 Value 属性?例如,我的点有新的自定义属性“Test Prop 1”,该属性的值为“Hello”。因此,我应该生成一个标题为“Test Prop 1”的新列,并且该列中的每一行都应显示相关点的值(在本例中,值将为“Hello”)。例如,当我尝试编辑第一行中此列中的值并将其更改为“Hi”时,它应该在集合点中找到第一个对象,在中找到名称属性 =“Test Prop 1”的 PointCustomPropViewModel 对象其集合 CustomProperties 并将 Value 属性从“Hello”更新为“Hi”。

c# wpf datagrid
1个回答
0
投票

您需要以某种方式动态生成列,例如根据源集合中第一个

PointCustomPropViewModel
中的
PointViewModel
项目的数量:

var pointViewModel = viewModel.Points[0];
foreach (var customProperty in pointViewModel.CustomProperties)
    dataGrid.Columns.Add(new DataGridTextColumn()
    {
        Header = customProperty.PropName,
        Binding = new Binding(customProperty.PropName)
    });
© www.soinside.com 2019 - 2024. All rights reserved.