c# - 绑定(bind)不适用于 xamarin 形式的 MVVM。未找到 'ItemSelected' 的属性、可绑定(bind)属性或事件,

标签 c# wpf mvvm xamarin.forms

我正在尝试使用 xamarin 中的 MVVM 将我的 ListView ItemSelected 与我的 ViewModel 绑定(bind)。对于一些我得到一个编译时错误 "没有找到 'ItemSelected' 的属性、可绑定(bind)属性或事件,或者值和属性之间的类型不匹配。调度程序"我已经在后面的 UI 代码中绑定(bind)了我的 ViewModel。下面是我的代码

后面的 UI 代码

  [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class ClientPage : ContentPage
    {
        private ClientViewModel viewModel {get;}
        public ClientPage()
        {
            InitializeComponent();
            BindingContext = viewModel = new ClientViewModel();
        }
    }

查看型号
 public class ClientViewModel : BaseViewModel
    {
 public ObservableCollection<Client> Clients { get; set; }
        private Client _SelectedItem { get; set; }
        public Client SelectedClient
        {
            get
            {
                return _SelectedItem;
            }
            set
            {
                _SelectedItem = value;
                Task.Run(async () => await ShowClientDetailModal(_SelectedItem));
            }
        }
    }

用户界面
 <StackLayout>
        <ListView x:Name="ClientListView"
                  ItemsSource="{Binding Clients}"
                  VerticalOptions="FillAndExpand"
                  HasUnevenRows="true"
                  RefreshCommand="{Binding LoadClientsCommand}"
                  IsPullToRefreshEnabled="True"
                  IsRefreshing="{Binding IsBusy, Mode=OneWay}"
                  CachingStrategy="RecycleElement"
                  ItemSelected="{Binding SelectedClient}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.ContextActions>
                            <MenuItem Clicked="OnDelete_Clicked" Text="Delete" CommandParameter="{Binding .}"/>
                        </ViewCell.ContextActions>
                        <StackLayout Padding="10">
                                   <Label Text="{Binding FullName}"
                                   d:Text="{Binding .}"
                                   LineBreakMode="NoWrap"
                                   Style="{DynamicResource ListItemTextStyle}" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>

最佳答案

ItemSelected 是一个事件,而不是可绑定(bind)属性您正在寻找的是一种将您的事件转换为命令的行为

如果您查看 Microsoft 文档,您可以在此处找到:https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/behaviors/reusable/event-to-command-behavior

行为:

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

此外,要使其正常工作,您将需要 BehaviorBase 类,该类可以在下面找到:
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;
    }
}

用法:
   <ListView.Behaviors>
            <local:EventToCommandBehavior EventName="ItemSelected" Command="{Binding SelectedClient}" />
   </ListView.Behaviors>

如果您有任何问题,Goodluck 随时回复

关于c# - 绑定(bind)不适用于 xamarin 形式的 MVVM。未找到 'ItemSelected' 的属性、可绑定(bind)属性或事件,,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59609838/

相关文章:

silverlight - 使用 MVVM 模式实现 Telerik VirtualQueryableCollectionView

c# - EnumerateFiles in drive 使用 LINQ 跳过回收站

c# - NHibernate - 使用 ICriteria 加入子查询

c# - 单声道项目: How do I assign a C# generic list as a TableView's datasource?

WPF + 多个应用程序实例之间的通信

WPF:MVVM:命令与 CallMethodAction?

c# - 如何将Excel工作表中的数据导入到C#中的数据表中?

c# - 如何将当前 VS 主题应用于现有控件

c# - 使用 HwndHost 在 WPF 中托管外部窗口的正确方法

c# - 使用 MVVM 通过 ViewModel 属性冒泡 INotifyPropertyChanged 事件的好方法是什么?