Xamarin形成对ObservableCollection绑定上下文的理解

时间:2019-06-04 13:39:19

标签: xamarin xamarin.forms

我在将ObservableCollection绑定到alexrainman CarouselView时遇到问题。 阅读一些基本文章后,我创建了视图模型:

public class PostObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        string postOwner = string.Empty;
        string id = string.Empty;
        string profileimage = string.Empty;
        string post = string.Empty;
        List<string> postimages = null;

        public string PostOwner
        {
            set
            {
                if (postOwner != value)
                {
                    postOwner = value;
                    OnPropertyChanged("PostOwner");
                }
            }
            get
            {
                return postOwner;
            }

        }

        public string Id {

            set
            {
                if (id != value)
                {
                    id = value;
                    OnPropertyChanged("Id");
                }
            }
            get
            {
                return id;
            }
        }


        public string Post
        {
            set
            {
                if (post != value)
                {
                    post = value;
                    OnPropertyChanged("Post");
                }
            }
            get
            {
                return post;
            }
        }
        public string ProfileImage
        {
            set
            {
                if (profileimage != value)
                {
                    profileimage = value;
                    OnPropertyChanged("ProfileImage") ;
                }
            }
            get
            {
                return profileimage;
            }

        }
        public List<string> PostImages
        {
            set
            {
                if (postimages != value)
                {
                    postimages = value;
                    OnPropertyChanged("PostImages");
                }
            }
            get
            {
                return postimages;
            }
        }

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

    }

我通过对服务器的REST调用来检索数据:

public static bool GetMyPostData(ref ObservableCollection<PostObject> myPosts, string groupid, string apikey)
 {
       try
            {
                string newURL = URL + "GetPosts";

                using (HttpClient client = new HttpClient())
                {

                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    MultipartFormDataContent formdata = new MultipartFormDataContent
                    {
                        { new StringContent(apikey), "apikey" },
                        { new StringContent(groupid), "groupid" }
                    };

                    HttpResponseMessage response = client.PostAsync(newURL, formdata).Result;  // Blocking call! Program will wait here until a response is received or a timeout occurs.

                    if (response.IsSuccessStatusCode)
                    {
                        try
                        {

                            myPosts = response.Content.ReadAsAsync<ObservableCollection<PostObject>>().Result;



                        }
                        catch (Exception e)
                        {
                            Debug.WriteLine(e);
                            return false;
                        }
                    }
                }
                return true;

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                return false;
            }
}

我可以正常工作的数据是什么,现在我像这样设置Binding上下文:

 ObservableCollection<PostObject> GroupPosts = new ObservableCollection<PostObject>();

       public Posts (GroupInfo ginfo)
        {
            InitializeComponent ();

                GroupTitle.Text = ginfo.Title;
                 CurrentGroupInfo = ginfo;
                GetDataPosts();

            BindingContext = GroupPosts;


       }
  public void GetDataPosts()
        {
            try
            {

                GroupPosts.Clear();

                if (RestController.GetMyPostData(ref GroupPosts, CurrentGroupInfo.Id.ToString(), apikey))
                {
                    Debug.WriteLine("Data downloaded");

                }
            }
            catch(Exception e)
            {
                Debug.WriteLine(e.Message);
            }

最后,我的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"
             xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin"
             xmlns:cv="clr-namespace:CarouselView.FormsPlugin.Abstractions;assembly=CarouselView.FormsPlugin.Abstractions"
              NavigationPage.HasNavigationBar="True"
             NavigationPage.HasBackButton="False"
             NavigationPage.BackButtonTitle="Back"
             x:Class="forms.Posts">

    <NavigationPage.TitleView>
        <StackLayout Orientation="Horizontal" VerticalOptions="Center" Spacing="10" >
            <Label x:Name="GroupTitle" TextColor="White" FontSize="Medium"/>
        </StackLayout>
    </NavigationPage.TitleView>

    <ContentPage.ToolbarItems>
        <ToolbarItem Name="iconexample" Icon="settings.png" Priority="0" Order="Primary" />
    </ContentPage.ToolbarItems>

    <ContentPage.Content>
        <cv:CarouselViewControl x:Name="carousel"
        ItemsSource="{Binding PostImages}"
        ShowArrows="true"
        ShowIndicators="true"
        Orientation="Horizontal">
       </cv:CarouselViewControl>


    </ContentPage.Content>
</ContentPage>

但是我遇到错误

Unhandled Exception:

System.NullReferenceException: Object reference not set to an instance of an object.

所以我不确定我缺少什么,还是需要多读一些?任何帮助都会很棒。

1 个答案:

答案 0 :(得分:0)

您要在此处进行一些更改:

  1. 将字段定义更改为属性,您将无法绑定到该字段:
public ObservableCollection<PostObject> GroupPosts { get; } = new ObservableCollection<PostObject>();
  1. 如果更新引用,则必须引发属性更改事件,因此属性定义应如下所示:
private ObservableCollection<PostObject> _groupPosts = new ObservableCollection<PostObject>();
public ObservableCollection<PostObject> GroupPosts
{
    get { return _groupPosts; }
    set 
    { 
        _groupPosts = value; 
        RaisePropertyChanged(.....); // here you should notify your binding that value has changed
    }
}
  1. 由于您尝试通过引用传递此列表(ref参数),因此无法使用属性进行编译,因此最好从数据提供者返回值然后应用它:
GroupPosts.Clear();
var newData = RestController.GetMyPostData(CurrentGroupInfo.Id.ToString(), apikey);
GroupPosts = newData;

将可观察的集合传递给基础数据提供者是一个坏习惯,因为它将限制它只能在UI线程上运行(否则,在非UI线程上更新集合之后,您可能会使应用程序崩溃)。但这是另一篇文章的顶部:)