在数据网格行中每列分隔 object

Seperate object per column in a datagrid row

我有一个来自 SCADA 软件的数据网格,我正在通过创建可用于更多用例的自定义用户控件在 WPF 中重新创建它。我有一个 SettingRow 类型的可观察 collection,它包含 one 单元格的数据。问题是它不包含一个单元格的数据。

如果我的 collection 中有 10 个项目,那么我在第 1 行第 3 列中看不到单独的项目。我在例如第 1 行第 2 列中看到相同的项目。简而言之:无论我 select 连续在哪一列,我都看到相同的 SettingRow object。

每个单元格都是一个单独的设置 object,绑定到 DataTemplateSelector 到 select 适当的数据模板以显示值(布尔值作为复选框,字符串和值作为文本框等)

我创建了一个具有模板select或基于 SettingRow class 中的值的 DataGrid。数据网格的项目源当前绑定到我的视图模型中的 ObservableCollection。它有效,我在每行的每个单元格中看到每个 SettingRow,但我很确定我在每一列中看到相同的 SettingRow,它不是独立于 object 的单独 object在那一列之前。

我在 Whosebug 上尝试了一些解决方案,在可观察对象 collection 中使用可观察对象 collection,但我并没有真正让它工作。

下面是每行显示的 class。 object 是否被复制到下一列?还是每一列都一样 object re-used?

public class SettingRow : ObservableObject
{

    public int ID { get; set; }

    public object Value { get; set; }

    public string Name { get; set; }

    public string Unit { get; set; }

}

我在 XAML 中的数据网格已声明,但只有名称 属性。其余通过代码添加。

<DataGrid x:Name="OverviewDataGridView" ItemsSource="{Binding SettingsCollection, Mode=TwoWay}" AutoGenerateColumns="True">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}">

            </DataGridTextColumn>
        </DataGrid.Columns>  

下面我为每个阶段创建一个列。这 4 个阶段是模拟的,因为我没有实际数据。现在,每个 SettingRow 都应该是单独可编辑的,我需要从 ViewModel 中检索它。

这在后面的代码中。

public void GenerateColumns()
    {
        //Simulate 4 phases  and adding a column per phase!
        for(int i = 0; i < 4; i++)
        {
            DataGridTemplateColumn templateCol = new DataGridTemplateColumn();
            templateCol.Header = "Phase " + i;

            TemplateSelector templateSel = new TemplateSelector();
            templateSel.BooleanTemplate = this.Resources["BooleanTemplate"] as DataTemplate;
            templateSel.TextTemplate = this.Resources["TextTemplate"] as DataTemplate;

            templateCol.CellTemplateSelector = templateSel;

            this.OverviewDataGridView.Columns.Add(templateCol);
        }

}

ViewModel 非常简单,它创建了一些测试数据。创建的每个 SettingRow 都显示在每一列中,但我想我在每个

中看到相同的 object
public class DynamicDataGridViewModel : ObservableObject
{
    private ObservableCollection<SettingRow> settingsCollection;
    public ObservableCollection<SettingRow> SettingsCollection
    {
        get { return settingsCollection; }
        set
        {
            settingsCollection = value;
            RaisePropertyChangedEvent("SettingsCollection");
        }
    }


    public DynamicDataGridViewModel()
    {
        SettingsCollection = new ObservableCollection<SettingRow>();
        SettingsCollection.Add(new SettingRow() { ID = 0, Name = "Phase Active", Value = true, Unit = "" });
        SettingsCollection.Add(new SettingRow() { ID = 1, Name = "Minimum phase duration", Value = +900, Unit = "s" });
        SettingsCollection.Add(new SettingRow() { ID = 2, Name = "Min Supply air temperature", Value = 50.0302, Unit = "C" });
    }

}

最后,我的 DataTemplateSelector。它只处理 SettingRow 的值并显示正确的符号(boolean = checkbox 等)

