将参数动态传递给 Xamarin 中的 BindingContext
Dynamically pass argument to a BindingContext in Xamarin
我需要使用下载的 JSON 中的数据填充自定义 ListView。
这是我创建的自定义 ListView:
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<StackLayout Orientation="Vertical" Spacing="5" VerticalOptions="Center">
<StackLayout Orientation="Horizontal">
<Label Text="{Binding TradeDate}" Padding="25,0,0,0" FontSize="19" TextColor="Black"></Label>
<Label Text="{Binding TradeGain}" Padding="0,0,25,0" FontSize="19" FontAttributes="Bold" TextColor="Green" HorizontalOptions="EndAndExpand"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding TradeQty}" Padding="25,0,0,0" FontSize="16"></Label>
<Label Text="{Binding TradeEff}" Padding="0,0,25,0" FontSize="16" HorizontalOptions="EndAndExpand"></Label>
</StackLayout>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
然后我将 BindingContext 设置为 class 和 ItemSource:
<ContentPage.BindingContext>
<local:TradesView>
<x:Arguments>
<x:String>cacca</x:String>
</x:Arguments>
</local:TradesView>
</ContentPage.BindingContext>
这是在 BindingContext 中看到的 TradeView class:
不幸的是,我无法从这里下载 JSON,因为它需要身份验证,这当然由另一个 ContentPage 处理。
public class TradesView
{
public ObservableCollection<Trade> Trades { get; set; }
public TradesView(string trades)
{
Trades = new ObservableCollection<Trade>();
JArray jArray = JArray.Parse(trades);
foreach (JObject trade in jArray){
Trades.Add(new Trade(trade["date"].ToString(), trade["gain"].ToString(), trade["depth"].ToString(), "0"));
}
}
}
问题是现在我不知道如何继续,因为似乎没有办法将变量作为参数传递给 TradeView 构造函数,它应该处理 JSON 并用我的内容填充 ObservableCollection需要。
我只是觉得我的程序是错误的,我应该放弃我所做的很多事情,但是我真的不知道如何解决这个问题。
有几种方法可以解决这个问题。这是一个,它使用“工厂方法”(Create
) 创建包含您的视图的 页面 ,然后设置该页面的 Items
属性.
如果只有一个页面包含该视图,这是有意义的。
用法:
var names = new List<string> { "One", "Two", "Three", "Four" };
MainPage = SelfBoundPageWithCollection.Create(names);
SelfBoundPageWithCollection.xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestXFUWP.SelfBoundPageWithCollection">
<ContentPage.Content>
<StackLayout>
<CollectionView ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Name}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
SelfBoundPageWithCollection.xaml.cs:
public partial class SelfBoundPageWithCollection : ContentPage
{
public SelfBoundPageWithCollection()
{
InitializeComponent();
BindingContext = this;
}
public ObservableCollection<ItemModel> Items {
get => _items;
set {
_items = value;
OnPropertyChanged();
}
}
private ObservableCollection<ItemModel> _items;
public static SelfBoundPageWithCollection Create(List<string> names)
{
var it = new SelfBoundPageWithCollection();
it.FillItems(names);
return it;
}
// Can call this directly later, to replace Items collection.
public void FillItems(List<string> names)
{
var items = new ObservableCollection<ItemModel>();
foreach (var name in names) {
items.Add(new ItemModel(name));
}
Items = items;
}
}
或者要有一个单独的“ViewModel”(MVVM),这样做:
用法:
var names = new List<string> { "One", "Two", "Three", "Four" };
MainPage = PageWithCollection.Create(names);
PageWithCollection.xaml.cs:
public partial class PageWithCollection : ContentPage
{
public PageWithCollection()
{
InitializeComponent();
BindingContext = new ViewModelWithItems();
}
public static PageWithCollection Create(List<string> names)
{
var it = new PageWithCollection();
var vm = (ViewModelWithItems)it.BindingContext;
vm.FillItems(names);
return it;
}
}
ViewModelWithItems.cs:
public class ViewModelWithItems : Xamarin.Forms.BindableObject
{
public ViewModelWithItems()
{
}
public ObservableCollection<ItemModel> Items {
get => _items;
set {
_items = value;
OnPropertyChanged();
}
}
private ObservableCollection<ItemModel> _items;
public void FillItems(List<string> names)
{
var items = new ObservableCollection<ItemModel>();
foreach (var name in names) {
items.Add(new ItemModel(name));
}
Items = items;
}
}
以上均指该机型:
ItemModel.cs:
public class ItemModel
{
public ItemModel(string name)
{
Name = name;
}
public string Name { get; set; }
}
我需要使用下载的 JSON 中的数据填充自定义 ListView。
这是我创建的自定义 ListView:
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<StackLayout Orientation="Vertical" Spacing="5" VerticalOptions="Center">
<StackLayout Orientation="Horizontal">
<Label Text="{Binding TradeDate}" Padding="25,0,0,0" FontSize="19" TextColor="Black"></Label>
<Label Text="{Binding TradeGain}" Padding="0,0,25,0" FontSize="19" FontAttributes="Bold" TextColor="Green" HorizontalOptions="EndAndExpand"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding TradeQty}" Padding="25,0,0,0" FontSize="16"></Label>
<Label Text="{Binding TradeEff}" Padding="0,0,25,0" FontSize="16" HorizontalOptions="EndAndExpand"></Label>
</StackLayout>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
然后我将 BindingContext 设置为 class 和 ItemSource:
<ContentPage.BindingContext>
<local:TradesView>
<x:Arguments>
<x:String>cacca</x:String>
</x:Arguments>
</local:TradesView>
</ContentPage.BindingContext>
这是在 BindingContext 中看到的 TradeView class:
不幸的是,我无法从这里下载 JSON,因为它需要身份验证,这当然由另一个 ContentPage 处理。
public class TradesView
{
public ObservableCollection<Trade> Trades { get; set; }
public TradesView(string trades)
{
Trades = new ObservableCollection<Trade>();
JArray jArray = JArray.Parse(trades);
foreach (JObject trade in jArray){
Trades.Add(new Trade(trade["date"].ToString(), trade["gain"].ToString(), trade["depth"].ToString(), "0"));
}
}
}
问题是现在我不知道如何继续,因为似乎没有办法将变量作为参数传递给 TradeView 构造函数,它应该处理 JSON 并用我的内容填充 ObservableCollection需要。
我只是觉得我的程序是错误的,我应该放弃我所做的很多事情,但是我真的不知道如何解决这个问题。
有几种方法可以解决这个问题。这是一个,它使用“工厂方法”(Create
) 创建包含您的视图的 页面 ,然后设置该页面的 Items
属性.
如果只有一个页面包含该视图,这是有意义的。
用法:
var names = new List<string> { "One", "Two", "Three", "Four" };
MainPage = SelfBoundPageWithCollection.Create(names);
SelfBoundPageWithCollection.xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestXFUWP.SelfBoundPageWithCollection">
<ContentPage.Content>
<StackLayout>
<CollectionView ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Name}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
SelfBoundPageWithCollection.xaml.cs:
public partial class SelfBoundPageWithCollection : ContentPage
{
public SelfBoundPageWithCollection()
{
InitializeComponent();
BindingContext = this;
}
public ObservableCollection<ItemModel> Items {
get => _items;
set {
_items = value;
OnPropertyChanged();
}
}
private ObservableCollection<ItemModel> _items;
public static SelfBoundPageWithCollection Create(List<string> names)
{
var it = new SelfBoundPageWithCollection();
it.FillItems(names);
return it;
}
// Can call this directly later, to replace Items collection.
public void FillItems(List<string> names)
{
var items = new ObservableCollection<ItemModel>();
foreach (var name in names) {
items.Add(new ItemModel(name));
}
Items = items;
}
}
或者要有一个单独的“ViewModel”(MVVM),这样做:
用法:
var names = new List<string> { "One", "Two", "Three", "Four" };
MainPage = PageWithCollection.Create(names);
PageWithCollection.xaml.cs:
public partial class PageWithCollection : ContentPage
{
public PageWithCollection()
{
InitializeComponent();
BindingContext = new ViewModelWithItems();
}
public static PageWithCollection Create(List<string> names)
{
var it = new PageWithCollection();
var vm = (ViewModelWithItems)it.BindingContext;
vm.FillItems(names);
return it;
}
}
ViewModelWithItems.cs:
public class ViewModelWithItems : Xamarin.Forms.BindableObject
{
public ViewModelWithItems()
{
}
public ObservableCollection<ItemModel> Items {
get => _items;
set {
_items = value;
OnPropertyChanged();
}
}
private ObservableCollection<ItemModel> _items;
public void FillItems(List<string> names)
{
var items = new ObservableCollection<ItemModel>();
foreach (var name in names) {
items.Add(new ItemModel(name));
}
Items = items;
}
}
以上均指该机型:
ItemModel.cs:
public class ItemModel
{
public ItemModel(string name)
{
Name = name;
}
public string Name { get; set; }
}