0

The DataTable is populated with the data from a database.

 var query = $"SELECT * FROM {databaseTable.Name}";
 OracleCommand oracleCommand = new OracleCommand(query, _connection);
 OracleDataAdapter oracleDataAdapter = new OracleDataAdapter(oracleCommand);
 DataTable data = new DataTable();
 oracleDataAdapter.Fill(data);
 return data;

I want to populate a DataGrid with the DataTable trough Itemssource. We don't want to specify any objects (classes). We want to fill the Grid with only the informations we get from the DataTable

<control:DataGrid x:Name="gridView1" Margin="5" ItemsSource="{Binding DataTable}" GridLinesVisibility="All" AlternatingRowBackground="DarkBlue">

At the moment I have a ListView that shows me all the Tables that we read out separately from the database

 <ListView x:Name="listView" ItemsSource="{Binding DatabaseTables, Mode=TwoWay}" DisplayMemberPath="Name" SelectedItem="{Binding DatabaseTable, Mode=TwoWay}">

and by selecting a table we want all the entries shown in the Grid with the expecting columns from the DataTable

I tried to look around, but couldn't find a solution.

1
  • You can expose the DataTable as a property of your page, and it should return the DataTable, selected in the Combo. Of course, the property must implement INotifyPropertyChange, and the Binding must be OneWay. Commented Feb 23, 2024 at 15:16

1 Answer 1

0

This should work:

MainPageViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using System.Data;
using System.Threading.Tasks;

namespace DataTableExample;

// This class needs to be "partial" 
// for the CommunityToolkit.NuGet package source generators.
public partial class  MainPageViewModel : ObservableObject
{
    [ObservableProperty]
    // "Items" property will be auto-generated for you.
    private ObservableCollection<object>? _items;

    [RelayCommand]
    // "LoadItemsCommand" will be auto-generated for you.
    private async Task LoadItems()
    {
        DataTable dataTable = await LoadItemsFromDataBase();

        ObservableCollection<object> items = new();

        foreach (DataRow row in dataTable.Rows)
        {
            items.Add(row.ItemArray);
        }

        Items = items;
    }

    private Task<DataTable> LoadItemsFromDataBase()
    {
        return Task.Run(() =>
        {
            DataTable dataTable = new();
            dataTable.Columns.Add("Id", typeof(int));
            dataTable.Columns.Add("Name", typeof(string));
            dataTable.Columns.Add("Price", typeof(decimal));
            dataTable.Rows.Add(1, "Product 1", 10.0);
            dataTable.Rows.Add(2, "Product 2", 20.0);
            dataTable.Rows.Add(3, "Product 3", 30.0);
            return dataTable;
        });
    }
}

MainPage.xaml.cs

using Microsoft.UI.Xaml.Controls;

namespace DataTableExample;
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
    }

    private MainPageViewModel ViewModel => new();
}

MainPage.xaml

<Page
    x:Class="DataTableExample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:DataTableExample"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:toolkit="using:CommunityToolkit.WinUI.UI.Controls"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    mc:Ignorable="d">

    <Grid RowDefinitions="Auto,*">
        <Button
            Grid.Row="0"
            Command="{x:Bind ViewModel.LoadItemsCommand}"
            Content="Load items" />
        <toolkit:DataGrid
            Grid.Row="1"
            AutoGenerateColumns="False"
            ItemsSource="{x:Bind ViewModel.Items, Mode=OneWay}">
            <toolkit:DataGrid.Columns>
                <toolkit:DataGridTextColumn
                    Binding="{Binding [0]}"
                    Header="ID" />
                <toolkit:DataGridTextColumn
                    Binding="{Binding [1]}"
                    Header="Name" />
                <toolkit:DataGridTextColumn
                    Binding="{Binding [2]}"
                    Header="Price" />
            </toolkit:DataGrid.Columns>
        </toolkit:DataGrid>
    </Grid>

</Page>

NOTE:

I'm using the CommunityToolkit.Mvvm NuGet package for the MVVM design.

UPDATE:

I came up with another solution that might be a bit closer to your requirements. This way you won't need to declare each column in XAML.

DataGridExtensions.cs

using CommunityToolkit.WinUI.UI.Controls;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
using System.Collections.ObjectModel;

namespace DataTableExample;

public static class DataGridExtensions
{
    public static readonly DependencyProperty ColumnsProperty =
        DependencyProperty.RegisterAttached(
            "Columns",
            typeof(ObservableCollection<Column>),
            typeof(DataGridExtensions),
            new PropertyMetadata(
                new ObservableCollection<Column>(),
                OnColumnsPropertyChanged));

    public static ObservableCollection<Column> GetColumns(DependencyObject obj)
    {
        return (ObservableCollection<Column>)obj.GetValue(ColumnsProperty);
    }

    public static void SetColumns(DependencyObject obj, ObservableCollection<Column> value)
    {
        obj.SetValue(ColumnsProperty, value);
    }

    private static void OnColumnsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is not DataGrid dataGrid ||
            e.NewValue is not ObservableCollection<Column> columns)
        {
            return;
        }

        dataGrid.Columns.Clear();

        foreach (Column column in columns)
        {
            Binding binding = new()
            {
                Path = new PropertyPath(column.Binding)
            };

            dataGrid.Columns.Add(
                new DataGridTextColumn
                {
                    Header = column.Header,
                    Binding = binding,
                });
        }
    }

    public class Column
    {
        public string? Header { get; set; }

        public string? Binding { get; set; }
    }
}

MainPageViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using System.Data;
using System.Threading.Tasks;

namespace DataTableExample;

public partial class  MainPageViewModel : ObservableObject
{
    [ObservableProperty]
    private ObservableCollection<object>? _items;

    [ObservableProperty]
    private ObservableCollection<DataGridExtensions.Column>? _columns;

    [RelayCommand]
    private async Task LoadItems()
    {
        DataTable dataTable = await LoadItemsFromDataBase();

        ObservableCollection<DataGridExtensions.Column> columns = new();
        ObservableCollection<object> items = new();

        int index = 0;

        foreach (DataColumn column in dataTable.Columns)
        {
            columns.Add(
                new DataGridExtensions.Column {
                    Header = column.ColumnName,
                    Binding = $"[{index++}]"
                });
        }

        foreach (DataRow row in dataTable.Rows)
        {
            items.Add(row.ItemArray);
        }

        Columns = columns;
        Items = items;
    }

    private Task<DataTable> LoadItemsFromDataBase()
    {
        return Task.Run(() =>
        {
            DataTable dataTable = new();
            dataTable.Columns.Add("Id", typeof(int));
            dataTable.Columns.Add("Name", typeof(string));
            dataTable.Columns.Add("Price", typeof(decimal));
            dataTable.Rows.Add(1, "Product 1", 10.0);
            dataTable.Rows.Add(2, "Product 2", 20.0);
            dataTable.Rows.Add(3, "Product 3", 30.0);
            return dataTable;
        });
    }
}

and...

MainPage.xaml

<Page
    x:Class="DataTableExample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:DataTableExample"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:toolkit="using:CommunityToolkit.WinUI.UI.Controls"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    mc:Ignorable="d">

    <Grid RowDefinitions="Auto,*">
        <Button
            Grid.Row="0"
            Command="{x:Bind ViewModel.LoadItemsCommand}"
            Content="Load items" />
        <toolkit:DataGrid
            Grid.Row="1"
            local:DataGridExtensions.Columns="{x:Bind ViewModel.Columns, Mode=OneWay}"
            AutoGenerateColumns="False"
            ItemsSource="{x:Bind ViewModel.Items, Mode=OneWay}" />
    </Grid>

</Page>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.