AboutView not registered?

/// App.xaml.cs
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);

_serviceProvider = serviceCollection.BuildServiceProvider();

var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();

mainWindow.Show();
}

private void OnExit(object sender, ExitEventArgs e)
{
// Dispose of services as needed
if (_serviceProvider is IDisposable disposable)
{
disposable.Dispose();
}
}

private void ConfigureServices(IServiceCollection services)
{
// Configure logging
services.AddLogging();

// Register Views
services.AddSingleton<MainWindow>();
services.AddSingleton<AboutView>();

// Register ViewModels
services.AddSingleton<IMainWindowViewModel, MainWindowViewModel>();
services.AddSingleton<IAboutViewViewModel, AboutViewViewModel>();

// Register Services
services.AddSingleton<IFileDialog, FileDialog>();
services.AddSingleton<ILogger, Logger>();
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);

_serviceProvider = serviceCollection.BuildServiceProvider();

var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();

mainWindow.Show();
}

private void OnExit(object sender, ExitEventArgs e)
{
// Dispose of services as needed
if (_serviceProvider is IDisposable disposable)
{
disposable.Dispose();
}
}

private void ConfigureServices(IServiceCollection services)
{
// Configure logging
services.AddLogging();

// Register Views
services.AddSingleton<MainWindow>();
services.AddSingleton<AboutView>();

// Register ViewModels
services.AddSingleton<IMainWindowViewModel, MainWindowViewModel>();
services.AddSingleton<IAboutViewViewModel, AboutViewViewModel>();

// Register Services
services.AddSingleton<IFileDialog, FileDialog>();
services.AddSingleton<ILogger, Logger>();
}
Trying to load the AboutView but seem to forgot how with DI going. Thank you for your help.
No description
85 Replies
jcotton42
jcotton42•2mo ago
@Temporal Nightmare you registered it as the interface, but are asking for the concrete type. But also, why the interfaces?
Temporal Nightmare
Temporal NightmareOP•2mo ago
What do you mean ? Because I want to follow the same patterns as DI @leowest and others mentioned it, or someone did, maybe not them
jcotton42
jcotton42•2mo ago
you did
services.AddSingleton<IAboutViewViewModel, AboutViewViewModel>();
services.AddSingleton<IAboutViewViewModel, AboutViewViewModel>();
in your setup, but your View is doing
_serviceProvider.GetRequiredService<AboutViewViewModel>();
_serviceProvider.GetRequiredService<AboutViewViewModel>();
The DI container knows how to fulfill IAboutViewViewModel, it does not know how to fulfill AboutViewViewModel. (Also, that really should be named AboutViewModel, not AboutViewViewModel) @Temporal Nightmare
Temporal Nightmare
Temporal NightmareOP•2mo ago
ok sorry:( sec Okay, renamed them. So how does one call a Window via [RelayCommand] if using DI?
jcotton42
jcotton42•2mo ago
I never said to not use DI. I said you were requesting the wrong type from the container. You registered the interface, but asked the DI container for the concrete type, you just need to ask for the interface instead.
Temporal Nightmare
Temporal NightmareOP•2mo ago
public void ShowAbout() { var view = _serviceProvider.GetRequiredService<IAboutViewModel>();
} closer? I stil lcant do view.ShowDialog() or whatever it is. XD @jcotton42 can you save me? I feel like an idiot, I've been trying 😦 I appreciate your time
Nasdack
Nasdack•2mo ago
Fetch the class, not the interface
Temporal Nightmare
Temporal NightmareOP•2mo ago
What? I did both ways and both were wrong.
#region Commands
[RelayCommand]
public void ShowAbout()
{
var view = _serviceProvider.GetRequiredService<IAboutViewModel>();

}
#endregion
#region Commands
[RelayCommand]
public void ShowAbout()
{
var view = _serviceProvider.GetRequiredService<IAboutViewModel>();

}
#endregion
I tried just the normal Class AboutViewModel too
Nasdack
Nasdack•2mo ago
There's no need for an interface for every single view model you make That's not what interfaces are for
Temporal Nightmare
Temporal NightmareOP•2mo ago
Then what are they for? I've seen 2 documents and some YT'ers use them for every VM
Nasdack
Nasdack•2mo ago
services.AddSingleton<AboutViewModel>();
services.AddSingleton<AboutViewModel>();
Then:
var view = _serviceProvider.GetRequiredService<AboutViewModel>();
var view = _serviceProvider.GetRequiredService<AboutViewModel>();
Temporal Nightmare
Temporal NightmareOP•2mo ago
No description
Temporal Nightmare
Temporal NightmareOP•2mo ago
No description
Temporal Nightmare
Temporal NightmareOP•2mo ago
Seems okay? Or am I this blind 😦
Nasdack
Nasdack•2mo ago
interface keyword - C# reference
Use the interface keyword to define contracts that any implementing type must support. Interfaces provide the means to create common behavior among a set of unrelated types.
Temporal Nightmare
Temporal NightmareOP•2mo ago
well this confuses me but either way, I did whatyou posted but once I do var view ... what do i do after?
Nasdack
Nasdack•2mo ago
you here are fetching the implementation (concrete type) of the service, not the service itself The service is registered as IAboutViewModel, and its concrete implementation is specified as AboutViewModel So when you fetch a service called AboutViewModel, it is not found You instead need to register the class itself as a service
Temporal Nightmare
Temporal NightmareOP•2mo ago
do I even need to? I don't see how a About window with some product info and a OK button needs it.
Nasdack
Nasdack•2mo ago
If your interface has the required properties and methods for that then yes
Temporal Nightmare
Temporal NightmareOP•2mo ago
I hate this shit, all I want to do is MAKE MY APP
Nasdack
Nasdack•2mo ago
you will see them
Temporal Nightmare
Temporal NightmareOP•2mo ago
not make a OS or a Government program 😐 but I don't know when to use interfaces or not, I keep getting confused 😦
Nasdack
Nasdack•2mo ago
Well I wouldn't use an interface for every single view model I make. An interface is like a common contract for multiple classes to adhere to... so something like IViewModelBase with common methods and functions that a group of view models must have, will make more sense
Temporal Nightmare
Temporal NightmareOP•2mo ago
but what is a contract? I hate buzzwords XD
Nasdack
Nasdack•2mo ago
An agreement between two or more parties
Temporal Nightmare
Temporal NightmareOP•2mo ago
Well yes
Nasdack
Nasdack•2mo ago
That's the dictionary's definition and it fits here The parties being classes, or other interfaces and the agreement being methods, properties, etc...
Temporal Nightmare
Temporal NightmareOP•2mo ago
No description
Temporal Nightmare
Temporal NightmareOP•2mo ago
I'm gonna upload to Github I guess Because I'm going in circles If I didn't need to impress people, I'd skip DI and just get the app done But no, I need to do it so I can get work
Nasdack
Nasdack•2mo ago
Why are you fetching the class when you have registered the interface? Of course the error is popping up
Temporal Nightmare
Temporal NightmareOP•2mo ago
CAN ONE OF YOU MAKE UP YOUR MIND
Temporal Nightmare
Temporal NightmareOP•2mo ago
No description
Temporal Nightmare
Temporal NightmareOP•2mo ago
^^^ Which is it 😭
Nasdack
Nasdack•2mo ago
. That was in reply to the code I sent you, which registers the class But you did not update that
Keswiik
Keswiik•2mo ago
Use an interface if you need to abstract the implementation from the contract consumers will use. ILogger is a great example. You have loggers that go to files, console, external sources, etc. Consumers likely don't care which specific implementation they are using, they just need to access the basic functionality of ILogger I would not make interfaces for a view model (like delegate said)
Temporal Nightmare
Temporal NightmareOP•2mo ago
ok so no interfaces? just for services like ILogger, IFileDialog etc got it App.xaml.cs
private void ConfigureServices(IServiceCollection services)
{
// Configure logging
services.AddLogging();

// Register Views
services.AddSingleton<MainWindow>();
services.AddSingleton<AboutView>();

// Register ViewModels
services.AddSingleton<MainViewModel>();
services.AddSingleton<AboutViewModel>();

// Register Services
services.AddSingleton<IFileDialog, FileDialog>();
services.AddSingleton<ILogger, Logger>();
}
private void ConfigureServices(IServiceCollection services)
{
// Configure logging
services.AddLogging();

// Register Views
services.AddSingleton<MainWindow>();
services.AddSingleton<AboutView>();

// Register ViewModels
services.AddSingleton<MainViewModel>();
services.AddSingleton<AboutViewModel>();

// Register Services
services.AddSingleton<IFileDialog, FileDialog>();
services.AddSingleton<ILogger, Logger>();
}
MainWindow.xaml.cs
using System.Windows;
using TitanStudioWpf.ViewModels;

namespace TitanStudioWpf;

public partial class MainWindow : Window
{
public MainWindow(MainViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
using System.Windows;
using TitanStudioWpf.ViewModels;

namespace TitanStudioWpf;

public partial class MainWindow : Window
{
public MainWindow(MainViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
using System.Windows;
using TitanStudioWpf.ViewModels;

namespace TitanStudioWpf.Views;

public partial class AboutView : Window
{
public AboutView(AboutViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
using System.Windows;
using TitanStudioWpf.ViewModels;

namespace TitanStudioWpf.Views;

public partial class AboutView : Window
{
public AboutView(AboutViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
Better? šŸ™‚ I deleted the 2 viewmodel interface files too
Keswiik
Keswiik•2mo ago
seems fine to me, assuming it runs i don't work with wpf lol
Temporal Nightmare
Temporal NightmareOP•2mo ago
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace TitanStudioWpf.ViewModels;

public partial class AboutViewModel : ObservableObject
{
[RelayCommand]
public void Close()
{
using (AboutViewModel view = new AboutViewModel())
{

}
}
}
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace TitanStudioWpf.ViewModels;

public partial class AboutViewModel : ObservableObject
{
[RelayCommand]
public void Close()
{
using (AboutViewModel view = new AboutViewModel())
{

}
}
}
so how do i call the window now? XD apparently, can't use using on WPF windows, it's not WinForms fair
Keswiik
Keswiik•2mo ago
I am going to assume this closes the AboutView?
Temporal Nightmare
Temporal NightmareOP•2mo ago
#region Commands [RelayCommand] public void ShowAbout() { var viewModel = _serviceProvider.GetRequiredService<AboutViewModel>(); var aboutWindow = new AboutView { DataContext = viewModel }; aboutWindow.ShowDialog(); } #endregion sorrt i had the wrong damn viewmodel i want to SEE the view! from MainWindow using MainWindowViewModel
Temporal Nightmare
Temporal NightmareOP•2mo ago
No description
Temporal Nightmare
Temporal NightmareOP•2mo ago
I am going insane I just want to see a Window, it's a goddamn modding app, no modder cares about Interfaces, DI, etc. But I'm trying to keep the structure as it helps reenforce it
Keswiik
Keswiik•2mo ago
can you, like, give a rundown on what is / isn't working right now?
Temporal Nightmare
Temporal NightmareOP•2mo ago
MainWindow shows up fine, DI and all. I go to Help => About, and expect it to open AboutView using MainViewModel That's where my issue is at the moment I'm trying 😦 I still need to do Velopack, which I will do once I get this part done. XD
Keswiik
Keswiik•2mo ago
Do you get any errors when you try to show the about view?
Temporal Nightmare
Temporal NightmareOP•2mo ago
No description
Temporal Nightmare
Temporal NightmareOP•2mo ago
Yes
Keswiik
Keswiik•2mo ago
you shouldn't be requesting AboutViewModel from the service provider, you should be requesting AboutView
Temporal Nightmare
Temporal NightmareOP•2mo ago
Because using Using (var view = new AboutView())
Keswiik
Keswiik•2mo ago
look at your constructors
Temporal Nightmare
Temporal NightmareOP•2mo ago
doesn't work ok so i dont even need var viewModel
Keswiik
Keswiik•2mo ago
i also don't see the point of including a using block for what you're doing
Temporal Nightmare
Temporal NightmareOP•2mo ago
[RelayCommand] public void ShowAbout() { var aboutWindow = new AboutView { DataContext = viewModel }; aboutWindow.ShowDialog(); } ok now we're down to 2 lines and stilll nothing
using System.Windows;
using TitanStudioWpf.ViewModels;

namespace TitanStudioWpf.Views;

public partial class AboutView : Window
{
public AboutView(AboutViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
using System.Windows;
using TitanStudioWpf.ViewModels;

namespace TitanStudioWpf.Views;

public partial class AboutView : Window
{
public AboutView(AboutViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
AboutViewModel.cs
Keswiik
Keswiik•2mo ago
i would expect this to break something there's no need to explicitly set the DataContext with an object initializer
Temporal Nightmare
Temporal NightmareOP•2mo ago
I'm sure of it, because I have 0 idea of the proper way, even AI messed up
Keswiik
Keswiik•2mo ago
you're DI-ing the view model
Temporal Nightmare
Temporal NightmareOP•2mo ago
true
Keswiik
Keswiik•2mo ago
and in this case viewModel could refer to a different type entirely
Temporal Nightmare
Temporal NightmareOP•2mo ago
I would upload this to Github but it's not meant to be public, it's a special case project. Can I just send you my solution / project? I don't want the entire world having or or AI to steal it. XD
Keswiik
Keswiik•2mo ago
struggle bus is part of the learning process
Temporal Nightmare
Temporal NightmareOP•2mo ago
No thanks, I struggle enough I just want a damn WINDOW to show up God, even in VISUAL BASIC, its easy but noooo, let's use DI and WPF and be confusing for idiots with autism and adhd like me!
Keswiik
Keswiik•2mo ago
my first suggestion is to try and isolate the problem; ignore your commands and stuff for now. use a codebehind handler and try displaying the window within your MainWindow class like
Temporal Nightmare
Temporal NightmareOP•2mo ago
I'm almost 50, I give 2 shits if I'm hired, which I won't be as I'm a ex-felon and have no future and AI will take all our jobs anyway So let me have this one moment That's a horrible decision, according to big youtubers who are also coders.
Keswiik
Keswiik•2mo ago
I said isolate the problem, not stick with that solution forever ĀÆ\_(惄)_/ĀÆ
Temporal Nightmare
Temporal NightmareOP•2mo ago
Fair enough, I'll try it that way. The end user doesn't even give a damn anyway, they're not coders. DI, Services, Interfaces, etc is a job / team thing Not a end user requirement anyway I'm only doing it to keep up with it and I can't even do that it seems 😐
Temporal Nightmare
Temporal NightmareOP•2mo ago
No description
Temporal Nightmare
Temporal NightmareOP•2mo ago
finally!
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using TitanStudioWpf.Views;

namespace TitanStudioWpf.ViewModels;

public partial class MainViewModel : ObservableObject
{
private readonly ILogger<MainViewModel> _logger;
private readonly IServiceProvider _serviceProvider;

#region Commands
[RelayCommand]
public void ShowAbout()
{
var aboutWindow = _serviceProvider.GetRequiredService<AboutView>();
aboutWindow.ShowDialog();
}
#endregion

#region Properties

#endregion

public MainViewModel(IServiceProvider serviceProvider, ILogger<MainViewModel> logger)
{
_logger = logger;
_serviceProvider = serviceProvider;
}
}
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using TitanStudioWpf.Views;

namespace TitanStudioWpf.ViewModels;

public partial class MainViewModel : ObservableObject
{
private readonly ILogger<MainViewModel> _logger;
private readonly IServiceProvider _serviceProvider;

#region Commands
[RelayCommand]
public void ShowAbout()
{
var aboutWindow = _serviceProvider.GetRequiredService<AboutView>();
aboutWindow.ShowDialog();
}
#endregion

#region Properties

#endregion

public MainViewModel(IServiceProvider serviceProvider, ILogger<MainViewModel> logger)
{
_logger = logger;
_serviceProvider = serviceProvider;
}
}
Well it works anyway! sweats
Keswiik
Keswiik•2mo ago
:Blob:
Temporal Nightmare
Temporal NightmareOP•2mo ago
I appreciate your time ded, delegate, leo, jcotton, I just wish I could tell the difference better when it comes to when to use interfaces/services. I get it right half the time anyway. And I do love WPF since leo and others got me finally to figure it out and eventually I'll toy with Avalonia once I get WPF under mybelt more.
Keswiik
Keswiik•2mo ago
avalonia is heavily inspired by wpf so some of the stuff you learn will translate over well enough
Temporal Nightmare
Temporal NightmareOP•2mo ago
Yep, was watching Kevin (Keboo) and it looks pretty similar besidess being cross platform of course.
leowest
leowest•2mo ago
I did told u to learn DI and lifecycles etc, never said anything specific about interfaces etc, just want to clear that out.
Temporal Nightmare
Temporal NightmareOP•2mo ago
Yeah, DI isn't bad at all, not sure where I got the Interfaces from, could of been an article I read too.
Temporal Nightmare
Temporal NightmareOP•2mo ago
leowest
leowest•2mo ago
yeah I dont recall even giving u any article either heh well glad u sorted out... I just got home do u still have any issue?
Temporal Nightmare
Temporal NightmareOP•2mo ago
well now I have one with TreeView with Matertial design, which worked before w.o Material Design so not sure lol
Temporal Nightmare
Temporal NightmareOP•2mo ago
No description
Temporal Nightmare
Temporal NightmareOP•2mo ago
nm it works if I hard code the colors in, will try to find the compatable Material ones Do you use Material Design or Fluent or roll your own? Style="{StaticResource MaterialDesignWindow}" Oh, forgot this. šŸ˜‚
leowest
leowest•2mo ago
depends on the requirement honestly, if its an internal tool I usually barely add anything if its something facing outside I will evaluate based on delivery time, demand, etc
Temporal Nightmare
Temporal NightmareOP•2mo ago
Ah
leowest
leowest•2mo ago
wpfui, material design are my fav for wpf thou
Temporal Nightmare
Temporal NightmareOP•2mo ago
I like Material Design a lot now, it has more controls, more ways to do stuff. I can't figure out how to change the colors of the buttons yet with it but it's a start Since I don't wanna break the "Theme"
leowest
leowest•2mo ago
they have a wiki in their github u can look at but u have for example
<materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="DeepPurple" SecondaryColor="Lime" />
<materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="DeepPurple" SecondaryColor="Lime" />
Temporal Nightmare
Temporal NightmareOP•2mo ago
Oh, yeah forgot, that's in App.xaml
<Application x:Class="TitanStudioWpf.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:TitanStudioWpf">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<materialDesign:BundledTheme BaseTheme="Dark" PrimaryColor="DeepPurple" SecondaryColor="Lime" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign3.Defaults.xaml" />
<ResourceDictionary Source="/TitanStudioWpf.Core;component/Resources/Theme.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
<Application x:Class="TitanStudioWpf.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:TitanStudioWpf">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<materialDesign:BundledTheme BaseTheme="Dark" PrimaryColor="DeepPurple" SecondaryColor="Lime" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign3.Defaults.xaml" />
<ResourceDictionary Source="/TitanStudioWpf.Core;component/Resources/Theme.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Now I know where to look, thanks šŸ™‚
Anton
Anton•2mo ago
Any class is already an abstraction, you don't need an interface. DI is for passing it its private dependencies automatically.

Did you find this page helpful?