TextChanged 事件未被触发 - MVVM Xamarin Forms

TextChanged Event is not getting fired - MVVM Xamarin Forms

我在 Bindable StackLayoutDataTemplate 中有一个 Entry 控件。我已经使用 Behavior 实现了 Entry 控件的 TextChanged 事件,但是事件没有被触发。

这是xaml代码

<Frame Padding="20,14,10,10"
       Grid.Column="1"
       BorderColor="LightGray">
    <Entry MaxLength="5"
           Keyboard="Numeric"
           HeightRequest="42">
        <Entry.Behaviors>
            <helpers:EventToCommandBehavior Command="{Binding RefreshCommand}"
            EventName="TextChanged"></helpers:EventToCommandBehavior>
        </Entry.Behaviors>
    </Entry>
</Frame>

单个文件中的行为类

namespace Product.Helpers
{
    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 string EventName
        {
            get { return (string)GetValue(EventNameProperty); }
            set { SetValue(EventNameProperty, value); }
        }
        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

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

        protected override void OnDetachingFrom(VisualElement bindable)
        {
            DeregisterEvent(EventName);
            base.OnDetachingFrom(bindable);
        }
        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);
        }

        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) || 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;

            resolvedParameter = eventArgs;

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

    }

    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;
        }
    }
}

命令的 ViewModel 代码

public ICommand RefreshCommand
{
    get
    {
        return new Command(async (args) =>
        {
            Refresh();
        });
    }
}
public void Refresh()
{
    var textbox = Subtotal;
} 

我从这里获取代码 csharpcorer - behavior。我怎样才能让它发挥作用?

你找不到它的原因是因为上下文。

为您当前的 ContentPage 命名:

<ContentPage 
...
x:Name="currentPage"/>

那么您的条目将类似于:

<Entry MaxLength="5"
       Keyboard="Numeric"
       HeightRequest="42">
    <Entry.Behaviors>
        <helpers:EventToCommandBehavior Command="{Binding BindingContext.RefreshCommand, Source={x:Reference currentPage}}"
        EventName="TextChanged"></helpers:EventToCommandBehavior>
    </Entry.Behaviors>
</Entry>