0

In my MainPage I am using a Custom Control which is an Entry and 2 buttons. I need to use the ".isFocused" property for the Entry in the ViewModel to do something, how can I do it?

I must get x:Name of the entry? I dont know can I do this, but I need to use .isFocused for the entry,so that when I click on the entry, a menu that I have is closed.

My Code:

CustomContol.xaml:

<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
    x:Class="Aname.Xamarin.UIControls.Controls.CKEditor"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Name="CKEditorView">
    <ContentView.Content>

        <StackLayout>



            <Frame
                Margin="0,0,0,2"
                Padding="0,0,0,0"
                BackgroundColor="White"
                BorderColor="{Binding BorderColor}"
                CornerRadius="{Binding CornerRadius}"
                HasShadow="False">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>


                    <ImageButton
                        Grid.Column="0"
                        Margin="10,0,0,0"
                        BackgroundColor="Transparent"
                        Command="{Binding Source={x:Reference CKEditorView}, Path=BindingContext.EmojiCommand}"
                        HorizontalOptions="Start"
                        Source="{Binding LeftSideIcon}"
                        WidthRequest="30" />

                    <Entry
                        x:Name="EntryControl"
                        Grid.Column="1"
                        Margin="0,0,50,0"
                        HorizontalOptions="Fill"
                        Keyboard="Chat"
                        Placeholder="{Binding Placeholder}"
                        Text="{Binding EntryText}"
                        TextColor="Black" />
                    <ImageButton
                        Grid.Column="1"
                        Margin="0,0,10,0"
                        BackgroundColor="Transparent"
                        Command="{Binding Source={x:Reference CKEditorView}, Path=BindingContext.SendCommand}"
                        HorizontalOptions="End"
                        Source="{Binding Source={x:Reference CKEditorView}, Path=RightSideIcon}"
                        WidthRequest="35" />


                </Grid>
            </Frame>


            <Frame Margin="0,-8,0,0" IsVisible="{Binding Source={x:Reference CKEditorView}, Path=BoxVisible}">
                <CollectionView
                    Margin="-10,-15,-10,-10"
                    HeightRequest="250"
                    ItemsSource="{Binding Source={x:Reference CKEditorView}, Path=EmojiItemSource}"
                    VerticalScrollBarVisibility="Never">

                    <CollectionView.ItemsLayout>
                        <GridItemsLayout Orientation="Horizontal" Span="5" />
                    </CollectionView.ItemsLayout>
                    <CollectionView.ItemTemplate>

                        <DataTemplate>
                            <ImageButton
                                Padding="5"
                                BackgroundColor="Transparent"
                                Command="{Binding Source={x:Reference CKEditorView}, Path=BindingContext.MethodCommandEmoji}"
                                CommandParameter="{Binding EmojiMethodCommand}"
                                HeightRequest="44"
                                Source="{Binding EmojiSource}"
                                WidthRequest="44" />
                        </DataTemplate>
                    </CollectionView.ItemTemplate>

                </CollectionView>
            </Frame>


        </StackLayout>

    </ContentView.Content>
</ContentView>

