I'm trying to implement a simple navigation which is just a MainWindow with a ContentPresenter on top of it. Most of the code is autogenerated. I only added a ContentPresenter, bound its content to a CurrentPage and created a view and a viewmodel for a home page
MainWindow.axaml
All of the code is autogenerated except the ContentPresenter
<Window xmlns="https://github.com/avaloniaui"
...>
<Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:MainWindowViewModel />
</Design.DataContext>
<ContentPresenter Content="{Binding CurrentPage}" />
</Window>
MainWindowViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
namespace AvaloniaApplication5.ViewModels
{
public partial class MainWindowViewModel : ViewModelBase
{
[ObservableProperty]
private ViewModelBase _currentPage = new HomeViewModel();
}
}
HomeView.axaml
A blank UserControl file that should work as a page that ContentPresenter navigates to
<UserControl xmlns="https://github.com/avaloniaui"
...>
Welcome to Avalonia!
</UserControl>
HomeViewModel.cs
namespace AvaloniaApplication5.ViewModels
{
public class HomeViewModel : ViewModelBase
{
}
}
The result of this code should be a display of HomeView.axaml in ContentPresenter but in reality it can't find HomeView.axaml
There's also a ViewLocator that resolves the view that corresponds to a specific ViewModel. This file is entirely autogenerated
ViewLocator.cs
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using AvaloniaApplication5.ViewModels;
using System;
namespace AvaloniaApplication5
{
public class ViewLocator : IDataTemplate
{
public Control? Build(object? data)
{
if (data is null)
return null;
var name = data.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
var type = Type.GetType(name);
if (type != null)
{
var control = (Control)Activator.CreateInstance(type)!;
control.DataContext = data;
return control;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object? data)
{
return data is ViewModelBase;
}
}
}
It seems like the ViewLocator does indeed work as intended and ContentPresenter wants to display HomeView but it can't find it.
I tried specifying Data Context for HomeView but it didn't do anything
HomeView.axaml.cs
public HomeView()
{
InitializeComponent();
DataContext = new HomeViewModel();
}
It's open bug in creating user control template Namespace is missing Views
... the ViewLocator
is depended on naming convention
correct the namespace
HomeView.axaml.cs
using Avalonia.Controls;
namespace AvaloniaApplication5.Views; // <<< make sure that name space Has Views
public partial class HomeView : UserControl
{
public HomeView()
{
InitializeComponent();
}
}
HomeView.axaml
<UserControl 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"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AvaloniaApplication5.Views.HomeView">
<!--namespace hase Views ....^^^^^... -->
Welcome to Avalonia!
</UserControl>