New to AvaloniaUI / ReactiveUI, but not to WPF. I'm trying to play around with AvaloniaUI to see if I want to port my entire WPF project over to it, but I've ran into a little bit of a hurdle. I've found many examples of binding commands to 'self', eg. UserControl binding in UserControlModel, MainWindow binding in MainWindowModel, but nothing on a child UserControl binding to Parent model command. I've based my MainWindowModel.cs after one of the basic examples given by AvaloniaUI as shown. I basically want a button on a page to select which page in the Pages[] list to go to. But for now just go to the next one in the list. In WPF I would just the NavigationService and URI to nav, but wanted to try out this paradigm in Avalonia UI.
MainWindowModel.cs
public class MainWindowViewModel : ViewModelBase
{
public MainWindowViewModel()
{
// Set current page to first on start up
_CurrentPage = Pages[0];
// Create Observables which will activate to deactivate our commands based on CurrentPage state
var canNavNext = this.WhenAnyValue(x => x.CurrentPage.CanNavigateNext);
var canNavPrev = this.WhenAnyValue(x => x.CurrentPage.CanNavigatePrevious);
NavigateNextCommand = ReactiveCommand.Create(NavigateNext, canNavNext);
NavigatePreviousCommand = ReactiveCommand.Create(NavigatePrevious, canNavPrev);
}
// A read.only array of possible pages
private readonly PageViewModelBase[] Pages =
{
new FirstPageViewModel(),
new SecondPageViewModel(),
new ThirdPageViewModel()
};
// The default is the first page
private PageViewModelBase _CurrentPage;
/// <summary>
/// Gets the current page. The property is read-only
/// </summary>
public PageViewModelBase CurrentPage
{
get { return _CurrentPage; }
private set { this.RaiseAndSetIfChanged(ref _CurrentPage, value); }
}
/// <summary>
/// Gets a command that navigates to the next page
/// </summary>
public ICommand NavigateNextCommand { get; }
private void NavigateNext()
{
// get the current index and add 1
var index = Pages.IndexOf(CurrentPage) + 1;
// /!\ Be aware that we have no check if the index is valid. You may want to add it on your own. /!\
CurrentPage = Pages[index];
}
/// <summary>
/// Gets a command that navigates to the previous page
/// </summary>
public ICommand NavigatePreviousCommand { get; }
private void NavigatePrevious()
{
// get the current index and subtract 1
var index = Pages.IndexOf(CurrentPage) - 1;
// /!\ Be aware that we have no check if the index is valid. You may want to add it on your own. /!\
CurrentPage = Pages[index];
}
}
The example binds the navigation buttons in MainWindow.axaml
<TransitioningContentControl Content="{Binding CurrentPage}" />
<StackPanel Grid.Row="1" Orientation="Horizontal" Spacing="5"
HorizontalAlignment="Right">
<Button Command="{Binding NavigatePreviousCommand}" Content="Back" />
<Button Command="{Binding NavigateNextCommand}" Content="Next" />
</StackPanel>
I would like to bind to these commands in childView Page buttons. Is there a way to do that? Or do I need to link up an Event handler to signal to the Parent (MainWindow) to do it? And if so what does a basic example look like?
Thanks!
I've tried a number of route examples but none are related to the Parent-Child relationship.