0

I thought this would be simple but can't find any good examples.

public Class BookVm : ImplementsPropertyChanged
{
    public int BookId {get;set;}
    private bool _favorite;
    public bool Favorite
    { 
        get { return _favorite; }
        set {
                _favorite = value;
                OnPropertyChanged("Favorite");
               MyDbContext.SaveChanges() // this does not work
        }
    }

Then in my XAML bound to Book

<CheckBox Content="Favorite" IsChecked="{Binding Favorite}" />

How and when do I call SaveChanges() on my DatabaseContext?

I don't want to implement a save button. If I intercept the PropertyChange event and call SaveChanges, nothing seems to happen. My object is modified in memory but the database does not see a change.

My BookVm class is created on application startup like so:

        foreach (var book in MyDbContext.Books)
            Books.Add(book);

Where Books is an ObservableCollection<Book> in my MainWindowVm

Julien
  • 212
  • 1
  • 18
  • 53

3 Answers3

1

Say you had a dataservice class which returns book and update a book:

 public class DataService
{
    public static void UpdateBook(Book book)
    {
        //Call the context to update the database
    }

    public static IEnumerable<Book> FetchBooks()
    {
        // return DBContext.GetBooks
    }
}

Now You can make a View Model which takes a book and then return the properties. BookId is not going to change as per database(if it is a primary key).

//Domain Object
public class Book
{
    public int BookId { get; set; }
    public bool Favourite { get; set; }
}

//View Model
public class BookVm : ImplementsPropertyChanged
{
    private readonly Book book;

    //Store the book
    public BookVm(Book book)
    {
        this.book = book;
    }

    private bool favorite;
    public int BookId
    {
        get { return book.BookId; }
    }

    public bool Favorite
    {
        get { return favorite; }
        set
        {
            if (favorite != value)
            {
                favorite = value;
                //Update the database 
                UpdateDatabase();
            }
        }
    }

    private void UpdateDatabase()
    {
        //set the favorite value of the domain book
        book.Favourite = favorite;
        DataService.UpdateBook(book);
    }
}

We are storing the domain object in the ViewModel for later user. We can also write a controller that will display the view like this:

public class BookController
{
    public void Display()
    {
        IEnumerable<Book> books = DataService.FetchBooks();
        ObservableCollection<BookVm> bookVms = new ObservableCollection<BookVm>();
        foreach (var book in books)
        {
            BookVm bookVm = new BookVm(book);
            bookVms.Add(bookVm);
        }
        //Get the View and then bind using the bookVms collection
    }
}
Avneesh
  • 654
  • 4
  • 6
  • so I need a middle layer between my VM and the database. thanks, will try pronto – Julien Jun 08 '14 at 15:24
  • The code should work as it is once you put your code in the Dataservice to connect to your DB. You cant try the answer vfabre is suggesting because then you would need to get the dependency property, get the datacontext, then call the DbContext again to fetch the book - change the favourite and save back again. Too much work to do and not clean. Issues will occur there. – Avneesh Jun 08 '14 at 15:29
0

If you want to save the changes of the property Favorite you have to subscribe to the property changed event and then save the value to the DB.

Here you can find a link with information about subscription to property changed event

Edit Here are an example from MSDN

Community
  • 1
  • 1
vfabre
  • 1,388
  • 12
  • 23
  • hi thanks please see my edit. what you are suggesting is similar to what i have tried and does not work. – Julien Jun 08 '14 at 15:22
  • @Julien see the msdn example. Right now you are saving changes in the set but you do not subscribe to the changes. You have to do the SaveChanges in the OnPropertyChanged method. – vfabre Jun 08 '14 at 15:33
0

Also guessing that you have similar code in the Implements property change.

public class ImplementsPropertyChanged : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
} 

You will also need to add the following to raise the notifications.

public bool Favorite
    {
        get { return favorite; }
        set
        {
            if (favorite != value)
            {
                favorite = value;
                //Update the database 
                UpdateDatabase();
                OnPropertyChanged("Favorite");
            }
        }
    }
Avneesh
  • 654
  • 4
  • 6