Search code examples
c#xamlbindingmaui

Bind in XAML to one item in a List, but that item is obtained by another property on the same ViewModel


I'm having this issue with binding and I'm not sure what I'm doing wrong. I have a ViewModel which contains an index property and in the same ViewModel theres's also a List<> of another ViewModel. In my XAML I'm trying to get a property from one of the ViewModels in the List indicated by that index value, but everything I tried in XAML except using a literal number hasn't worked. It kinda did worked binding on codebehind but it only updated once and never again, and it was using the default mode.

The ViewModels are being constantly (every 1/60th of a second in some cases) one way via UDP.

CarDataViewModel.cs

public partial class CarDataViewModel : ObservableObject
{
    [ObservableProperty]
    private uint _currentLapTimeInMS;
    
    ...
}

MainViewModel.cs

public partial class MainViewModel : ObservableObject
{
    [ObservableProperty]
    private byte _playerIndex;

    [ObservableProperty]
    private List<CarDataViewModel> _carDataViewModels;

    public MainViewModel()
    {
        CarDataViewModels = new();
        for (int i = 0; i < 22; i++)
        {
            CarDataViewModel carDataViewModel = new();
            CarDataViewModels.Add(carDataViewModel);
        }
    }
}

MauiProgram.cs

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
                        .UseMauiCommunityToolkit()
                        .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });

                builder.Services.AddSingleton<MainViewModel>();
                return builder.Build();
    }
}

AppShell.xaml.cs

public partial class AppShell : Shell
{
    public AppShell()
    {
        InitializeComponent();

        BindingContext = ServiceHelper.GetService<MainViewModel>();
        ...
    }

    ...
}

When I access directly using an explicit list index it works...

...

<!-- This updates fine -->
<Label Text={Binding CarDataViewModels[0].CurrentLapTimeInMS} />

...

...but that array will grow depending on the amount of cars running, so the UDP stream also provides me with the array index I should be keeping and eye on, which I also have it as a property in my MainViewModel.


Solution

  • you need to create another property

    [ObservableProperty]
    private CarDataViewModel _selectedCarData;
    

    and then update it whenever you update _playerIndex

    SelectedCarData = CarDataViewModels[PlayerIndex];