2

私の最初のビュー モデル (MainViewModel に名前を変更) には、ActionViewModel のリストがあります。私のxamlには、リストにバインドされたリストボックスがあり、リストボックスにはActionViewModelのプロパティにバインドされたテンプレートがあります。

これまでのところ、すべてがうまく機能しています。listitems の 1 つを選択すると、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);
}
4

1 に答える 1

2

あなたがこれを行うことができるようになると私が考えることができる3つの方法があります。

  1. データが変更されたActionServiceときに、何らかの通知を送信できます。これを行う簡単な方法の 1 つは、MvvmCross Messenger プラグインを使用することです。これは、n+1 日間の mvvmcross ビデオのCollectionService.csでCollectABull サービスが機能する方法です(詳細については、 http://mvvmcross.wordpress.comの N=13 を参照してください) 。

    これは私が一般的に使用するアプローチです。オーバーヘッドが低く、WeakReferences を使用し (メモリ リークが発生しない)、拡張が容易で (任意のオブジェクトが変更をリッスンできます)、ViewModel オブジェクトと Model オブジェクトの疎結合を促進します。

  2. Refreshリスト ViewModel にある種の API を実装し、これを適切な View イベント ( ViewDidAppear、 、OnNavigatedToなどOnResume) から呼び出すことができます。

    通常、既知のデータを更新するためにこのアプローチを使用することはありませんが、リソースを集中的に使用するオブジェクト (タイマーなど) を有効/無効にするために使用しました。

    モデル データの特定の形状 (および特にその変更頻度) については、このアプローチがメッセンジャー アプローチよりも効率的であるシナリオを想像できます。

  3. の使用を拡張して、モデル レイヤーに戻すINotifyPropertyChangedことができます。INotifyCollectionChanged

    私はこれを数回行いましたが、うまくいきました。

    このアプローチを選択する場合は、すべてのビューがWeakReferenceMvvmCross バインディングで使用されるサブスクリプションなどのサブスクリプションを使用して変更イベントにサブスクライブするように注意してください - WeakSubscriptionを参照してください。これを行わなかった場合、UI 自体がビューを削除した後でも、モデルによってビューがメモリに保持される可能性があります。

于 2013-08-23T17:30:30.323 に答える