I have two models in my data access layer: Table1 and Table2.
I want to use the WinUI 3 DataGrid from the CommunityToolkit to display two columns from each table: Table1.ColumnA, Table1.ColumnB, Table2.ColumnC, Table2.ColumnD
My thought was to use linq in my ViewModel class to join the enumerable from each model:
IEnumerable<Table1> table1 = unitOfWorkDbGlobal.Table1.GetAll().ToList();
IEnumerable<Table2> table2 = unitOfWorkDbGlobal.Table2.GetAll().ToList();
var JoinedTables = (from t1 in table1
join t2 in table2 on t1.TestGuid equals t2.TestGuid
select new
{ t1.ColumnA, t1.ColumnB,
t2.ColumnC, t2.ColumnD });
The problem that occurred with this approach is that I could create a CommunityToolkit.Mvvm [ObservableProperty]
with table1 or table2 as needed, but I cannot create an observable property with the join because I'm using a var type. When I use JoinedTables.GetType().Name
to determine the explicit type, it returns an Enumerable<JoinIterator>d__122 4
type, which appears to be computer gobbledygook unusable as a property type.
[ObservableProperty]
private ObservableCollection<Table1>? _table1Collection; //this works
[ObservableProperty]
private Enumerable<JoinIterator> d__122`4 _joinedTables; //Errors
How can the joined table be made into an ObservableProperty that can be bound in XAML to a CommunityToolkit DataGrid.
Here is an example of the XAML that I would like to use (note ViewModel
is assigned in the code-behind as the class with the code that I added above):
<controls:DataGrid x:Name="MyDataGrid"
AutoGenerateColumns="False"
ItemsSource="{x:Bind ViewModel.JoinedTables, Mode=OneWay}">
<controls:DataGrid.Columns>
<controls:DataGridTextColumn
Header="Column A"
Width="250"
Binding="{Binding ColumnA}"
FontSize="14" />
<controls:DataGridTextColumn
Header="Column B"
Width="250"
Binding="{Binding ColumnB}"
FontSize="14" />
<controls:DataGridTextColumn
Header="Column C"
Width="250"
Binding="{Binding ColumnC}"
FontSize="14" />
<controls:DataGridTextColumn
Header="Column D"
Width="250"
Binding="{Binding ColumnD}"
FontSize="14" />
</controls:DataGrid.Columns>
</controls:DataGrid>
CodePudding user response:
You need to create a type for the joined tables. Something like this.
ViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace DataGridTests;
public class Table1
{
public int Id { get; set; }
public string ColumnA { get; set; } = string.Empty;
public string ColumnB { get; set; } = string.Empty;
}
public class Table2
{
public int Id { get; set; }
public string ColumnC { get; set; } = string.Empty;
public string ColumnD { get; set; } = string.Empty;
}
public partial class JoinedTable : ObservableObject
{
[ObservableProperty]
private string columnA = string.Empty;
partial void OnColumnAChanged(string value)
{
// Update database.
}
public string ColumnB { get; set; } = string.Empty;
public string ColumnC { get; set; } = string.Empty;
public string ColumnD { get; set; } = string.Empty;
}
public partial class MainWindowViewModel : ObservableObject
{
[ObservableProperty]
private ObservableCollection<JoinedTable> joinedTables = new();
public MainWindowViewModel()
{
IEnumerable<JoinedTable> joinedTablesSource = Table1.Join(
Table2,
table1 => table1.Id,
table2 => table2.Id,
(table1, table2) => new JoinedTable()
{
ColumnA = table1.ColumnA,
ColumnB = table1.ColumnB,
ColumnC = table2.ColumnC,
ColumnD = table2.ColumnD,
});
JoinedTables = new ObservableCollection<JoinedTable>(joinedTablesSource);
}
private ObservableCollection<Table1> Table1 { get; set; } = new()
{
{new Table1() { Id = 1, ColumnA="Table1-A-1", ColumnB="Table1-B-1" } },
{new Table1() { Id = 2, ColumnA="Table1-A-2", ColumnB="Table1-B-2" } },
{new Table1() { Id = 3, ColumnA="Table1-A-3", ColumnB="Table1-B-3" } },
};
private ObservableCollection<Table2> Table2 { get; set; } = new()
{
{new Table2() { Id = 1, ColumnC="Table2-C-1", ColumnD="Table2-D-1" } },
{new Table2() { Id = 20, ColumnC="Table2-C-2", ColumnD="Table2-D-2" } },
{new Table2() { Id = 3, ColumnC="Table2-C-3", ColumnD="Table2-D-3" } },
};
}
.xaml
<toolkit:DataGrid ItemsSource="{x:Bind ViewModel.JoinedTables, Mode=OneWay}">
<toolkit:DataGrid.Columns>
<toolkit:DataGridTextColumn
Binding="{Binding ColumnA, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Header="A"
IsReadOnly="False" />
<toolkit:DataGridTextColumn
Binding="{Binding ColumnB}"
Header="B" />
<toolkit:DataGridTextColumn
Binding="{Binding ColumnC}"
Header="C" />
<toolkit:DataGridTextColumn
Binding="{Binding ColumnD}"
Header="D" />
</toolkit:DataGrid.Columns>
</toolkit:DataGrid>