I was following this tutorial, which I do see is based on the .net core 2.1 framework
, but adapted for the .net 5 avalonia.mvvm
template. I followed the code line for line with the exception of the Program.cs
file given the fact that the avalonia.mvvm template in .net 5 implements the ViewLocator.cs
class so I don't believe I have to use Locator
. Yet, when I run the app while the Router.NavigationStack.Count
increments, the view remains on its default content. Here is the code
/// MainWindow.axaml
<Design.DataContext>
<vm:MainWindowViewModel/>
</Design.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<rxui:RoutedViewHost Grid.Row="0" Router="{Binding Router}" PageTransition="{x:Null}">
<rxui:RoutedViewHost.DefaultContent>
<TextBlock Text="Main Window"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</rxui:RoutedViewHost.DefaultContent>
</rxui:RoutedViewHost>
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="15">
<StackPanel.Styles>
<Style Selector="StackPanel > :is(Control)">
<Setter Property="Margin" Value="2"/>
</Style>
<Style Selector="StackPanel > TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</StackPanel.Styles>
<Button Content="Go next" Command="{Binding GoNext}" />
<Button Content="Go back" Command="{Binding GoBack}" />
<TextBlock Text="{Binding Router.NavigationStack.Count}" />
</StackPanel>
</Grid>
//MainWindowViewModel.cs
public class MainWindowViewModel : ViewModelBase, IScreen
{
public RoutingState Router { get; } = new RoutingState();
public ReactiveCommand<Unit, IRoutableViewModel> GoNext { get; }
public ReactiveCommand<Unit, Unit> GoBack => Router.NavigateBack;
public MainWindowViewModel()
{
GoNext = ReactiveCommand.CreateFromObservable(
() => Router.Navigate.Execute(new CommandCenterViewModel(this))
);
}
}
//CommandCenterView.axaml
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:vm="using:GuiClient.ViewModels"
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="GuiClient.Views.CommandCenterView">
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock x:Name="PathTextBlock" Text="Hi, I'm the first view!" />
<TextBlock Text="{Binding UrlPathSegment}" />
</StackPanel>
</UserControl>
///CommandCenterViewModel.cs
public class CommandCenterViewModel : ViewModelBase, IRoutableViewModel
{
public string UrlPathSegment { get; } = Guid.NewGuid().ToString().Substring(0, 5);
public IScreen HostScreen { get; }
public CommandCenterViewModel(IScreen screen) => HostScreen = screen;
}
//ViewLocator.cs in case this is relevant
public class ViewLocator : IDataTemplate
{
public IControl Build(object data)
{
var name = data.GetType().FullName!.Replace("ViewModel", "View");
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
else
{
return new TextBlock { Text = "Not Found: " + name };
}
}
public bool Match(object data)
{
return data is ViewModelBase;
}
}
Tried digging around online and couldn't find anyone who'd ran into the same issue. I'd appreciate help/being pointed in the right direction. Thanks!
Apparently the answer was just that the ViewLocator.cs
class of the current avalonia.mvvm template has nothing to do with the IViewLocator
that RoutedViewHost
from ReactiveUI
needs in order to work. Just needed to add this line to Program.cs
Locator.CurrentMutable.Register(() => new CommandCenterView(), typeof(IViewFor<CommandCenterViewModel>));