将按钮绑定到列表视图数据模板中的命令
Binding button to command inside listview dataTemplate
我遇到了这个解决方案,它应该绑定到根页面而不是 listview,它对我不起作用(我正在尝试在 listview 中按下按钮时执行命令并传递 listview 项目 ID)现在(Path=BindingContext.RequestAccepted) Cannot resolve 属性 "RequestAccepted" in data context of type object .
<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>
视图模型
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));
}
}
在 ListView 中,使用 'command parameter' 和 'clicked' 分别获取每个按钮的命令。
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
}
希望对您有所帮助。
我曾经为列表中的每个项目创建一个 ViewModel。如果我已经有一个模型,我会在 ViewModel 中使用它,通常在一个名为 Item 的 属性 中。所以在绑定中我会写 Item.RequestUserName 例如。但这使我可以向 ViewModel 添加命令并绑定它们。
我认为您需要做的是定义 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
{
}
}
我遇到了这个解决方案,它应该绑定到根页面而不是 listview,它对我不起作用(我正在尝试在 listview 中按下按钮时执行命令并传递 listview 项目 ID)现在(Path=BindingContext.RequestAccepted) Cannot resolve 属性 "RequestAccepted" in data context of type object .
<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>
视图模型
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));
}
}
在 ListView 中,使用 'command parameter' 和 'clicked' 分别获取每个按钮的命令。
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
}
希望对您有所帮助。
我曾经为列表中的每个项目创建一个 ViewModel。如果我已经有一个模型,我会在 ViewModel 中使用它,通常在一个名为 Item 的 属性 中。所以在绑定中我会写 Item.RequestUserName 例如。但这使我可以向 ViewModel 添加命令并绑定它们。
我认为您需要做的是定义 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
{
}
}