如何从 EventToCommandBehavior 传递 Command 参数

How can I pass Command parameter from EventToCommandBehavior

我正在使用 EventToCommandBehaviorEntry 控件。 EntryBindable stacklayoutDataTemplate 内。

我想将当前项目作为命令参数传递。我做不到。下面是我的代码。

这是我的行为class

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 object CommandParameter
    {
        get { return GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }
    public IValueConverter Converter
    {
        get { return (IValueConverter)GetValue(InputConverterProperty); }
        set { SetValue(InputConverterProperty, value); }
    }
    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);
        behavior.CommandParameter = 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) || 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);
    }

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

这是我的xaml代码

<Entry     
MaxLength="5"
HorizontalOptions="Center"
HeightRequest="42">
<Entry.Behaviors>
<helpers:EventToCommandBehavior
    Command="{Binding BindingContext.RefreshCommand, Source={x:Reference multitenderPage}}"
             CommandParameter="{Binding .}" EventName="TextChanged"></helpers:EventToCommandBehavior>
</Entry.Behaviors>
</Entry>

这是视图模型代码

public ICommand RefreshCommand { get; set; }
RefreshCommand = new Command<TendersList>(Refresh1);

当我执行 Command<TendersList> 时,命令没有命中。当我执行 Command(async (args) => 时,我在 args 中得到 oldnew Entry 的值,而不是我想得到 itemitemId 来自参数

如何获取列表的当前 record/item。当行为发生时?

发生这种情况的原因是此方法的最后一行,每次您设置新事件时,它都会覆盖您在 Command 参数中的任何内容,并将其替换为该特定对象:

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);
    behavior.CommandParameter = bindable;
}

是否要在触发事件后获取条目的文本 RefreshCommand

如果是,您可以将条目本身作为 CommandParameter 的参数传递。

请参考以下代码:

        <StackLayout BindableLayout.ItemsSource="{Binding User.Items}"
                     Orientation="Vertical"
                     Margin="0,10,0,0"
                     Spacing="20">
            <BindableLayout.ItemTemplate>
                <DataTemplate>
                    <Entry  x:Name="myEntry"   MaxLength="5"
                            HorizontalOptions="FillAndExpand" HeightRequest="42">
                        <Entry.Behaviors>
                            <bindablelayoutdemo:EventToCommandBehavior
         Command="{Binding BindingContext.RefreshCommand, Source={x:Reference myPage}}"
         CommandParameter="{x:Reference myEntry}"  EventName="TextChanged"></bindablelayoutdemo:EventToCommandBehavior>
                        </Entry.Behaviors>

                    </Entry>
                </DataTemplate>
            </BindableLayout.ItemTemplate>
        </StackLayout>

注:

myPage是当前页的x:Name="myPage"