Question

So I'm trying to build a small cookbook application using WPF and MVVM light. I've run into a situation where I'm binding a List from the model to the view model. And it works fine for displaying and removing items, but when adding items I couldn't get the display to update.

I came across ObserableCollections which seemed to be just what I wanted, but I'm not sure I'm using them correctly because it seems wrong to be creating a new OC every time. How am I supposed to be retrieving an observable collection when the model is using a list?

Model(s):

public class Recipe
{
    public int Id { get; set; }
    public string Title { get; set; }
    public List<RecipeIngredient> Ingredients { get; set; }
}

public class RecipeIngredient
{
    // ... //
}

ViewModel:

 public Recipe SelectedRecipe
{
    get
    {
        return this.selectedRecipe;
    }
    set
    {
        this.selectedRecipe = value;
        RaisePropertyChanged("SelectedRecipe");
        RaisePropertyChanged("RecipeIngredients");
    }
}

public ObservableCollection<RecipeIngredient> RecipeIngredients
{
    get 
    {
        return new ObservableCollection<RecipeIngredient>(selectedRecipe.Ingredients.ToList());
    }
}

public RelayCommand<EventArgs> AddIngredientCommand { get; private set; }
public RelayCommand<string> DeleteIngredientCommand { get; private set; }

private void AddIngredient(EventArgs eventArgs)
{
    SelectedRecipe.Ingredients.Add(new RecipeIngredient() { Name = "New Ingredient" }); 
    RaisePropertyChanged("RecipeIngredients");
}

private void DeleteIngredient(string name)
{
    SelectedRecipe.Ingredients = SelectedRecipe.Ingredients.Where(i => i.Name != name).ToList();
    RaisePropertyChanged("RecipeIngredients");
}

public MainViewModel()
{
    DBController db = new DBController();
    recipes = db.GetRecipeList();

    RecipeSelectionChangedCommand = new RelayCommand<SelectionChangedEventArgs>((args) => RecipeSelectionChanged(args));
    SaveRecipeCommand = new RelayCommand<EventArgs>((args) => SaveRecipe(args));    
    AddIngredientCommand = new RelayCommand<EventArgs>((args) => AddIngredient(args));
    DeleteIngredientCommand = new RelayCommand<string>((args) => DeleteIngredient(args));
}

Am I way off track here?

Était-ce utile?

La solution

Should have read more carefully. If you're displaying the selected recipe's ingredients in an alternate view, you should be using data binding in the view <ListBox ItemsSource="{Binding SelectedRecipe.Ingredients}"/> You could consider using linq to entities (Entity Framework) for ORM..

public class RecipeVM
{
    public RecipeVM(Recipe r)
    {
        recipe = r;
    }
    Recipe recipe;
    public int Id 
    { 
        get
        {
            return recipe.Id;
        }
        set
        {
            PropertyChanged("Id");
            recipe.id = value;
        }
    }
    public string Title
    {
        get
        {
            return recipe.Title;
        }
        set
        {
            PropertyChanged("Title");
            recipe.Title = value;
        }
    }
    ObservableCollection<RecipeIngredient> ingredients;
    public ObservableCollection<RecipeIngredient> Ingredients 
    {
        get
        {
            if (ingredients == null)
                ingredients = new ObservableCollection<RecipeIngredient>(recipe.Ingredients);
            return ingredients;
        }
        set
        {
            PropertyChanged("Ingredients");
            ingredients = value;
        }
    }
}

You'll need to modify that a bit if you want to keep the collections in sync though..

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top