【问题标题】:Data Binding a DataGrid to an Object with Nested Classes将 DataGrid 数据绑定到具有嵌套类的对象
【发布时间】:2016-12-07 20:10:23
【问题描述】:

所以我有一个运行查询并返回 JSON 响应的 api 调用。由于 JSON 响应的结构,我创建了一个类,我可以使用 Json.Net 将返回直接反序列化。这是示例类:

public class QuerySet
{
    public List<Column> Columns { get; set; }
    public class Column
    {
        public List<string> Name { get; set; }
    }
    public List<RowSet> Rows { get; set; }
    public class RowSet
    {
        public List<DataSet> Row { get; set; }
        public class DataSet
        {
            public List<string> Data { get; set; }
        }
    }
}

现在,单个 API 调用可以包含多个查询集,因此对于每个返回,我生成一个查询集列表,然后我想将 DataGrid 数据绑定到每个集。这是我目前在窗口后面的代码中的一个示例:

    public List<DataGrid> QueryResults;

    public QueryResultsWindow(string _name, JObject _returns)
    {
        InitializeComponent();
        QueryNameText.Text = _name;
        QueryResults = new List<DataGrid>();

        JArray sets = (JArray)_returns.SelectToken("$..Set");

        foreach(JObject set in sets)
        {
            DataGrid dg = new DataGrid();
            QuerySet s = new QuerySet();
            s = JsonConvert.DeserializeObject<QuerySet>(set.ToString());

            dg.ItemsSource = s.Rows;

            QueryResults.Add(dg);
        }

        ResultsListBox.ItemsSource = QueryResults;
    }

您可能会看到这里的问题是,对于每个特定的 DataGrid,我希望将列标题绑定到 Name 属性,并从 Data 属性填充数据。

这是我目前在窗口中设置 XAML 的方式:

   <DockPanel>
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" VerticalAlignment="Top">
            <TextBlock x:Name="QueryNameText" Margin="5"></TextBlock>
            <Button Content="Export Results" Click="Button_Click" Margin="5"></Button>
        </StackPanel>
        <ListBox DockPanel.Dock="Top" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="3" Name="ResultsListBox">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <DataGrid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}" CanUserAddRows="False" IsReadOnly="True" SelectionUnit="Cell">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="{Binding Name}"></DataGridTextColumn>
                        </DataGrid.Columns>
                    </DataGrid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </DockPanel>

我知道,如果我想为每种可能的返回类型创建一个自定义类,这会容易得多。然而,考虑到数百种潜在的回报类型,这似乎不太可行。我尝试过使用 DataTables,我尝试过在 XAML 中的 ListBox 中设置 DataGrid,但我可能没有正确实现这一点,最后解决了尝试创建 DataGrids 列表然后绑定到这些的解决方案。

我需要一些帮助。

谢谢!

【问题讨论】:

    标签: c# json wpf xaml datagrid


    【解决方案1】:

    在搞砸了这个之后。这是我想出的答案。

    我取了上面的查询集类,在QuerySet类里面添加了一个构建DataTable的方法:

       public class QuerySet
        {
            public DataTable BindableTable { get; private set; }
            public static List<string> ColumnName { get; private set; }
            public static List<RowSet.DataSet> RowsSet { get; private set; }
    
            public List<Column> Columns { get; set; }
            public class Column
            {
                private List<string> _name;
    
                public List<string> Name
                {
                    get { return _name; }
                    set { _name = value; ColumnName = _name; }
                }
    
    
            }
            public List<RowSet> Rows { get; set; }
    
            public class RowSet
            {
                private List<DataSet> _row;
    
                public List<DataSet> Row
                {
                    get { return _row; }
                    set { _row = value; RowsSet = _row; }
                }
    
                public class DataSet
                {
                    public List<string> Data { get; set; }
                }
            }
    
            public void GetDataGridTable()
            {
                DataTable table = new DataTable();
                foreach(string name in ColumnName)
                {
                    table.Columns.Add(name);
                }
                foreach(RowSet.DataSet set in RowsSet)
                {
                    DataRow row = table.NewRow();
                    int counter = 0;
                    foreach(string item in set.Data)
                    {
                        row[counter] = item;
                        counter++;
                    }
                    table.Rows.Add(row);
                }
    
                BindableTable = table;
            }
        }
    

    我添加了几个访问器以更轻松地访问嵌套位,并从那里构建了一个 DataTable。在弹出窗口后面的代码中,我创建了一个可观察的 DataGrid 集合,并根据 QuerySet 将每个 Grid 的 DataContext 设置为一个 DataView:

        public ObservableCollection<DataGrid> QueryResults;
        public event PropertyChangedEventHandler PropertyChanged;
    
        public QueryResultsWindow(string _name, JObject _returns)
        {
            InitializeComponent();
            QueryNameText.Text = _name;
            QueryResults = new ObservableCollection<DataGrid>();
    
            JArray sets = (JArray)_returns.SelectToken("$..Set");
    
            foreach(JObject set in sets)
            {
                DataGrid dg = new DataGrid();
                QuerySet s = new QuerySet();
                s = JsonConvert.DeserializeObject<QuerySet>(set.ToString());
    
                s.GetDataGridTable();
                DataView newView = new DataView(s.BindableTable);
                dg.ItemsSource = newView;
                dg.CanUserAddRows = false;
                dg.CanUserDeleteRows = false;
                QueryResults.Add(dg);
            }
    
            ResultsListBox.ItemsSource = QueryResults;
        }
    

    然后我的弹出窗口中的 XAML 非常简单:

    <DockPanel>
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" VerticalAlignment="Top">
            <TextBlock x:Name="QueryNameText" Margin="5"></TextBlock>
            <Button Content="Export Results" Click="Button_Click" Margin="5"></Button>
        </StackPanel>
        <ListBox DockPanel.Dock="Top" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="3" Name="ResultsListBox" ItemsSource="{Binding QueryResults}">
        </ListBox>
    </DockPanel>
    

    显然这不是最优雅的解决方案。即使只是在这里查看它,我也可以轻松地在 QuerySet 类中创建 DataView,而不是在后面的代码中进行转换。因此,虽然答案并不完美,但它目前正在发挥作用。

    【讨论】:

      猜你喜欢
      • 2012-05-27
      • 2019-04-01
      • 2017-05-14
      • 2011-08-22
      • 1970-01-01
      • 2020-08-14
      • 2014-08-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多