将ViewModel属性与Xamarin中的ViewView绑定

时间:2017-09-04 17:52:32

标签: c# .net xamarin mvvm xamarin.forms

我是Xamarin的新手。我试图将属性值与ListView绑定,但没有取得任何成功。尝试在互联网上搜索,但它没有奏效。此外,属性更改事件始终为null。这是我的ViewModel

namespace DemoApp.ViewModels
{
    class MainViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<ShippingDetail> ShippingDetailList { get; set; }

    public ObservableCollection<ShippingDetail> ShippingDetails

        {
            get { return ShippingDetailList; }
            set
            {
                ShippingDetailList = value;
                OnPropertyChanged("Changed");
            }
        }

         public async Task GetShippingDataAsync(string TrackID)
    {
        GenericRestClient<ShippingDetail> client = new GenericRestClient<ShippingDetail>();

        ShippingDetails = await client.GetAsyncByID(TrackID);

    }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string property)
        {
            var changed = PropertyChanged;

            if (changed == null)
                return;

            changed(this, new PropertyChangedEventArgs(property));
        }

    }
}

这是我的View Xaml Code

<?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:Class="DemoApp.TrackByID"
               Title="Mex World Wide"
             xmlns:local="clr-DemoApp"
             xmlns:ViewModels="clr-DemoApp.ViewModels">



    <ContentPage.BindingContext>
        <ViewModels:MainViewModel/>
    </ContentPage.BindingContext>

    <ContentPage.Content>
        <AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">

            <StackLayout AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
                <ScrollView>
                    <StackLayout>
                        <StackLayout Padding="30" Spacing="2" VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand">
                            <Entry x:Name="TrackIDText"  HorizontalTextAlignment="Center" Placeholder="Enter Your Shipment Tracking ID" TextChanged="TrackID_TextChanged"></Entry>

                        </StackLayout>
                        <StackLayout Padding="30" VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand">
                            <Button x:Name="TrackBtn" Text="Track" IsEnabled="False" BackgroundColor="Olive" Clicked="TrackBtn_Clicked"/>
                            <Button x:Name="ScanBtn" Text="Scan Barcode" IsEnabled="True" BackgroundColor="Azure" Clicked="ScanBtn_Clicked"/>
                        </StackLayout>
                    </StackLayout>
                </ScrollView>
                <StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand">
                    <ListView  x:Name="ShippingLV"
                  RowHeight="60"
                               ItemsSource="{Binding ShippingDetails}"/>
                </StackLayout>
            </StackLayout>

            <StackLayout x:Name="ActivityIndsL" IsVisible="False" Padding="12"
                 AbsoluteLayout.LayoutFlags="PositionProportional"
                 AbsoluteLayout.LayoutBounds="0.5,0.5,-1,-1">

                <ActivityIndicator x:Name="TrackingActivity" Color ="#FF4081"/>

                <Label Text="Please Wait while Details are being fetched..." HorizontalOptions="Center" TextColor="#FF4081"/>

            </StackLayout>

        </AbsoluteLayout>


    </ContentPage.Content>


</ContentPage>

我正在尝试使用ListView绑定ShippingDetails作为其ItemSource,这是在按钮单击事件上调用的。以下是XAML View的代码

private async void TrackBtn_Clicked(object sender, EventArgs e)
    {
        MainViewModel obj = new MainViewModel();

        ActivityIndsL.IsVisible = true;
        TrackingActivity.IsRunning = true;

        TrackingActivity.IsVisible = true;
        TrackBtn.IsEnabled = false;
        ScanBtn.IsEnabled = false;

        await obj.GetShippingDataAsync(TrackIDText.Text);

        ActivityIndsL.IsVisible = false;
        TrackingActivity.IsRunning = false;
        TrackingActivity.IsVisible = false;
        TrackBtn.IsEnabled = true;
        ScanBtn.IsEnabled = true;



    }

请纠正我在哪里做错了。 感谢

1 个答案:

答案 0 :(得分:1)

您的代码有些问题。首先,您使用错误的值调用OnPropertyChanged。它应该是已经改变的属性的名称,如下所示:

public ObservableCollection<ShippingDetail> ShippingDetails
{
    get { return ShippingDetailList; }
    set
    {
        ShippingDetailList = value;
        OnPropertyChanged("ShippingDetails");
    }
}

此外,您已将MainViewModel设置为XAML中的BindingContext:

<ContentPage.BindingContext>
    <ViewModels:MainViewModel/>
</ContentPage.BindingContext>

在按钮的点击事件中无需再次执行此操作。每次单击按钮时,我都不会创建新实例,而是像这样引用现有的视图模型:

private async void TrackBtn_Clicked(object sender, EventArgs e)
{
    MainViewModel vm = this.BindingContext as MainViewModel;
    await vm.GetShippingDataAsync(TrackIDText.Text);
}

修改:我还要在您的代码中修复一件事。我将ShippingDetailList定义为私有实例字段,因为ShippingDetails属性用于将其公开给外部世界。这不会真正影响您的代码的工作方式,但它更接近正确的 C#方式。

private ObservableCollection<ShippingDetail> shippingDetailList;

Here's一些关于字段的好阅读材料,如果您有兴趣的话。