亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 Controller/ViewComponent 中設置/更改屬性的 Display

在 Controller/ViewComponent 中設置/更改屬性的 Display

C#
陪伴而非守候 2022-10-23 16:14:34
根據2010 年的這個答案,關于 mvc-2,這是不可能的?,F在,在 asp.net-core 2.2 中呢?我的用例:我有一個BaseViewModel被 2 個視圖使用的視圖:(TableView對于用戶)和TableManagentView(對于管理員)。由BaseViewModela 調用ViewComponent。以下是一些示例:基礎視圖模型:public class BaseViewModel {    [Display(Name = "Comment")    public string UserComment { get; set; }}表視圖:@await Component.InvokeAsync(nameof(Base), new { myObject = myObject, stringName = "User"})表管理視圖:@await Component.InvokeAsync(nameof(Base), new { myObject = myObject, stringName = "Admin"})根據:public class Base : ViewComponent{    public IViewComponentResult Invoke(BaseViewModel myObjet, string invokingView)    {        // here i want to do something like that        if (invokingView == "User") {            myObject.UserComment.SetDisplayName("My Comment");        }         if (invokingView == "Admin") {            myObject.UserComment.SetDisplayName("User's Comment");        }        return View("BaseViewComponent", myObject);    }}基本視圖組件:@Html.DisplayNameFor(model => model.UserComment)被BaseViewModel簡化了,但還有更多的屬性。我想這樣做的原因是避免兩個表中的代碼重復。唯一應該改變的是標簽名稱。我試過了reflection,但沒有成功:public IViewComponentResult Invoke(BaseViewModel myObject, string invokingView)    {        MemberInfo property = typeof(BaseViewModel).GetProperty("UserComment");        property.GetCustomAttributes(typeof(DisplayAttribute)).Cast<DisplayAttribute>().Single().Name = "test";        return View("BaseViewComponent", myObject);    }Name不會改變并保持初始"Comment"設置。如果無法以編程方式設置屬性名稱,我還有哪些其他解決方案?我正在考慮ViewBag/ViewDataor TempData,但這個解決方案對我沒有吸引力。這樣做的利弊是什么?
查看完整描述

1 回答

?
慕的地8271018

TA貢獻1796條經驗 獲得超4個贊

擴展我留下的評論,你可以解決這個問題的一種方法是讓你BaseViewModel成為一個抽象類并擁有從它派生的具體類。所以UserViewModel和AdminViewModel。這兩個具體類將成為兩者的模型,TableView并將TableManagentView負責告訴“外部世界”如何標記字段。


基類有兩個主要方面(除了你的普通字段):一個Dictionary<string, string>包含標簽的抽象和一個從列表中獲取標簽的方法:string GetLabel(string propName). 所以是這樣的:


public abstract class BaseViewModel

{

    protected abstract Dictionary<string, string> Labels { get; }


    public string UserComment { get; set; }


    public string GetLabel(string propName)

    {

        if (!Labels.TryGetValue(propName, out var label))

            throw new KeyNotFoundException($"Label not found for property name: {propName}");


        return label;

    }

}

然后創建兩個派生類User和Admin:


public sealed class UserViewModel : BaseViewModel

{

    protected override Dictionary<string, string> Labels => new Dictionary<string, string>

    {

        { nameof(UserComment), "User label" }

    };

}


public sealed class AdminViewModel : BaseViewModel

{

    protected override Dictionary<string, string> Labels => new Dictionary<string, string>

    {

        { nameof(UserComment), "Admin label" }

    };

}

他們只Dictionary<string, string>為基類上的每個字段實現并設置適當的文本。


接下來,將您的更改BaseViewComponent為:


查看:


@model DisplayNameTest.Models.BaseViewModel


<h3>Hello from my View Component</h3>


<!-- Gets the label via the method on the base class -->

<p>@Model.GetLabel(nameof(BaseViewModel.UserComment))</p>


<p>@Model.UserComment)</p>

ComponentView 類(現在更簡單了)


public IViewComponentResult Invoke(BaseViewModel viewModel)

{

    return View(viewModel);

}

最后,改變你的觀點TableView和TableManagentView這個:


@model WebApp.Models.AdminViewModel


@{

    Layout = null;

}


<h1>Admin View</h1>

<div>

    @await Component.InvokeAsync("Base", Model)

</div>

和控制器:


public IActionResult Index()

{

    var adminViewModel = new AdminViewModel { UserComment = "some comment from admin" };

    return View(adminViewModel);

}

現在,當您導航到 時TableView,您會將 a 傳遞UserViewModel給 the BaseViewComponent,它會找出正確的標簽。引入新字段現在需要您更改視圖模型,將新條目添加到字典中。


它并不完美,但我認為這是解決它的好方法。到目前為止,我還不是 MVC 專家,所以也許其他人也可以想出一種更自然的方法來做到這一點。我還準備了一個工作示例應用程序并推送到 GitHub。你可以在這里查看:aspnet-view-component-demo。希望它以某種方式有所幫助。


查看完整回答
反對 回復 2022-10-23
  • 1 回答
  • 0 關注
  • 103 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號