Поведение события к команде не выполняет команду - PullRequest
1 голос
/ 01 февраля 2020

Я использую Event to Command Поведение, найденное здесь , чтобы реализовать команду в событии ItemTapped объекта ListView. Я скопировал классы EventToCommandBehavior и BehaviorBase в свой проект.

Вот мой View

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:d="http://xamarin.com/schemas/2014/forms/design"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:AppVentas.Behaviors"
         mc:Ignorable="d"
         x:Class="AppVentas.Views.UsuariosView">
<ContentPage.Content>
    <ListView HasUnevenRows="True"
              ItemsSource="{Binding Usuarios}"
              ItemTapped="ListView_ItemTapped">
        <ListView.Behaviors>
            <local:EventToCommandBehavior 
                EventName="ItemTapped" 
                Command="{Binding OpenChatCommand}"/>
        </ListView.Behaviors>
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Label Text="{Binding Nombre}"/>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage.Content>

И мой ViewModel

public class UsuariosViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public ObservableCollection<Usuarios> Usuarios { get; set; }
    public ICommand OpenChatCommand { get; set; }

    private UsuarioController usuarioController = new UsuarioController();

    public UsuariosViewModel()
    {
        Usuarios = new ObservableCollection<Usuarios>(usuarioController.Get().Where(i => i.Token == null));

        OpenChatCommand = new Command<Usuarios>(OpenChat);
    }


    void OpenChat(Usuarios usuario)
    {
        //trying to do something
    }
}

Проблема в том, что OpenChatCommand никогда не выполняется, метод OnEvent of класс EventToCommandBehavior do выполняется, но строка Command.Execute (resolvedParameter); просто ничего не делает.

Я использую пакет PropertyChanged.Fody, если он мне нужен.

Любая помощь приветствуется, спасибо.

Ответы [ 2 ]

0 голосов
/ 03 февраля 2020

От Многоразовый EventToCommandBehavior , я предлагаю вам использовать конвертер в вашем коде, я создаю простой, на который вы можете посмотреть:

<ContentPage
x:Class="Listviewsample.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:converter="clr-namespace:Listviewsample"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:local="clr-namespace:Listviewsample.Behaviors"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ContentPage.Resources>
    <converter:TappedItemConverter x:Key="converter1" />
</ContentPage.Resources>

<StackLayout>
    <!--  Place new controls here  -->
    <ListView
        x:Name="listview1"
        HasUnevenRows="True"
        ItemsSource="{Binding images}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout>
                        <Label Text="{Binding title}" />
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
        <ListView.Behaviors>
            <local:EventToCommandBehavior
                Command="{Binding command1}"
                Converter="{StaticResource converter1}"
                EventName="ItemTapped" />
        </ListView.Behaviors>
    </ListView>
</StackLayout>

public partial class MainPage : ContentPage
{
    public ObservableCollection<imagemodel> images { get; set; }
    public Command command1 { get; set; }
    public MainPage()
    {
        InitializeComponent();
        images = new ObservableCollection<imagemodel>()
        {
            new imagemodel(){title="image 1"},
            new imagemodel(){title="image 2"},
            new imagemodel(){title="image 3"}
        };
        command1 = new Command<imagemodel>(commandpage);

        this.BindingContext = this;
    }
    private void commandpage(imagemodel m)
    {
        Console.WriteLine("the image model title is {0}",m.title.ToString());
    }


}

public class imagemodel
{
    public string title { get; set; }

}

The BehaviorBase.cs:

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

}

EventToCommandBehavior.cs:

 public class EventToCommandBehavior : BehaviorBase<View>
{
    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(View bindable)
    {
        base.OnAttachedTo(bindable);
        RegisterEvent(EventName);
    }
    protected override void OnDetachingFrom(View 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);

    }

}

Свойство Converter.cs поведения - это данные, связанные со свойством command1 связанного с ним свойства. ViewModel, в то время как свойство Converter установлено на экземпляр TappedItemConverter, который возвращает элемент Tapped объекта ListView из ItemTappedEventArgs.

 public class TappedItemConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var eventArgs = value as ItemTappedEventArgs;
        return eventArgs.Item;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Вот пример на github, вы можете посмотреть:

https://github.com/CherryBu/Eventtocommand

0 голосов
/ 02 февраля 2020

Предполагая, что ваш bindingcontext правильно установлен для экземпляра UsuariosViewModel, проблема, которую я вижу здесь, заключается в том, что вы не передаете параметр команды. Ваша команда принимает Usuar ios, но вам нужно передать это через свойство CommandParameter в EventToCommandBehavior.

Я также заметил, что у вас определен ListView_ItemTapped, но я не уверен, что вы делаете в этом методе. Не нужно заставлять команду работать, но, возможно, вы используете ее для чего-то другого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...