I am trying to set up my application to show a different view depending on what the name of the device is. Unfortunately, I can't seem to get the View to load, though the ViewModel is getting called. I'm not entirely sure what I'm missing.
Currently, when the application loads, the only thing shows up is the MainWindow, but the View is not being loaded inside of it.
How can I get a View to load?
Here is my MainWindow.axaml:
<Window
xmlns="https://github.com/avaloniaui"
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:vm="clr-namespace:TAStagingApp.ViewModels.Implementations;assembly=TAStagingApp.ViewModels"
mc:Ignorable="d"
d:DesignWidth="800"
d:DesignHeight="450"
x:Class="TAStagingApp.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
Background="{StaticResource TABackgroundColor}"
Icon="/Assets/tastaging.png"
WindowStartupLocation="CenterScreen"
Title="TA Staging">
<Design.DataContext>
<vm:MainWindowViewModel />
</Design.DataContext>
<Grid>
<ContentPresenter Name="StagingContent"/>
</Grid>
</Window>
And the MainWindow.axaml.cs
namespace TAStagingApp.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public void SetContent(Control control)
{
var mainContent = this.FindControl<ContentPresenter>("StagingContent");
mainContent!.Content = control;
}
}
App.axaml.cs
using AvaloniaApplication = Avalonia.Application;
namespace TAStagingApp;
public partial class App : AvaloniaApplication
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
var viewModelLoader = new ViewModelLoader(new MainWindow());
ServiceLocator.Initialize(viewModelLoader);
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
DataContext = GetRequiredService<IMainWindowViewModel>();
desktop.MainWindow = new MainWindow
{
DataContext = DataContext,
};
viewModelLoader.LoadContentViewBasedOnComputerName();
}
base.OnFrameworkInitializationCompleted();
}
private static T GetRequiredService<T>() => Locator.Current.GetRequiredService<T>();
}
ViewModelLoader.cs
namespace TAStagingApp.DependencyInjection.Loaders;
public sealed class ViewModelLoader(MainWindow mainWindow) : IViewModelLoader
{
private readonly MainWindow _mainWindow = mainWindow;
public void LoadContentViewBasedOnComputerName()
{
var serviceProvider = DeviceTypeHelper.GetDeviceTypeServiceProvider();
var deviceType = DeviceTypeHelper.GetDeviceType(serviceProvider);
Control contentView = deviceType.Value.ToString() switch
{
var device when device.Equals(DeviceType.Server.ToString()) => new ServerConfigureView(),
var device when device.Equals(DeviceType.Terminal.ToString()) => new TerminalConfigureView(),
var device when device.Equals(DeviceType.Kitchen.ToString()) => new TerminalConfigureView(),
_ => new AdminView()
};
_mainWindow.SetContent(contentView);
}
}
MainWindowViewModel.cs
namespace TAStagingApp.ViewModels.Implementations;
public class MainWindowViewModel : ViewModelBase, IMainWindowViewModel
{
public MainWindowViewModel(IActivateViewModel viewModel)
{
if (viewModel.GetType() == typeof(TerminalConfigureViewModel))
{
TerminalConfigureViewModel = viewModel;
}
else if (viewModel.GetType() == typeof(ServerConfigureViewModel))
{
ServerConfigureViewModel = viewModel;
}
else
{
AdminViewModel = viewModel;
}
Activate(viewModel);
}
public MainWindowViewModel()
{
}
public IActivateViewModel AdminViewModel { get; } = default!;
public IActivateViewModel TerminalConfigureViewModel { get; } = default!;
public IActivateViewModel ServerConfigureViewModel { get; } = default!;
private static void Activate(IActivateViewModel viewModel)
=> viewModel.Activate();
}
I've been looking at this for two days now and can't figure out what I'm missing.
The problem is your
ViewModelLoaderis working with an instance ofMainWindowwhich is different from the actualyou can fix it by instantiating
ViewModelLoaderwith the application Main windowSide Advice
Actually, you should redesign your architecture because you get architecture dead look!
If I were you, I will use data templates to make my life easy!
And put in your
MainViewModleProperty CalledCurrentViewModelorActivatedViewModelor Whatever of typeViewModelBaseAll of
ServerConfigureViewModel,TerminalConfigureViewModelandAdminViewModelshould inherit fromViewModelBaseand can be signed toCurrentViewModdeland bind to it in main Window
now if you change
CurrentViewModdelin Main Window View will change without all this code ofViewModleLocatorand this staff