将按钮绑定到列表视图dataTemplate中的命令

时间:2018-07-01 12:03:14

标签: listview xamarin xamarin.forms binding icommand

我遇到了这个解决方案,该解决方案应该绑定到根页面而不是不适用于我的列表视图(我正在尝试在列表视图中按下按钮并通过它传递列表视图项ID时执行命令)已给出Path = BindingContext.RequestAccepted)。无法在类型object的数据上下文中解析属性“ RequestAccepted”。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:viewModels="clr-namespace:XamarinApp.ViewModels;assembly=XamarinApp"
         x:Name="RequestsPage"
         x:Class="XamarinApp.ViewModels.Views.CustomerTransferRequestsPage">

<ContentPage.BindingContext>
    <viewModels:CustomerTransferRequestsViewModel/>
</ContentPage.BindingContext>

<ContentPage.Content>
    <StackLayout >
        <Label Text="لا يوجد لديك طلبات حالياً" IsVisible="{Binding EmptyLableVisible}"  ></Label>


        <ActivityIndicator IsRunning="{Binding IsLoading}" HorizontalOptions="FillAndExpand"
                           VerticalOptions="FillAndExpand"/>



        <ListView ItemsSource="{Binding RequestedItems}" 
                  HasUnevenRows="True"
                  ItemTapped="ListView_OnItemTapped"
        >

            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout>

                            <Label Text="{Binding RequestUserName}"></Label>
                            <Label Text="{Binding ItemsName}"></Label>
                            <Label Text="{Binding ItemsPrice}"></Label>

                            <StackLayout Orientation="Vertical">

                                <Button Text="قبول" Command="{Binding Source={x:Reference RequestsPage}, Path=BindingContext.RequestAccepted}"></Button>
                                <Button Text="رفض"></Button>

                            </StackLayout>


                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

    </StackLayout>
</ContentPage.Content>

viewModel

 public class CustomerTransferRequestsViewModel : INotifyPropertyChanged
{

  public CustomerTransferRequestsViewModel()
    {
        if (GetRequestedItems.CanExecute(null))
        {
            GetRequestedItems.Execute(null);
        }
    }
    ApiServices _apiServices = new ApiServices();

    private ObservableCollection<GetCustomerTransferOrderRespond> _requestedItems;
    private bool _emptyLableVisible;
    private bool _isLoading;

    public ObservableCollection<GetCustomerTransferOrderRespond> RequestedItems
    {
        get => _requestedItems;
        set
        {
            if (Equals(value, _requestedItems)) return;
            _requestedItems = value;
            OnPropertyChanged();
        }
    }

    public bool EmptyLableVisible
    {
        get => _emptyLableVisible;

        set
        {
            if (Equals(value, _emptyLableVisible)) return;
            _emptyLableVisible = value;
            OnPropertyChanged();
        }

    }

    public bool IsLoading { get => _isLoading; set 
        {
            if (Equals(value, _isLoading)) return;
            _isLoading = value;
            OnPropertyChanged();
        }
    }

    public ICommand GetRequestedItems
    {

        get
        {
            return new Command(async () =>
            {
                IsLoading = true;
                var accesstoken = Settings.AccessToken;
                RequestedItems = await _apiServices.GetCustomerTranferOrdersAsync(accesstoken);

                if (RequestedItems == null)
                {
                    EmptyLableVisible = true;
                    IsLoading = false;
                }
                else
                {
                    EmptyLableVisible = false;
                    IsLoading = false;
                }

            });
        }
    }


