Click here to Skip to main content
15,886,806 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
Hi all,

I am working in UWP with EntityFrameWorkCore and SQLite.
I am trying to bind to my DbSet, but it doesn't update.

I could make my binding work when I change the property Name, it gets updated. But the ListView doesn't update when I add/remove items to/from my DbSet.

Here is my code:

Here the classes. Note that the binding to DbSet when I add/remove items doesn't work.
But when I modify the name it works and updates.

public class ContactsContext : DbContext
{
    public DbSet<Contact> Contacts { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite("Data Source=blogging.db");
    }
}

public class Contact : INotifyPropertyChanged
{
    private string _Name;

    public event PropertyChangedEventHandler PropertyChanged;

    [Key]
    public string Name
    {
        get { return _Name; }
        set
        {
            if (_Name != value)
            {
                _Name = value;
                NotifyPropertyChanged("Name");
            }
        }
    }

    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this,
                new PropertyChangedEventArgs(propertyName));
        }
    }

}


<ListView Name="myListView" ItemsSource="{Binding}"
HorizontalAlignment="Center" VerticalAlignment="Center">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="Data:Contact">
            <TextBlock Text="{x:Bind Name}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>


private void Page_Loaded(object sender, RoutedEventArgs e)
{
    using (ContactsContext db = new ContactsContext())
    {
        myListView.ItemsSource = db.Contacts;
    }
}

private void Adder_Click(object sender, RoutedEventArgs e)
{
    using (ContactsContext db = new ContactsContext())
    {
        db.Contacts.Add(new Contact { Name = myTextBox.Text });
        db.SaveChanges();
    }
}


What I have tried:

I already tried to add the
INotifyPropertyChanged
to my DataContext class, but no effect.

public class ContactsContext : DbContext
    {
        private DbSet<Contact> _Contacts { get; set; }
        
        public event PropertyChangedEventHandler PropertyChanged;

        public string Contacts
        {
            get { return _Contacts; }
            set
            {
                    _Contacts = value;
                    NotifyPropertyChanged("Contacts");
            }
        }

        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this,
                    new PropertyChangedEventArgs(propertyName));
            }
        }


        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite("Data Source=blogging.db");
        }
    }


Tried to create another class that was an ObservableCollection to List the Contacts. But
1) this looked a very complicated solution and I think there must be something easier.
2) it worked fine, but I had some issues when saving the changes (db.SaveChanges).

Someone lived throught this and has some fantastic solution?
thanks.
Posted
Updated 16-Feb-18 6:45am
v3

1 solution

Your Page_Loaded method creates one instance of your context, loads the data, and binds it to your list. Your Adder_Click method creates a completely separate instance of your context, adds a new record, and saves the changes.

Changes made to one instance of your context will not be visible to a different instance of your context. Instead, you will need to create a single instance of your context, and use that for all operations in your page.

Also, in EF6, you would need to use the set's .Load() method and .Local property to bind to a WPF control. You'll need to check whether that's still the case with EF Core and UWP:
Entity Framework Databinding with WPF[^]
 
Share this answer
 
v2
Comments
Scolo 17-Feb-18 4:43am    
Hi Richard, thanks for the answer :)

But, I can agree and disagree?
That doesn't explain then why if I do this:
db.Contacts.FirstOrDefault().Name = "updated";

it updates in the ListView.

I played a bit with .Local and .Load() and I got a different problem. I could make the ListView refresh very well, but when I tried .SaveChanges() it didn't save anything.
Richard Deeming 19-Feb-18 14:03pm    
Are you running that line against the DbContext instance you used to bind your list, or a new DbContext instance?
Scolo 20-Feb-18 10:31am    
Both,
I tried with
using (ContactsContext db = new ContactsContext())
inside I made my binding and used Local, no help.
But also tried declaring a private at the beginning
private ContactsContext myContext = new ContactsContext();
and use it all along. None of them worked (with the private, I tried also static, no help).

I'm starting to think it is just something not working in UWP.
As you can see in the Microsoft docs they only talk about binding to WPF and WinForms.
Scolo 19-Feb-18 4:32am    
I am still stuck with this.
I follow the WPF tutorial, but it doesn't help at all in UWP.

I try to bind like this:
Hide   Copy Code
db.Contacts.Load(); myListView.ItemsSource = db.Contacts.Local;

and it still doesn't refresh when I later add/remove items.

Unluckily in UWP there is no Hide   Copy Code
Items.Refresh()
or similar.
So that tutorial doesn't help much.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900