0

I am using MVVM with WPF and still figuring things out.

The problem I am having is, I call an api that returns a List of data. I add the list of data to an observable collection. (This api gets called when the window opens.) When the window opens the GridView is empty. Only when I hardcode data into my constructor does it show.

I want the data from my API show when the page is opened.

What am I doing wrong and how can I solve this?

Any help and guidance will be appreciated.

My view xaml

<Window x:Class="ErrorLogger_WPF.Views.ExceptionDetailsListView"
    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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:ErrorLogger_WPF.Views" xmlns:viewmodels="clr-namespace:ErrorLogger_WPF.ViewModels" d:DataContext="{d:DesignInstance Type=viewmodels:ExceptionDetailsListViewModel}"
    mc:Ignorable="d"      
    Title="ExceptionDetailsListView" Height="450" Width="800">
<Grid>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="15"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <ListView HorizontalAlignment="Left" VerticalAlignment="Top" Name="ExceptionList" ItemsSource="{Binding ExceptionDetails}" Height="Auto" Grid.Row="1">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Exception ID" DisplayMemberBinding="{Binding Path=Id}" Width="Auto"/>
                    <GridViewColumn Header="Exception Type" DisplayMemberBinding="{Binding Path=ExceptionType}" Width="Auto"/>
                    <GridViewColumn Header="Exception Message" DisplayMemberBinding="{Binding Path=ExceptionMessage}" Width="Auto"/>
                    <GridViewColumn Header="Inner Exception" DisplayMemberBinding="{Binding Path=InnerException}" Width="Auto"/>
                    <GridViewColumn Header="Exception Source File" DisplayMemberBinding="{Binding Path=ExceptionSourceFile}" Width="Auto"/>
                    <GridViewColumn Header="Exception Source Line" DisplayMemberBinding="{Binding Path=ExceptionSourceLine}" Width="Auto"/>
                    <GridViewColumn Header="Exception Caller" DisplayMemberBinding="{Binding Path=ExceptionCaller}" Width="Auto"/>
                    <GridViewColumn Header="Date and Time Logged" DisplayMemberBinding="{Binding Path=dateLogged}" Width="Auto"/>
                    <GridViewColumn Header="View/Edit" Width="auto">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <Button x:Name="Open" Content="Open Or Edit" 
                                    Command="{Binding Path=DataContext.OpenExceptionCommand,RelativeSource={RelativeSource AncestorType=Window,Mode=FindAncestor}}"
                                    CommandParameter="{Binding}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
        <Button Content="Button" HorizontalAlignment="Left" Margin="237,138,0,0" Grid.Row="1" VerticalAlignment="Top" Command="{Binding RefreshDataGridCommand}"/>

    </Grid>
</Grid>

my xaml.cs file

 using ErrorLogger_WPF.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace ErrorLogger_WPF.Views
{
    /// <summary>
    /// Interaction logic for ExceptionDetailsListView.xaml
    /// </summary>
    public partial class ExceptionDetailsListView : Window
    {
        public ExceptionDetailsListView()
        {
            DataContext = new ExceptionDetailsListViewModel();
            InitializeComponent();
        }

        
    }
}

My viewmodel

    using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ErrorLogger_WPF.Services;
using ErrorLogger_WPF.Views;
using Shared;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ErrorLogger_WPF.ViewModels
{
    
    internal partial class ExceptionDetailsListViewModel : ObservableObject
    {
        #region Properties

        
        public ObservableCollection<ExceptionDetails> ExceptionDetails { get; set; }

        #endregion
        APIService apiService = new APIService();

        

        public ExceptionDetailsListViewModel()
        {
            LoadData();  
        }

        private async void LoadData()
        {
            var exceptionDetails = await apiService.GetExceptionDetails();
            ExceptionDetails = new ObservableCollection<ExceptionDetails>(exceptionDetails);

        }

        [RelayCommand]
        private void OpenException(ExceptionDetails exDetails)
        {
            var detailedExceptionView = new DetailedExceptionView(exDetails);
            
            detailedExceptionView.ShowDialog();
            
        }
        [RelayCommand]
        private  void RefreshDataGrid()
        {
            LoadData();
        }
    }
}
MarkBerry
  • 25
  • 8

1 Answers1

0

Your current implementation does not raise INotifyPropertyChangedwhen setting the ExceptionDetails property. Therefore the binding does not update UI. Either raise it in the setter, or use the built-in ObservableObject.SetProperty.

zaphod-ii
  • 424
  • 3
  • 11