public class TemplateSelector : DataTemplateSelector
{
    public DataTemplate BooleanTemplate { get; set; }

    public DataTemplate TextTemplate { get; set; }

    public SettingRow Content { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        ContentPresenter presenter = container as ContentPresenter;
        DataGridCell cell = presenter.Parent as DataGridCell;
        SettingRow row = (cell.DataContext as SettingRow); 

        if(row != null && row.Value != null)
        {
            this.Content = row;

            switch (Type.GetTypeCode(row.Value.GetType()))
            {
                case TypeCode.Boolean:
                    return BooleanTemplate;
                default:
                    return TextTemplate;
            }
        }
        else
        {
            return null;
        }
    }
}

编辑:

以下各栏的模板

<DataTemplate x:Key="BooleanTemplate">
            <StackPanel Orientation="Horizontal" Margin="2">
                <CheckBox IsChecked="{Binding Value}"/>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="TextTemplate">
            <StackPanel Orientation="Horizontal" Margin="2">
            <TextBox Height="25" MinWidth="70" FontSize="14">
                <TextBox.Text>
                    <MultiBinding StringFormat="{}{0} {1}">
                        <Binding Path="Value" Mode="TwoWay"/>
                        <Binding Path="Unit"  Mode="TwoWay"/>
                    </MultiBinding>
                </TextBox.Text>
            </TextBox>
        </StackPanel>
        </DataTemplate>

我需要的是绑定到可观察对象的 DataGrid collection。它具有动态数量的列(代表一个阶段),我需要在每一列中有一个 SettingRow 并且它可以根据 object 进行编辑。例如,我可以将调平阶段中的阶段持续时间设置的可见性设置为不可见。

编辑 2:

我的想法是在一个可观察对象 collection 中使用一个可观察对象 collection 就像下面的代码片段这样我可以将我的数据表示为每一行中的列。这样我就可以访问每一行和每一列个人 object.:

 private ObservableCollection<ObservableCollection<SettingRow>> items;
    public ObservableCollection<ObservableCollection<SettingRow>> ItemsSourceOfDataGrid
    {
        get { return items; }
        set
        {
            items = value;
            RaisePropertyChangedEvent("ItemsSourceOfDataGrid")
        }
    }

编辑:因此,在查看了评论和您想要的内容之后,最简单的事情就是定义所有行名称,然后让 ObservableCollection 成为列而不是行的集合。如果您想走动态行和列的疯狂路线,那么这些可以帮助您入门:

https://svitla.com/blog/grid-with-dynamic-number-of-rows-and-columns-part-1 https://svitla.com/blog/grid-with-dynamic-number-of-rows-and-columns-part-2

来源Github:https://github.com/IReznykov/Blog

因此,使用动态列的方法非常简单。

重申一下:

确保您的 RaisePropertyChangedEvent 已添加到模型中的项目中。这将允许它们在您的 SettingsCollection 中动态更改。此外,您的 DataGrid 的 XAML 部分需要以某种方式设置才能使用此功能。

public class SettingColumn : ObservableObject
{
    public int _PhaseNumber;
    public int PhaseNumber
    {
        get { return _PhaseNumber; }
        set
        {
            PhaseNumber = value;
            RaisePropertyChangedEvent("PhaseNumber");
        }
    }

    public object _MinPhaseDuration;
    public object MinPhaseDuration
    {
        get { return _Value; }
        set
        {
            Value = value;
            RaisePropertyChangedEvent("Value");
        }
    }

    public string _MinSupplyAirTemp;
    public string MinSupplyAirTemp
    {
        get { return _MinSupplyAirTemp; }
        set
        {
            MinSupplyAirTemp = value;
            RaisePropertyChangedEvent("MinSupplyAirTemp");
        }
    }

    // The rest of your row labels here.
    .
    .
    .

希望此编辑对您有所帮助。同样,动态行和列很痛苦。为自己省去一些麻烦并定义所有行标签或列标签。