MainPage.xaml:

  <StackLayout AbsoluteLayout.LayoutBounds="0,1,AutoSize,AutoSize" AbsoluteLayout.LayoutFlags="PositionProportional">
            <fav:CKEditor
                x:Name="entrycontrol"
                BorderColor="{Binding BorderColor}"
                BoxVisible="{Binding IsVisible}"
                CornerRadius="{Binding CornerRadius}"
                EmojiItemSource="{Binding EmojiList}"
                LeftSideIcon="{Binding LeftSideIcon}"
                Placeholder="{Binding Placeholder}"
                RightSideIcon="{Binding RightSideIcon}"
                Text="{Binding EntryText}" />
        </StackLayout>
  • Does this answer your question? [Set focus on TextBox in WPF from view model](https://stackoverflow.com/questions/1356045/set-focus-on-textbox-in-wpf-from-view-model) Please see the accepted answer in that post, it should help. Also it would help to include your VM and what you've tried so we could actually help you further. – Trevor Oct 27 '20 at 13:02
  • 1
    you can just bind `IsFocused` to a property in your VM, or use the `Focused` event – Jason Oct 27 '20 at 13:05

1 Answers1

-1

You could use EventToCommand Behavior.

Define the following classes

public class EventToCommandBehavior : BehaviorBase<VisualElement>
{
    Delegate eventHandler;

    public static readonly BindableProperty EventNameProperty = BindableProperty.Create("EventName", typeof(string), typeof(EventToCommandBehavior), null, propertyChanged: OnEventNameChanged);
    public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(EventToCommandBehavior), null);
    public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create("CommandParameter", typeof(object), typeof(EventToCommandBehavior), null);
    public static readonly BindableProperty InputConverterProperty = BindableProperty.Create("Converter", typeof(IValueConverter), typeof(EventToCommandBehavior), null);

    public string EventName
    {
        get { return (string)GetValue(EventNameProperty); }
        set { SetValue(EventNameProperty, value); }
    }

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public object CommandParameter
    {
        get { return GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }

    public IValueConverter Converter
    {
        get { return (IValueConverter)GetValue(InputConverterProperty); }
        set { SetValue(InputConverterProperty, value); }
    }

    protected override void OnAttachedTo(VisualElement bindable)
    {
        base.OnAttachedTo(bindable);
        RegisterEvent(EventName);
    }

    protected override void OnDetachingFrom(VisualElement bindable)
    {
        DeregisterEvent(EventName);
        base.OnDetachingFrom(bindable);
    }

    void RegisterEvent(string name)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            return;
        }

        EventInfo eventInfo = AssociatedObject.GetType().GetRuntimeEvent(name);
        if (eventInfo == null)
        {
            throw new ArgumentException(string.Format("EventToCommandBehavior: Can't register the '{0}' event.", EventName));
        }
        MethodInfo methodInfo = typeof(EventToCommandBehavior).GetTypeInfo().GetDeclaredMethod("OnEvent");
        eventHandler = methodInfo.CreateDelegate(eventInfo.EventHandlerType, this);
        eventInfo.AddEventHandler(AssociatedObject, eventHandler);
    }

    void DeregisterEvent(string name)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            return;
        }

        if (eventHandler == null)
        {
            return;
        }
        EventInfo eventInfo = AssociatedObject.GetType().GetRuntimeEvent(name);
        if (eventInfo == null)
        {
            throw new ArgumentException(string.Format("EventToCommandBehavior: Can't de-register the '{0}' event.", EventName));
        }
        eventInfo.RemoveEventHandler(AssociatedObject, eventHandler);
        eventHandler = null;
    }

    void OnEvent(object sender, object eventArgs)
    {
        if (Command == null)
        {
            return;
        }

        object resolvedParameter;
        if (CommandParameter != null)
        {
            resolvedParameter = CommandParameter;
        }
        else if (Converter != null)
        {
            resolvedParameter = Converter.Convert(eventArgs, typeof(object), null, null);
        }
        else
        {
            resolvedParameter = eventArgs;
        }

        if (Command.CanExecute(resolvedParameter))
        {
            Command.Execute(resolvedParameter);
        }
    }

    static void OnEventNameChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var behavior = (EventToCommandBehavior)bindable;
        if (behavior.AssociatedObject == null)
        {
            return;
        }

        string oldEventName = (string)oldValue;
        string newEventName = (string)newValue;

        behavior.DeregisterEvent(oldEventName);
        behavior.RegisterEvent(newEventName);
    }
}

And

public class BehaviorBase<T> : Behavior<T> where T : BindableObject
{
    public T AssociatedObject { get; private set; }

    protected override void OnAttachedTo(T bindable)
    {
        base.OnAttachedTo(bindable);
        AssociatedObject = bindable;

        if (bindable.BindingContext != null)
        {
            BindingContext = bindable.BindingContext;
        }

        bindable.BindingContextChanged += OnBindingContextChanged;
    }

    protected override void OnDetachingFrom(T bindable)
    {
        base.OnDetachingFrom(bindable);
        bindable.BindingContextChanged -= OnBindingContextChanged;
        AssociatedObject = null;
    }

    void OnBindingContextChanged(object sender, EventArgs e)
    {
        OnBindingContextChanged();
    }

    protected override void OnBindingContextChanged()
    {
        base.OnBindingContextChanged();
        BindingContext = AssociatedObject.BindingContext;
    }
}

in Custom Control

<StackLayout>
            <Entry
                        x:Name="EntryControl"
                        Grid.Column="1"
                        Margin="0,0,50,0"
                        HorizontalOptions="Fill"
                        Keyboard="Chat"
                        Placeholder="{Binding Placeholder}"
                        Text="{Binding EntryText}"
                        TextColor="Black" >

                <Entry.Behaviors>
                    <local:EventToCommandBehavior EventName="Focused" Command="{Binding Source={x:Reference CKEditorView},Path=FocusedCommand}" CommandParameter="True"/>
                    <local:EventToCommandBehavior EventName="Unfocused" Command="{Binding Source={x:Reference CKEditorView},Path=FocusedCommand}" CommandParameter="False"/>
                </Entry.Behaviors>

            </Entry>
        </StackLayout>
public static readonly BindableProperty FocusedCommandProperty =
                   BindableProperty.Create(nameof(FocusedCommand), typeof(ICommand), typeof(CKEditor));

public ICommand FocusedCommand
{
   get => (ICommand)GetValue(FocusedCommandProperty);
   set => SetValue(FocusedCommandProperty, value);
}

in ContentPage

 <local:CKEditor  FocusedCommand="{Binding FocusedCommand}" />

in ViewModel

public ICommand FocusedCommand { get; set; }
FocusedCommand = new Command((arg)=> {

    bool isFocused = (bool)arg;
            
    if(isFocused)
    {
         //focused
    }

    else
    {
       //unfocused
    }
});
Lucas Zhang
  • 18,630
  • 3
  • 12
  • 22