簡體   English   中英

ASP MVC.NET - 如何綁定KeyValuePair?

[英]ASP MVC.NET - how to bind KeyValuePair?

是否有可能綁定這種財產?

public KeyValuePair<string, string> Stuff { get; set; }

我試圖在視圖中使用以下代碼,但它不起作用:

<%=Html.Text("Stuff", Model.Stuff.Value)%>    
<%=Html.Hidden("Model.Stuff.Key", Model.Stuff.Key)%>

KeyValuePair<K,V>是一個結構,而不是一個類,因此每次調用Stuff屬性都會返回原始KeyValuePair的副本。 因此,當您綁定到Model.Stuff.ValueModel.Stuff.Key ,您實際上正在處理KeyValuePair<K,V>兩個不同實例,其中沒有一個是您的模型中的實例。 因此,當它們更新時,它不會更新模型中的Stuff屬性... QED

順便說一句,Key和Value屬性是只讀的,因此您無法修改它們:您必須替換KeyValuePair實例

以下解決方法應該有效:

型號:

private KeyValuePair<string, string> _stuff;
public KeyValuePair<string, string> Stuff
{
    get { return _stuff; }
    set { _stuff = value; }
}

public string StuffKey
{
    get { return _stuff.Key; }
    set { _stuff = new KeyValuePair<string, string>(value, _stuff.Value); }
}

public string StuffValue
{
    get { return _stuff.Value; }
    set { _stuff = new KeyValuePair<string, string>(_stuff.Key, value); }
}

查看:

<%=Html.Text("Stuff", Model.StuffValue)%>    
<%=Html.Hidden("Model.StuffKey", Model.StuffKey)%>
<%=Html.Text("Stuff.Value", Model.Stuff.Value)%>

可能會工作嗎?

如果你需要綁定一個Dictionary,這樣每個值都有一個texbox來編輯它,下面是一種讓它工作的方法。 影響HTML中name屬性生成方式的非常重要的部分是模型表達式,它確保在回發時發生模型綁定。 此示例僅適用於Dictionary。

鏈接的文章解釋了使綁定工作的HTML語法,但是它使用Razor語法來實現這一點非常神秘。 此外,文章的不同之處在於它們允許編輯鍵和值,並使用整數索引,即使字典的鍵是字符串,而不是整數。 因此,如果您嘗試綁定字典,在確定采用哪種方法之前,首先需要首先評估是否只需要值可編輯,或者鍵和值都是可編輯的,因為這些方案是完全不同的。

如果您需要綁定到復雜對象,即Dictionary,那么您應該能夠為每個屬性創建一個文本框,並將表達式鑽入屬性,類似於文章。

http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

 public class SomeVM
    {
        public Dictionary<string, string> Fields { get; set; }
    }

    public class HomeController : Controller
    {
        [HttpGet]
        public ViewResult Edit()
        {
            SomeVM vm = new SomeVM
            {
             Fields = new Dictionary<string, string>() {
                    { "Name1", "Value1"},
                    { "Name2", "Value2"}
                }
            };

            return View(vm);

        }

        [HttpPost]
        public ViewResult Edit(SomeVM vm) //Posted values in vm.Fields
        {
            return View();
        }
    }

CSHTML:

僅限編輯器(當然您可以添加LabelFor以根據Key生成標簽):

@model MvcApplication2.Controllers.SomeVM

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>SomeVM</legend>

        @foreach(var kvpair in Model.Fields)
        {
            @Html.EditorFor(m => m.Fields[kvpair.Key])  //html: <input name="Fields[Name1]" …this is how the model binder knows during the post that this textbox value gets stuffed in a dictionary named “Fields”, either a parameter named Fields or a property of a parameter(in this example vm.Fields).
        }

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

編輯鍵/值:@ {var fields = Model.Fields.ToList(); }

    @for (int i = 0; i < fields.Count; ++i) 
    {
        //It is important that the variable is named fields, to match the property name in the Post method's viewmodel.
        @Html.TextBoxFor(m => fields[i].Key)
        @Html.TextBoxFor(m => fields[i].Value)

        //generates using integers, even though the dictionary doesn't use integer keys,
        //it allows model binder to correlate the textbox for the key with the value textbox:            
        //<input name="fields[0].Key" ...
        //<input name="fields[0].Value" ...

        //You could even use javascript to allow user to add additional pairs on the fly, so long as the [0] index is incremented properly
    }

我知道這是一個較老的問題,但我不喜歡任何建議的解決方案,所以我給我的。 我已經重寫了默認模型綁定器來處理KeyValuePairs,所以我可以像以前一樣使用它們。

public class CustomModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var model = base.BindModel(controllerContext, bindingContext);            
        model = ResolveKeyValuePairs(bindingContext, model);
        return model;
    }

    private object ResolveKeyValuePairs(ModelBindingContext bindingContext, object model)
    {
        var type = bindingContext.ModelType;
        if (type.IsGenericType)
        {
            if (type.GetGenericTypeDefinition() == typeof (KeyValuePair<,>))
            {                    
                var values = bindingContext.ValueProvider as ValueProviderCollection;
                if (values != null)
                {
                    var key = values.GetValue(bindingContext.ModelName + ".Key");
                    var keyValue = Convert.ChangeType(key.AttemptedValue, bindingContext.ModelType.GetGenericArguments()[0]);
                    var value = values.GetValue(bindingContext.ModelName + ".Value");
                    var valueValue = Convert.ChangeType(value.AttemptedValue, bindingContext.ModelType.GetGenericArguments()[1]);
                    return Activator.CreateInstance(bindingContext.ModelType, new[] {keyValue, valueValue});
                }

            }
        }
        return model;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM