更新先前加载的 Razor 局部视图中的模型值

Update Model Value in a Previously Loaded Razor Partial View

我有一个视图,当视图呈现时加载一组模块(我们会说其他局部视图)。

所以在主视图中这样想:

<div>
    @Html.PartialView("~/Views/MyApp/Partials/Module1.cshtml");
</div>
<div>
    @Html.PartialView("~/Views/MyApp/Partials/Module2.cshtml");
</div>
<div>
    @Html.PartialView("~/Views/MyApp/Partials/Module3.cshtml");
</div>

局部视图中有一个模型值已更改 Module2.cshtml。实际上它在 Module2 视图的操作中被改变了。我在 public ActionResult RenderChecklist(Model pageModel, IGrouping<string, ChecklistItem> list, int checklistCount):

中设置模型值
if (itemCounter == itemCheckedCounter)
{
    priorityCounter++;
    pageModel.MyAppInfo.ChecklistPriorityLevel = priorityCounter;
    listRestrict = "no-restrict";
    overlayShow = "hidden";
}
else
{
    listRestrict = "no-restrict";
    overlayShow = "hidden";
}

根据 ChecklistPriorityLevel 值确定是否在 Module1Module3 等中显示叠加层,但由于 Module1 在 [=15= 之前加载], ChecklistPriorityLevel in Module1 的值始终初始化为0.

在每个模块中调用的局部视图中的代码是这样的:

@if (moduleRestrict && !(moduleRestrictPriorityLevel <= checklistPriority) && !Model.GetValue<bool>("moduleRestrictBypass"))
{
    const string moduleLockMessage = "This section is locked.";

    <div class="module overlay show">
        <img src="/assets/myapp/images/lock.png" alt="Module Lock">
        <p>@moduleLockMessage</p>
    </div>
}

模型中的相关代码只是常规get,此时设置:

namespace MyApp.Core.MySite.Models
{
    /// <summary>
    ///     Model for MySite.
    /// </summary>
    public class MyAppInfoModel
    {
        ... //other models

        [Ignore]
        public int ChecklistPriorityLevel { get; set; }
    }
}

所以我的问题是如何获取此模型值的变化以触发已加载的其他模块(部分视图)的变化?

免责声明:出于隐私目的,我更改了一些实际代码。我只是想提供足够的信息让观众了解我想做什么。我正在寻找最佳选择,无论是异步还是其他方式,以正确获取其他局部视图中的值,而不管首先加载哪个局部视图。

修复我自己的问题(但我仍然很想看看如何处理)

因此,对于我的特定问题,我决定在加载任何模块之前强制设置模型的值。我的应用程序的工作方式,Module2 实际上可以在任何位置,并且任何模块都可以在 Module2 之前或之后。模块的顺序由后台确定。所以我只是决定创建一个 SurfaceController 并在主视图上获取数据(清单),但随后我必须在 "Module2" 中再次获取数据,这是我的 ChecklistModule。我不太喜欢重复检查清单两次,但为了获得 ChecklistPriorityLevel 值,我必须重复检查清单。

所以在我的主视图中调用如下:

MyAppChecklistController.SetChecklistPriorityLevel(Model);

那么我的方法是:

public static void SetChecklistPriorityLevel(MyAppRenderModel pageModel)
{
    var checklist = GetCheckList(pageModel);
    var priorityCounter = 1;

    foreach (var list in checklist)
    {
        var listCount = list.Count();
        var itemData = new ValueTuple<int, int, string>(1, 1, null);

        itemData = list.OrderBy(x => x.IsChecked).ThenBy(x => x.SortOrder).Aggregate(itemData,
            (current, item) => GetItemList(item, current.Item1, current.Item2, current.Item3, listCount));

        var itemCounter = itemData.Item1;
        var itemCheckedCounter = itemData.Item2;
        //  var itemList = itemData.Item3;

        priorityCounter = GetPriorityLevel(itemCounter, itemCheckedCounter, priorityCounter);

        pageModel.ChecklistPriorityLevel = priorityCounter;
    }
}

然后当我在 ChecklistModule 部分视图中呈现清单时:

[ChildActionOnly]
public ActionResult RenderChecklist(IGrouping<string, ChecklistItem> list,
        int checklistCount, int checklistCounter, int priorityCounter)
{
    var parentFolder = list.First().UmbracoContent.Parent;
    var listCount = list.Count();
    var itemData = new ValueTuple<int, int, string>(1, 1, null);
    var color = GetChecklistColorValue(parentFolder);

    itemData = list.OrderBy(x => x.IsChecked).ThenBy(x => x.SortOrder).Aggregate(itemData,
        (current, item) => GetItemList(item, current.Item1, current.Item2, current.Item3, listCount));

    var itemCounter = itemData.Item1;
    var itemCheckedCounter = itemData.Item2;
    var itemList = itemData.Item3;

    var checklistDict = GetChecklistRestrictions(parentFolder, itemCounter,
        itemCheckedCounter, priorityCounter);

    checklistDict.Add("color", color);
    checklistDict.Add("itemList", itemList);
    checklistDict.Add("checklistCounter", checklistCounter);

    return GetChecklistLayout(checklistCount, checklistLayoutDict);
}

正如您所看到的,我几乎 运行 在一个页面加载中两次检查清单。我不想那样做。如果有人有更好的想法来提高效率,请告诉我。

更新: 上面的解决方案(即使只发布了部分代码)解决了我的问题,但是我决定只在视图上捕捉清单并添加它也适用于模型,然后在部分中使用该模型 (pageModel.Checklists),所以我实际上并没有用 Linq 两次获取清单。我仍然需要遍历清单两次,但我不会两次获取值。所以更多的是 hack,但也许我以后会继续寻找一种方法来简化它。