Binding DataGrid to DataTable. DataGrid's ItemSource is null on first load. - WPF

I'm trying to bind a DataGrid to a DataTable located in my viewmodel. The columns are dynamic hence why I'm binding to a DataTable and adding the columns and rows in the viewmodel. The relevant VM code looks like:
private DataTable _data;
public DataTable Data
{
get => _data;
set
{
_data = value;
OnPropertyChanged();
}
}

// called in VM's constructor. Also tried calling it in the view's code-behind in loaded event.
public void LoadData()
{
Data = new DataTable();
Data.BeginLoadData();

// adding columns using Data.Columns.Add
// adding rows using Data.Rows.Add

Data.EndLoadData();
}
private DataTable _data;
public DataTable Data
{
get => _data;
set
{
_data = value;
OnPropertyChanged();
}
}

// called in VM's constructor. Also tried calling it in the view's code-behind in loaded event.
public void LoadData()
{
Data = new DataTable();
Data.BeginLoadData();

// adding columns using Data.Columns.Add
// adding rows using Data.Rows.Add

Data.EndLoadData();
}
Now the viewmodel is created before the view, and the view's datacontext is set to the viewmodel when the view is created. The xaml for the DataGrid is:
<DataGrid
x:Name="AttributesGrid"
IsReadOnly="True"
ItemsSource="{Binding Data, IsAsync=True}"/>
<DataGrid
x:Name="AttributesGrid"
IsReadOnly="True"
ItemsSource="{Binding Data, IsAsync=True}"/>
There are certain columns I need to hide based on a list of strings in the VM. So I checked in both the View's Loaded event and the DataGrid's Loaded event, and in both cases the ItemSource is null, so I can't access the columns to hide them. Why would it be null if it is bound to the DataTable in the vm?
2 Replies
SpReeD
SpReeD7mo ago
The OnPropertyChanged is called on Data = new DataTable(); which is an blank/empty DataTable, afterwards it isn't called; afaik DataTable doesn't implement an observable, so you have to call OnPropertyChanged manually or, set the Data property at the end, after your DataTable is ready. Also use the name parameter of the method; I guess you implemented it manually like so
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
The usage of this would be OnPropertyChanged(nameof(this.Data)); In any case, try to look into the CommunityToolkit, it simplifies the access and usage to a lot of things in WPF & MVVM pattern. For instance, creating an observable property only needs an attribute to be set, the setter & getter methods will be generated for you in the background. Like:
[ObservableProperty]
private DataTable data;
[ObservableProperty]
private DataTable data;
This field will generate the correct observable property.
Nacho Man Randy Cabbage
@SpReeD yeah I would love to use the toolkit, unfortunately this is an a massive older app relying on mvvmlight and just don't have the time to convert it all.
Want results from more Discord servers?
Add your server