【问题标题】:MVVM List and ObservableCollectionMVVM 列表和 ObservableCollection
【发布时间】:2014-06-26 17:31:14
【问题描述】:

所以我正在尝试使用 WPF 和 MVVM light 构建一个小型食谱应用程序。我遇到了将模型中的列表绑定到视图模型的情况。它可以很好地显示和删除项目,但是在添加项目时我无法更新显示。

我遇到了 ObserableCollections,这似乎正是我想要的,但我不确定我是否正确使用它们,因为每次都创建一个新的 OC 似乎是错误的。当模型使用列表时,我应该如何检索可观察的集合?

型号:

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

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

视图模型:

 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));
}

我是不是跑偏了?

【问题讨论】:

  • 为什么需要 ViewModel 中的 ObservableCollection 作为模型中的 List?
  • RecipeIngredients 只能在构造函数中实例化一次。否则,每次 UI 想要刷新它都会获得一个新实例。完全没有必要,而且可能导致不当行为。
  • MMVM Light 为已更改的属性提供 lambda 表达式:RaisePropertyChanged(() => this.RecipeIngredients),这使得它更安全、更易于重构和更易于维护。
  • 哦,哇,感谢有关 lambda 的提示,重构绝对是一件痛苦的事。
  • @Tomtom - 因为我最初是绑定到 SelectedRecipe.Ingredients 的,但是删除列表并调用 RPC 永远不会刷新它,直到我创建了一个 OC 属性并绑定到它。

标签: c# wpf mvvm mvvm-light observablecollection


【解决方案1】:

应该更仔细地阅读。如果您在备用视图中显示所选配方的成分,您应该在视图中使用数据绑定&lt;ListBox ItemsSource="{Binding SelectedRecipe.Ingredients}"/&gt; 您可以考虑使用 linq to entity (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;
        }
    }
}

如果你想保持集合同步,你需要稍微修改一下..

【讨论】:

  • "" 这正是我以前的!但是,当我更改成分(即 List)并为其调用 RaisePropertyChanged 时,我永远无法让它更新删除。这就是我制作 observable 集合属性并将其绑定到该属性的原因。
  • 无论如何,如果您打算修改集合本身(而不是其中的项目),那么如果您“应该”将实现 INotifyCollectionChanged(如 ObservableCollection)的东西暴露给 UI )。所以你可以包装整个食谱类,我会补充一点。
  • 不是我需要更新VM外部的集合。只是当我从 List 中删除一个项目时,NPC 无法刷新视图。但我认为你举的例子是我一直在寻找但找不到的过程,我很感激!
  • ^-^ 如果您有任何其他问题,请随时询问。一般情况下,您应该修改此示例中的 oc 而不是直接修改列表。完成后(例如保存),您可以更新列表。
猜你喜欢
  • 2013-09-18
  • 1970-01-01
  • 2011-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多