DataContext is unknown

JasinCole

Well-known member
Joined
Feb 16, 2023
Messages
66
Programming Experience
1-3
Ok, another rabbit hole I went down and I have no idea what or where my issue is

I created a WPF to just explore how I might be able to display my database information. I have the following code.
The problem I am seeing is two issues. But Let's start with the first one.

If I set a breakpoint at line 12 of MainViewModel and inspect _service variable the database is not returning any information. I get Errors that state "Exception = Timed out after 1000ms"
In a console application with the same IHost setup used for dependency injection I do not have this problem, so it seems the issue is with the WPF app and I am unsure why...

The second problem is the DataContext is unknown in MainWindow.xaml. Which makes no sense since I set the DataContext to the VM which contains an Observable property called Name

App.xaml.cs:
using System;
using System.Windows;
using DatabaseAccess;
using DatabaseAccess.Context;
using LifeRaft_GUI.ViewModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace LifeRaft_GUI
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App
    {
        private static IHost? AppHost { get; set; }
        private static string? _connectionString;
     
        public App()
        {
            AppHost = Host.CreateDefaultBuilder()
                .ConfigureAppConfiguration((context, configuration) =>
                {
                    configuration.Sources.Clear();
                    configuration
                        .AddJsonFile("appsettings.json", true, true);

                    _connectionString = BuildConnectionString(configuration.Build());
                })
                .ConfigureServices((context, services) =>
                {
                    services.AddSingleton<MainWindow>();
                    services.AddSingleton<MainViewModel>();
                    services.AddScoped<IUnitOfWork, UnitOfWork>();
                    services.AddDbContext<SageDbContext>(options => options.UseSqlServer(_connectionString));
                })
                .Build();
        }

        protected override async void OnStartup(StartupEventArgs e)
        {
            await AppHost!.StartAsync();
            var startUpForm = AppHost.Services.GetRequiredService<MainWindow>();
            startUpForm.Show();
         
            base.OnStartup(e);
        }

        protected override async void OnExit(ExitEventArgs e)
        {
            await AppHost!.StopAsync();
         
            base.OnExit(e);
        }
     
        public new static App Current => (App)Application.Current;

MainWindow.xaml.cs:
namespace LifeRaft_GUI
{
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = App.Current.MainVm;
        }
    }
}

MainViewModel:
using DatabaseAccess.Entities;

namespace LifeRaft_GUI.ViewModels;

public partial class MainViewModel : ObservableObject
{
    private readonly IUnitOfWork _service;

    public MainViewModel(IUnitOfWork service)
    {
        _service = service;
    }

    [ObservableProperty] private string name;

    public IEnumerable<Employ> Employees()
    {
        return _service.Employees.GetAll();
    }

}

UnitOfWork:
using DatabaseAccess.Context;
using DatabaseAccess.Repositories;

namespace DatabaseAccess;

public class UnitOfWork : IUnitOfWork
{
    private readonly SageDbContext _ctx;

    public UnitOfWork(SageDbContext ctx)
    {
        _ctx = ctx;
        Employees = new EmployRepository(_ctx);
        Payrecs = new PayrecRepository(_ctx);
    }
 
    public IEmployRepository Employees { get; }
    public IPayrecRepository Payrecs { get; }

    public void Dispose()
    {
        _ctx.Dispose();
        GC.SuppressFinalize(this);
    }
}

MainWindow.xaml:
<Window x:Class="LifeRaft_GUI.MainWindow"
        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:LifeRaft_GUI"
        mc:Ignorable="d"
        Title="Life Raft" Height="450" Width="800">
     
        <TextBlock Text="{ Binding Name}"></TextBlock>

</Window>
 
For the DataContext issue, I would try changing line 3:
C#:
public partial class MainWindow
to
C#:
public partial class MainWindow : Window
to see if it makes any difference.

As for the database time out issue, does the error only occur when trying to inspect the value with a breakpoint? What happens if you just run the application. In general, WPF and console apps have a difference in the way any async dispatchers work. Also I can't recall whether WPF main threads are STA while console is free-threaded.
 
Adding Window doesn't seem to fix the issue. I did fix it by adding this in MainWindow.xaml

C#:
d:DataContext="{d:DesignInstance local:MainWindow}

What that actually does behind the scene and what it fixes I don't know. Guess it'll just be a Black Box
 
Take the DataContext line out of the MainWindow code behind and put it in the startup
C#:
 protected override async void OnStartup(StartupEventArgs e)
        {
            await AppHost!.StartAsync();
            var startUpForm = AppHost.Services.GetRequiredService<MainWindow>();
            startupForm.Datacontext = AppHost.Services.GetRequiredService<MainViewModel>();
            startUpForm.Show();
         
            base.OnStartup(e);
        }

See if that helps.
 
DataContext is a crucial concept in software development, particularly in the context of data binding and the Model-View-ViewModel (MVVM) pattern. It represents the object or data source that provides the context for binding data to UI elements. DataContext allows for seamless communication between the UI and underlying data, enabling efficient data manipulation and updates. It serves as a bridge, facilitating the interaction and synchronization between the presentation layer and the underlying data model, resulting in a more dynamic and responsive user interface.
 
Maybe consulting with software development specialist *** SPAMMY LINK REMOVED *** is a move towards addressing this issue.
 
@Zomab: This is your second post, and again I had to remove a spam link to your services. The main forum is not for offering services. Go to the specific advertising subforum if you want to offer your services.
 
Back
Top Bottom