Question

I have a mobile service collection in my view model which gets data from a mobile service database in the cloud. I am trying to bind this MobileServiceCollection to a Listbox (with item template) in my ui. But because of the Query command is async the ui doesn't update. This is i'm setting the Listbox.ItemSource before the data is received async. (I know the data gets received via breakpoints. (i know my binding is correct i've set Listbox.Itemsource after a button click then the data is displayed in my ui).

I know this probably has to do with the NotifyChange so i have tried implementing that. But I can't get it to work. So basicly my question is:

How do i update a listbox in my ui with a Async data source represented as a MobileSericeCollection.

Here is what i have so far:

Xaml:

            <ListBox x:Name="ListOfProducts" ItemsSource="{Binding}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                    <TextBlock x:Name="tb1" Margin="0,0,0,0" Text="{Binding ProductName, Mode=TwoWay}"></TextBlock>
                    <TextBlock x:Name="tb2" Margin="200,0,0,0" Text="{Binding ProductPrice, Mode=TwoWay}"></TextBlock>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate> 
        </ListBox>

Code behind:

    public partial class ProductList : PhoneApplicationPage
    {
    ProductListViewModel plvm = new ProductListViewModel();

    public ProductList()
    {
        InitializeComponent();

       ListOfProducts.ItemsSource = plvm.P;
    }
    }

ViewModel:

    class ProductListViewModel
{
    public MobileServiceCollection<Product, Product> P;

    public ProductListViewModel()
    {         
        getProducts();
    }

    /// <summary>
    /// Fetch all products from the database (async).
    /// </summary>
    private async void getProducts()
    {
        P = await App.MobileService.GetTable<Product>()
            //.Where(Product => Product.ProductName == "tomato")
            .OrderByDescending(Product => Product.ProductPrice)
            .ToCollectionAsync();
    }
}

Model:

    [DataContract]
public class Product 
{
    [DataMember(Name = "id")]
    public string id { get; set; }

    [DataMember(Name = "ProductName")]
    public string ProductName { get; set; }


    [DataMember(Name = "ProductPrice")]
    public float ProductPrice { get; set; }
}

If someone could help me on this one its much appriciated

Was it helpful?

Solution

Try to do it this way :

First, make your ProductListViewModel implements INotifyPropertyChanged.

Second, make P a property instead of field/member, because data-binding only works with public properties. And raise property changed notification properly :

private MobileServiceCollection<Product, Product> _p;
public MobileServiceCollection<Product, Product> P
{
    get { return _p; }
    set 
    {
        _p = value;
        NotifyPropertyChanged("P");
    }
}

Third, set DataContext of your view properly. Data-binding resolve path relative to view's current DataContext :

ProductListViewModel plvm = new ProductListViewModel();
public ProductList()
{
    InitializeComponent();
    this.DataContext = plvm;
}

Forth, set ItemsSource binding path to P property of DataContext/ProductListViewModel :

<ListBox x:Name="ListOfProducts" ItemsSource="{Binding P}">
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top