Search code examples
c#mauieventtocommand

Maui event to command behavior how to get sender and args inside command?


Style code:

<Style x:Key="SpacesQuestionEditor" TargetType="Editor">
        <Setter Property="behaviors:TestEditorStyleBehavior.AttachBehavior">
            <Setter.Value>
                    <toolkit:EventToCommandBehavior EventName="TextChanged"                                                    
                                                    Command="{Binding Source={x:Reference TestEditorPage}, Path=BindingContext.EditorTextChangedCommand}"
                                                    CommandParameter="{Binding .}"/>
    


                </Setter.Value>
        </Setter>
</Style>

Editor code:

<Editor x:Name="spacesTextEditor" Placeholder="Enter text" Style="{StaticResource SpacesQuestionEditor}" Text="{Binding SpacesEditorText}" AutoSize="TextChanges"/>

Command from view model code:

[RelayCommand]
public void EditorTextChanged(TestQuestion testQuestion)
{            
   ChangeHtml(testQuestion);         
}     

Attach behavior code:

 public class TestEditorStyleBehavior : Behavior<Editor>
    {
        public static readonly BindableProperty AttachBehaviorProperty = BindableProperty.CreateAttached(
            propertyName: "AttachBehavior", 
            returnType:typeof(object), 
            declaringType: typeof(TestEditorStyleBehavior), 
            defaultValue: null, 
            propertyChanged: OnAttachBehaviorChanged);

        public static object GetAttachBehavior(BindableObject view)
        {
            return (object)view.GetValue(AttachBehaviorProperty);
        }

        public static void SetAttachBehavior(BindableObject view, object value)
        {
            view.SetValue(AttachBehaviorProperty, value);
        }

        static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue)
        {
            Editor editor = view as Editor;
            if (editor == null)
            {
                return;
            }

            EventToCommandBehavior attachBehavior = newValue as EventToCommandBehavior;
            editor.Behaviors.Add(attachBehavior);
        }
    }

I am attaching event to my command but i dont understand how to get sender and event args inside my command. I need both of this arguments for my needs. I understand how to pass whole editor object or just model from data type but dont understand how to get event paramethers. Can u please explain how to do this?


Solution

  • You can try to create a custom view for your Editor.

    I achieved this function by inheriting parent class Entry. The same applies to Editor.

    You can refer to the following code:

    1.create a class MyEntry.cs and add necessary BindableProperty.

      public class MyEntry:Entry 
    {
        public MyEntry()
        {
            this.TextChanged += this.OnTextChanged;
        }
    
        public static readonly BindableProperty TextChangedCommandProperty =
            BindableProperty.Create(nameof(MyEntry.TextChangedCommand), typeof(ICommand), typeof(Entry));
    
        public static readonly BindableProperty TextChangedCommandParameterProperty =
            BindableProperty.Create(nameof(MyEntry.TextChangedCommandParameter), typeof(object), typeof(Entry));
    
        public ICommand TextChangedCommand
        {
            get => (ICommand)this.GetValue(MyEntry.TextChangedCommandProperty);
            set => this.SetValue(TextChangedCommandProperty, (object)value);
        }
    
        public object TextChangedCommandParameter
        {
            get => this.GetValue(MyEntry.TextChangedCommandParameterProperty);
            set => this.SetValue(TextChangedCommandParameterProperty, value);
        }
    
        private void OnTextChanged(object sender, TextChangedEventArgs e)
        {
            if (this.TextChangedCommand == null ||
                 !this.TextChangedCommand.CanExecute(this.TextChangedCommandParameter))
                return;
    
            this.TextChangedCommand.Execute(this.TextChangedCommandParameter);
        }
    }
    

    2.created a viewmodel (MyViewModel.cs)

    public class MyViewModel: INotifyPropertyChanged 
    {
    
        string inputValue;
        public string InputValue
        {
            set { SetProperty(ref inputValue, value); }
            get { return inputValue; }
        }
    
        public ICommand TextChangedCommand { get; set; }
    
        public MyViewModel() {
    
            TextChangedCommand = new Command(testcommand);
    
    
        }
        private void testcommand(object obj)
        {
            if (obj!= null)
            {
                MyViewModel viewModel = obj as MyViewModel;
    
                Console.WriteLine("---> input string is = " + viewModel.InputValue);
            }
        }
        bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Object.Equals(storage, value))
                return false;
            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
    

    3.Usage example:

    <?xml version="1.0" encoding="utf-8" ?> 
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:mauiApp0705="clr-namespace:MauiApp0705"
                 x:Class="MauiApp0705.MainPage">
    
        <ContentPage.BindingContext>
            <mauiApp0705:MyViewModel></mauiApp0705:MyViewModel>
        </ContentPage.BindingContext>
    
            <VerticalStackLayout
                Spacing="25"
                Padding="30,0"
                VerticalOptions="Center">
    
            <mauiApp0705:MyEntry 
               Text="{Binding InputValue}"
               HorizontalTextAlignment="Start"
               HorizontalOptions="FillAndExpand"
               VerticalOptions="Center"
               VerticalTextAlignment="Center"
               Keyboard='Text'
               ClearButtonVisibility="WhileEditing"
               TextChangedCommand="{Binding TextChangedCommand, Mode=OneTime}"
               TextChangedCommandParameter="{Binding Mode=OneTime}" >
            </mauiApp0705:MyEntry>
    
        </VerticalStackLayout>
    
    </ContentPage>