    public ICommand RequestAccepted
    {
        get
        {
            return new Command(async () =>
            {
                //RequestAccepted Logic

            });
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

3 个答案:

答案 0 :(得分:1)

我认为您需要做的是定义ICommand属性并使用Command进行分配,

在ViewModel中是这样的。

public ICommand RequestAccepted
    {
        get;
        set;
    }

在构造函数中,您可以使用以下命令分配属性,

public CustomerTransferRequestsViewModel()
    {
        if (GetRequestedItems.CanExecute(null))
        {
            GetRequestedItems.Execute(null);
        }
        RequestAccepted = new Command(() =>
        {
            //code goes here
        });

    }

.XAML页面

<?xml version="1.0" encoding="utf-8"?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Name="RequestsPage"
    xmlns:local="clr-namespace:Stack51123113"
    x:Class="Stack51123113.MainPage">
    <ContentPage.BindingContext>
        <local:CustomerTransferRequestsViewModel />
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout>
            <Label
                Text="لا يوجد لديك طلبات حالياً">
            </Label>
            <ListView
                ItemsSource="{Binding RequestedItems}"
                HasUnevenRows="True">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout>
                                <Label
                                    Text="{Binding RequestUserName}">
                                </Label>
                                <Label
                                    Text="{Binding ItemsName}">
                                </Label>
                                <Label
                                    Text="{Binding ItemsPrice}">
                                </Label>
                                <StackLayout
                                    Orientation="Vertical">
                                    <Button
                                        Text="قبول"
                                        Command="{Binding Source={x:Reference RequestsPage}, Path=BindingContext.RequestAccepted}">
                                    </Button>
                                    <Button
                                        Text="رفض">
                                    </Button>
                                </StackLayout>
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

ViewModel

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Xamarin.Forms;

namespace Stack51123113
{
    public class CustomerTransferRequestsViewModel : INotifyPropertyChanged
    {

        public CustomerTransferRequestsViewModel()
        {
            if (GetRequestedItems.CanExecute(null))
            {
                GetRequestedItems.Execute(null);
            }
            RequestAccepted = new Command(() =>
            {
                //code goes here
            });

        }
        ApiServices _apiServices = new ApiServices();

        private ObservableCollection<GetCustomerTransferOrderRespond> _requestedItems;
        private bool _emptyLableVisible;
        private bool _isLoading;

        public ObservableCollection<GetCustomerTransferOrderRespond> RequestedItems
        {
            get => _requestedItems;
            set
            {
                if (Equals(value, _requestedItems)) return;
                _requestedItems = value;
                OnPropertyChanged();
            }
        }

        public bool EmptyLableVisible
        {
            get => _emptyLableVisible;

            set
            {
                if (Equals(value, _emptyLableVisible)) return;
                _emptyLableVisible = value;
                OnPropertyChanged();
            }

        }

        public bool IsLoading
        {
            get => _isLoading; set
            {
                if (Equals(value, _isLoading)) return;
                _isLoading = value;
                OnPropertyChanged();
            }
        }

        public ICommand GetRequestedItems
        {

            get
            {
                return new Command(async () =>
                {
                    RequestedItems = new ObservableCollection<GetCustomerTransferOrderRespond>(new List<GetCustomerTransferOrderRespond>()
                    {
                        new GetCustomerTransferOrderRespond(),
                        new GetCustomerTransferOrderRespond(),
                    });
                });
            }
        }

        public ICommand RequestAccepted
        {
            get;
            set;
        }


        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class ApiServices
    {
        public ApiServices()
        {
        }
    }

    public class GetCustomerTransferOrderRespond
    {
    }
}

答案 1 :(得分:0)

在ListView中,使用“命令参数”和“单击”来分别获取每个按钮的命令。

xaml

 <Button CommandParameter="{Binding ItemID}" Clicked="ItemClicked" />

xaml.cs

 async void ItemClicked(object sender, System.EventArgs e)
 {
     var Button = (Button)sender;
     String Value = Button.CommandParameter.ToString(); // This gives the Item ID
 }

希望这会有所帮助。

答案 2 :(得分:0)

我用来为列表中的每个项目创建一个ViewModel。如果我已经有一个模型,则可以在ViewModel中使用它,通常在一个名为Item的属性中。因此,在绑定中,我将编写例如Item.RequestUserName。但这使我可以向ViewModel添加命令并对其进行绑定。