【问题标题】:How can I pass Command parameter from EventToCommandBehavior如何从 EventToCommandBehavior 传递 Command 参数
【发布时间】:2022-01-26 21:23:22
【问题描述】:

我正在使用EventToCommandBehaviorEntry 控件。 Entry 位于 DataTemplate 内部,属于 Bindable stacklayout

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

这是我的行为类

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&lt;TendersList&gt; 时,命令没有命中。当我执行Command(async (args) =&gt; 时,我在args 中得到oldnewEntry,而不是我想从参数中获取itemitemId

如何获取当前记录/列表项。什么时候出现行为?

【问题讨论】:

    标签: xaml xamarin xamarin.forms behavior


    【解决方案1】:

    发生这种情况的原因是该方法的最后一行,每次您设置一个新事件时,它都会覆盖您在 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;
    }
    

    【讨论】:

      【解决方案2】:

      您想在触发事件RefreshCommand后获取条目的文本吗?

      如果是,您可以将Entry本身作为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"

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-12
        • 2016-09-24
        • 1970-01-01
        • 1970-01-01
        • 2021-07-09
        • 2011-06-15
        • 2018-12-25
        • 2021-02-19
        相关资源
        最近更新 更多