将参数动态传递给 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; }
}