事件到命令行为不执行命令



我正在使用此处找到的事件到命令行为在列表视图的 ItemTapped 事件中实现命令。我将 EventToCommandBehavior 和 BehaviorBase 类复制到我的项目中。

这是我的观点

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

和我的视图模型

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永远不会被执行,EventToCommandBehavior类的方法OnEvent会被执行,但行Command.Execute(solveParameter(;只是什么都不做。

我正在使用PropertyChanged.Fody软件包,如果它有任何用处。

任何帮助不胜感激,谢谢。

从可重用的 EventToCommandBehavior,我建议你可以在代码中使用 Converter,我创建简单的你可以看看:

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

行为库.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,Command 属性是绑定到关联 ViewModel 的 command1 属性的数据,而 Converter 属性设置为 TappedItemConverter 实例,该实例从 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

假设您的绑定上下文已正确设置为 UsuariosViewModel 的实例,我在这里看到的问题是您没有传递命令参数。您的命令接受 usuarios,但您需要通过 EventToCommandBehavior 上的 CommandParameter 属性传递该命令。

我还注意到您ListView_ItemTapped定义,但我不确定您在该方法中做什么。不应该要求使命令工作,但也许您正在将其用于其他目的。

最新更新