【问题标题】:How do I update the parent viewmodel when child viewmodel is updated更新子视图模型时如何更新父视图模型
【发布时间】:2013-08-26 15:51:45
【问题描述】:

在我的第一个视图模型(重命名为 MainViewModel)中,我有一个 ActionViewModel 列表。 在我的 xaml 中,我有一个绑定到列表的列表框,在列表框中,我有一个绑定到 ActionViewModel 属性的模板。

到目前为止一切顺利,一切正常。 选择其中一个列表项时,我导航到 ActionViewModel 并与它一起传递 id。 ActionViewModel 从内存中的静态列表中检索信息,MainViewModel 也从中检索信息以创建 actionviewmodel 列表。

到目前为止仍然很好,我可以编辑属性,所有绑定都可以正常工作,我很高兴。 通过单击保存按钮,信息被收集并存储在静态列表中。 当我点击后退按钮时,我返回列表,但不幸的是显示的值仍然相同,有没有办法发送命令重新加载列表中的项目?将完整的视图模型作为对新 ActionViewModel 的引用传递?还是某些属性告诉父级“列表中的此视图模型已更新”?

我确信上面的文字有点混乱,所以这里有一些代码来澄清一下(希望如此)

MainViewModel.cs

private List<ActionViewModel> _actionViewModels;
public List<ActionViewModel> ActionViewModels
{
    get { return _actionViewModels; }
    set { _actionViewModels = value; RaisePropertyChanged(() => ActionViewModels); }
}


private Cirrious.MvvmCross.ViewModels.MvxCommand<int> _navigateToAction;
public System.Windows.Input.ICommand NavigateToAction
{
    get
    {
        _navigateToAction = _navigateToAction ?? new Cirrious.MvvmCross.ViewModels.MvxCommand<int>((action) => NavigateToTheDesiredAction(action));
        return _navigateToAction;
    }
}

private void NavigateToTheDesiredAction(int action)
{
    ShowViewModel<ActionViewModel>(new { id = action });
}

// Get DTOs from server or from cache and fill the list of ActionViewModels
public async Task Load()
{
    ActionService actionService = new ActionService();

    List<ActionViewModel> actionViewModels = new List<ActionViewModel>();

    MyActions = await actionService.GetMyActions();
    foreach (ActionDTO action in MyActions)
    {
        ActionViewModel actionViewModel = new ActionViewModel();
        await actionViewModel.Load(action.id);
        actionViewModels.Add(actionViewModel);
    }

    ActionViewModels = actionViewModels;
}

ActionViewModel.cs

public int ID
{
    get { return TheAction.id; }
    set { TheAction.id = value; RaisePropertyChanged(() => ID); }
}

public string Title
{
    get { return TheAction.Title; }
    set { TheAction.Title = value; RaisePropertyChanged(() => Title); }
}

public async Task Load(int actionId)
{
    ActionDTO TheAction = await actionService.GetAction(actionId);
    this.ID = TheAction.id;
    this.Title = TheAction.Title;
}

private Cirrious.MvvmCross.ViewModels.MvxCommand _save;
public System.Windows.Input.ICommand Save
{
    get
    {
        _save = _save ?? new Cirrious.MvvmCross.ViewModels.MvxCommand(PreSaveModel);
        return _save;
    }
}

private void PreSaveModel()
{
    SaveModel();
}

private async Task SaveModel()
{
    ValidationDTO result = await actionService.SaveAction(TheAction);
}

ActionService.cs

public static List<ActionDTO> AllActions = new List<ActionDTO>();

public async Task<ActionDTO> GetAction(int actionId)
{
    ActionDTO action = AllActions.FirstOrDefault(a => a.id == actionId);
    if (action == null)
    {
        int tempActionId = await LoadAction(actionId);
        if (tempActionId > 0)
            return await GetAction(actionId);
        else
            return new ActionDTO() { Error = new ValidationDTO(false, "Failed to load the action with id " + actionId, ErrorCode.InvalidActionId) };
    }
    return action;
}

private async Task<int> LoadAction(int actionId)
{
    ActionDTO action = await webservice.GetAction(actionId);
    AllActions.Add(action);
    return action.id;
}

public async Task<ValidationDTO> SaveAction(ActionDTO action)
{
    List<ActionDTO> currentList = AllActions;
    ActionDTO removeActionFromList = currentList.FirstOrDefault(a => a.id == action.id);
    if (removeActionFromList != null)
        currentList.Remove(removeActionFromList);

    currentList.Add(action);
    AllActions = currentList;
    return await webservice.SaveAction(action);
}

【问题讨论】:

    标签: c# windows-phone viewmodel mvvmcross


    【解决方案1】:

    我能想到的有 3 种方法可以让你做到这一点。

    1. ActionService 可以在数据更改时发出某种通知。一种简单的方法是使用 MvvmCross Messenger 插件。这是在 mvvmcross 视频的 N+1 天中 CollectionService.cs 中的 CollectABull 服务的工作方式(有关更多信息,请观看 http://mvvmcross.wordpress.com 中的 N=13)

      这是我通常使用的方法。它具有低开销,使用WeakReferences(因此不会泄漏内存),易于扩展(任何对象都可以监听更改),并且它鼓励 ViewModel 和 Model 对象的松散耦合

    2. 您可以在列表 ViewModel 上实现某种Refresh API,并可以从适当的视图事件(例如ViewDidAppearOnNavigatedToOnResume)调用它。

      我通常不使用此方法刷新已知数据,但我已将其用于启用/禁用资源密集型对象 - 例如计时器

      对于某些形状的模型数据(尤其是它的变化频率),我可以想象这种方法可能比信使方法更有效的场景。

    3. 您可以将INotifyPropertyChangedINotifyCollectionChanged 的使用扩展回您的模型层。

      我已经这样做了几次,对我来说效果很好。

      如果您确实选择了这种方法,请注意确保所有视图都使用 WeakReference 订阅(例如 MvvmCross 绑定中使用的订阅)订阅更改事件 - 请参阅 WeakSubscription。如果您不这样做,那么即使在 UI 本身已将其删除后,Model 也有可能导致 Views 保留在内存中。

    【讨论】:

    • 第一个解决方案对我来说是最好的解决方案,在观看了 youtube 上的 N=12 和 N=13 教程之后,这只是实现消息操作的问题,它就像一个魅力。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多