Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] RoutedCommand #21

Merged
merged 8 commits into from
Mar 18, 2024

Conversation

workgroupengineering
Copy link
Contributor

Experimenta implemtation of RoutedCommand like WPF.

the currently supported flow is this:

sequenceDiagram
    participant RotendCommand
    participant View
    participant RoutedCommandsManager
    participant ViewModel
    participant TopLevel
    TopLevel->>RoutedCommandsManager: Got Focus
    RoutedCommandsManager->>RotendCommand: Raise CanExecuteChanged
    RotendCommand->>View: Raise RoutedCommandsManager.CanExecuteEvent
    View->>RoutedCommandsManager: Raise RoutedCommandsManager.CanExecuteEvent
    RoutedCommandsManager->>ViewModel: ICommand.CanExecute
    RoutedCommandsManager->>RotendCommand: Handle=True
    RotendCommand->>View: Raise RoutedCommandsManager.ExecuteEvent
    View->>RoutedCommandsManager: Raise RoutedCommandsManager.ExecuteEvent
    RoutedCommandsManager->>ViewModel: ICommand.Execute
Loading

Get Started

  1. Install package

    dotnet add package package Avalonia.Labs.RoutedCommand
  2. Add XML Namespace

    <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"
                xmlns:lab="clr-namespace:Avalonia.Labs.Catalog"
    +             xmlns:rc="clr-namespace:Avalonia.Labs.Input;assembly=Avalonia.Labs.RoutedCommand"
                mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
                xmlns:viewModels="clr-namespace:Avalonia.Labs.Catalog.ViewModels"
                x:Class="Avalonia.Labs.Catalog.Views.RouteCommandView"
                x:DataType="viewModels:RouteCommandViewModel"
                HorizontalContentAlignment="Stretch"
                VerticalContentAlignment="Stretch"
                >
                ...
    </UserControl>
    
  3. Define your's RouterCommands

    public static class ApplicationCommands
    {
        public readonly static RoutedCommand Open = new RoutedCommand(nameof(Open));
        public readonly static RoutedCommand Save = new RoutedCommand(nameof(Save));
    }
  4. Assing your RotedCommand

            <UniformGrid Columns="2"
                        Grid.Column="2">
                <Button Content="Open"
                        Command="{x:Static lab:ApplicationCommands.Open}"
                        CommandParameter="{Binding .}"/>
                <Button Content="Save"
                        Command="{x:Static lab:ApplicationCommands.Save}"
                        CommandParameter="{Binding .}"/>
            </UniformGrid>
  5. Binding RouterCommand to your's ViewModel

    <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"
                xmlns:lab="clr-namespace:Avalonia.Labs.Catalog"
                xmlns:rc="clr-namespace:Avalonia.Labs.Input;assembly=Avalonia.Labs.RoutedCommand"
                mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
                xmlns:viewModels="clr-namespace:Avalonia.Labs.Catalog.ViewModels"
                x:Class="Avalonia.Labs.Catalog.Views.RouteCommandView"
                x:DataType="viewModels:RouteCommandViewModel"
                HorizontalContentAlignment="Stretch"
                VerticalContentAlignment="Stretch"
                >
    <rc:RoutedCommandsManager.Commands>
        <rc:RoutedCommandBinding RoutedCommand="{x:Static lab:ApplicationCommands.Open}" Command="{Binding Open}" />
        <rc:RoutedCommandBinding RoutedCommand="{x:Static lab:ApplicationCommands.Save}" Command="{Binding Save}" />
    </rc:RoutedCommandsManager.Commands>
    ...
    </UserControl>

Todo

  • KeyBinding
  • CommandTarget (requires modification in Avalonia).

private static readonly WeakReference<IInputElement?> _inputElement =
new WeakReference<IInputElement?>(default);

internal static event EventHandler? Invalidate = default;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this event


namespace Avalonia.Labs.Input
{
public sealed class RoutedCommandBinding : AvaloniaObject
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WPF CommandBinding is a bit different, where you set original ICommand and has CanExecute + Executed events.
It can be confusing when porting code from WPF, as in this PR RoutedCommandBinding.Command is actually target command, that gets executed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed Command to ExecutingCommand

@maxkatz6 maxkatz6 merged commit ea77b67 into AvaloniaUI:main Mar 18, 2024
2 of 3 checks passed
@workgroupengineering workgroupengineering deleted the features/RoutedCommand branch March 18, 2024 05:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants