从View Model绑定到ListView项目的tapped属性

Jar*_*ves 15 c# xaml mvvm xamarin xamarin.forms

我正在尝试使用itemtapped属性将事件绑定到菜单页面上的ListView.目前我在我的应用程序中使用MVVM(Xamarin表单实验室)框架.我想要完成的是当用户点击菜单项时,应用导航到正确的视图.

这是xaml代码:

<ListView x:Name="list"
        ItemsSource="{Binding MenuItems}" 
        SelectedItem="{Binding SelectedItem}" 
        ItemTapped= SET-BINDING-HERE >
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell>
        <ViewCell.View>
          //setup template here
        </ViewCell.View>
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate> 
</ListView>
Run Code Online (Sandbox Code Playgroud)

我想将itemtapped事件绑定到此函数:

public void NavigateTo(object sender, ItemTappedEventArgs args)
  {
      var test = args.Item as MenuModel;
      cPageTypes.GetByKey(test.CommandParameter)
                .SwitchRootPage(AIMCore.ViewModels.ElliottBaseViewModel.MasterPage);
      list.SelectedItem = null;
      AIMCore.ViewModels.BaseViewModel.MasterPage.IsPresented = false;
  }
Run Code Online (Sandbox Code Playgroud)

如果我将函数添加到视图后面的代码然后设置ItemTapped ='NavigatTo ',我现在可以使用它,但这似乎是错误的,因为它击败了MVVM概念.我真正想做的是将事件绑定到我的ViewModel中的相同功能,如下所示:

<ListView x:Name="list"
        ItemsSource="{Binding MenuItems}" 
        SelectedItem="{Binding SelectedItem}" 
        ItemTapped= "{Binding NavigateTo}" > // this binding is to the ViewModel
Run Code Online (Sandbox Code Playgroud)

然而,这不起作用或我没有正确地做到这一点.当我尝试以这种方式实现它时代码生成和错误.

错误: Xamarin.Forms.Xaml.XamlParseException:在Xamarin.Forms.Xaml.BaseValueNode.SetPropertyValue中找不到名称ItemTapped的属性

Nir*_*hta 26

我遵循相同的架构,通过创建自定义列表控件并使用命令创建了1个可绑定属性,我使用以下代码在View模型中覆盖:

我的PCL中的自定义控制[.cs]页面

using System;
using System.Windows.Input;
using Xamarin.Forms;


namespace YourNS {

    public class ListView : Xamarin.Forms.ListView {

        public static BindableProperty ItemClickCommandProperty = BindableProperty.Create<ListView, ICommand>(x => x.ItemClickCommand, null);


        public ListView() {
            this.ItemTapped += this.OnItemTapped;
        }


        public ICommand ItemClickCommand {
            get { return (ICommand)this.GetValue(ItemClickCommandProperty); }
            set { this.SetValue(ItemClickCommandProperty, value); }
        }


        private void OnItemTapped(object sender, ItemTappedEventArgs e) {
            if (e.Item != null && this.ItemClickCommand != null && this.ItemClickCommand.CanExecute(e)) {
                this.ItemClickCommand.Execute(e.Item);
                this.SelectedItem = null;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的XAML页面

<ContentPage ...
             xmlns:local="clr-namespace:Samples.Views;assembly=Your Assebly Name">

<local:ListView ItemClickCommand="{Binding Select}" 
        ItemsSource="{Binding List}">
Run Code Online (Sandbox Code Playgroud)

在我的视图模型中[在这个例子中,我只打开了对话框操作表

private Command<Signature> selectCmd;
        public Command<Signature> Select {
            get {
                this.selectCmd = this.selectCmd ?? new Command<Signature>(s => 
                    this.dialogs.ActionSheet(new ActionSheetConfig()
                        .Add("View", () => {
                            if (!this.fileViewer.Open(s.FilePath))
                                this.dialogs.Alert(String.Format("Could not open file {0}", s.FileName));
                        })
                        .Add("Cancel")
                    )
                );
                return this.selectCmd;
            }
        }
Run Code Online (Sandbox Code Playgroud)

  • @Thierry:您使用的是<ListView>还是<local:ListView>?ItemClickCommand未在Xamarin.Forms附带的内置ListView中定义.这里的答案继承自ListView,使用名为ItemClickCommand的新属性创建自己的自定义ListView.要使用它,您需要将正确的xmlns定义添加到XAML的顶部,并使用<local:ListView>或<[whatever]:ListView>,其中[whatever]是您定义的xmlns. (2认同)

Chr*_*the 7

或者,您可以使用附加行为

public static class ListViewAttachedBehavior
{
    public static readonly BindableProperty CommandProperty =
        BindableProperty.CreateAttached (
            "Command",
            typeof(ICommand),
            typeof(ListViewAttachedBehavior),
            null,
            propertyChanged:OnCommandChanged);

    static void OnCommandChanged (BindableObject view, object oldValue, object newValue)
    {
        var entry = view as ListView;
        if (entry == null) 
            return;

        entry.ItemTapped += (sender, e) => 
            {
                var command = (newValue as ICommand);
                if(command == null)
                    return;

                if(command.CanExecute(e.Item))
                {
                    command.Execute(e.Item);
                }

            };
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在ListView上调用它

 <ListView
        RowHeight="70"
        x:Name="AcquaintanceListView"
        b:ListViewAttachedBehavior.Command="{Binding ItemSelectedCommand}"
        ItemsSource="{Binding Acquaintances}">
Run Code Online (Sandbox Code Playgroud)