I would like to bind an Avalonia UI Datagrid with a dynamicdata sourcecache. I would like to be able to use a backend service that will be updated as soon as a change is made in the datagrid. So far I have been able to bind it in a way that Adds and Deletes are triggered. I haven't been able to trigger the update event. This is the code I use:
ViewModel
public class PersonVM:ViewModelBase
{
private int _id;
private string _lastName="";
private string _firstName="";
private int _age;
public int Id { get => _id; set => this.RaiseAndSetIfChanged(ref _id, value); }
public string LastName { get => _lastName; set => this.RaiseAndSetIfChanged(ref _lastName, value); }
public string FirstName { get => _firstName; set => this.RaiseAndSetIfChanged(ref _firstName, value); }
public int Age { get => _age; set => this.RaiseAndSetIfChanged(ref _age, value); }
}
Viewmodel for the main window
public class MainWindowViewModel : ViewModelBase
{
private SourceCache<PersonVM,int> _personsCache = new SourceCache<PersonVM,int>(x=>x.Id);
private IObservableCollection<PersonVM> _persons = new ObservableCollectionExtended<PersonVM>();
public IObservableCollection<PersonVM> Persons => _persons;
public MainWindowViewModel()
{
_personsCache.AddOrUpdate(new PersonVM() { Id = 1, LastName = "Doe", FirstName = "John", Age = 24 });
_personsCache.AddOrUpdate(new PersonVM() { Id = 2, LastName = "Doe", FirstName = "Jane", Age = 18 });
_personsCache.AddOrUpdate(new PersonVM() { Id = 3, LastName = "Foo", FirstName = "Alice", Age = 20 });
_personsCache.AddOrUpdate(new PersonVM() { Id = 4, LastName = "Bar", FirstName = "Bob", Age = 34 });
_personsCache.
Connect()
.ForEachChange(x=>Debug.WriteLine($"{x.Reason}{x.Key}"))
.ObserveOn(RxApp.MainThreadScheduler).Bind(_persons).Subscribe();
}
// add a new line in the sourcecache
public void AddRow()
{
int nextid = _personsCache.Keys.Max()+1;
_personsCache.AddOrUpdate(new PersonVM() { Id=nextid,LastName="",FirstName="",Age=0} );
}
// delete a line in the sourcecache
public void DeleteRow(int id)
{
_personsCache.RemoveKey(id);
}
// Tracker to check if the changes in the viewmodel have been correctly triggered.
public void ListItems()
{
foreach(var v in _personsCache.Items)
{
Debug.WriteLine($"{v.Id}{v.LastName}{v.FirstName}{v.Age}");
}
}
}
Main window XAML
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:DataGridBindingSourceCache.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="DataGridBindingSourceCache.Views.MainWindow"
Icon="/Assets/avalonia-logo.ico"
Title="DataGridBindingSourceCache">
<Grid RowDefinitions="auto,1*,auto">
<DataGrid Name="dgPersons" Items="{Binding Persons,Mode=TwoWay}" Grid.Row="1" IsReadOnly="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Id" Binding ="{Binding Id}"/>
<DataGridTextColumn Header="Firstname" Binding ="{Binding FirstName, Mode=TwoWay}" IsReadOnly="False"/>
<DataGridTextColumn Header="Lastname" Binding ="{Binding LastName, Mode=TwoWay}" IsReadOnly="False"/>
<DataGridTextColumn Header="Age" Binding ="{Binding Age, Mode=TwoWay}" IsReadOnly="False"/>
<DataGridTemplateColumn>
<DataTemplate>
<Button Content="Delete" Command="{Binding $parent[DataGrid].DataContext.DeleteRow}" CommandParameter="{Binding Id}"/>
</DataTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<Button Command="{Binding AddRow}">Add row</Button>
<Button Command="{Binding ListItems}">List items</Button>
</StackPanel>
</Grid>
</Window>
The update I make in the Datagrid seems to be reported in the sourcecache (as can be ssen with the ListItems function), but the update event of the sourcecache is not triggered when I do a change in the Datagrid.
Could you please point me to what I am doing wrong? Thanks a lot.