2009-05-21 3 views
3

강력한 문자열을 사용하여 "ViewData"라는 마법 문자열없이 모델을 뷰에 바인딩하는 방법을 보여주는 좋은 블로그 게시물을 찾을 수없는 것 같습니다. 형식화 된 뷰는 내가 취하려고하는 접근법입니다.)ViewData (강력한 형식의 뷰)없이 Html.DropDownList를 바인딩하는 방법

내 모델에 직접 바인딩하려면 아래에서 변경해야 할 사항을 아는 사람이 있습니까?

보기

<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of MvcApplication1.Category))" %> 
<asp:Content ID="aboutContent" ContentPlaceHolderID="MainContent" runat="server"> 
    <%=Html.DropDownList("CategoryList")%> 
</asp:Content> 

컨트롤러

Function Index() As ActionResult 
    Dim list As New List(Of Category) 
    list.Add(New Category With {.CategoryID = 1, .CategoryName = "Test1"}) 
    list.Add(New Category With {.CategoryID = 2, .CategoryName = "Test2"}) 

    Return View() 
End Function 

EDIT 큰 응답

VB의 마지막 솔루션은 다음과 같습니다, 감사합니다!

컨트롤러

Function Index() As ActionResult 
    Dim id As Integer = 1 
    Dim ProductObject As Product = mProductService.GetProductById(id) 

    Return View(ProductObject) 
End Function 

보기

<%=Html.DropDownList("Category", New SelectList(Model.Categories, "CategoryID", "CategoryName"))%> 

제품 클래스 (w이 범주에 대한 IEnumeralbe 속성 /)

Public Class Product 
    Public Sub New() 

    End Sub 


    Private mProductID As Integer 
    Public Property ProductID() As Integer 
     Get 
      Return mProductID 
     End Get 
     Set(ByVal value As Integer) 
      mProductID = value 
     End Set 
    End Property 

    ReadOnly Property Categories() As IEnumerable(Of Category) 
     Get 
      Dim list As New List(Of Category) 
      list.Add(New Category With {.CategoryID = 1, .CategoryName = "Test1"}) 
      list.Add(New Category With {.CategoryID = 2, .CategoryName = "Test2"}) 

      Return list 
     End Get 
    End Property 

End Class 

답변

5

드롭 다운 목록 도우미가 IEnumerable<SelectListItem> 아닌 IEnumerable<Category> 소요이 부를 것이다 방법이다. 일반적으로 페이지에 특정 모델이 있어야합니다. 모델에는 컬렉션이 아닌 드롭 다운에서 선택한 값에 대한 속성이 포함됩니다. ViewData를 통해 선택할 컬렉션을 제공합니다. 선택할 속성과 컬렉션을 모두 포함하는보기 전용 모델을 가질 수 있지만 이는 클래스의 확산을 의미 할 수 있습니다. 급증하는 수업이나 마술 끈이 더 나쁜 디자인인지에 대한 논쟁이 있습니다. 코드에

필자는 것 같은 뭔가 : 푸 int ​​형의 속성 범주를 포함하는 클래스입니다

<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of Foo)" %> 
<asp:Content ID="aboutContent" ContentPlaceHolderID="MainContent" runat="server"> 
    <%=Html.DropDownList("Category", ViewData("CategoryList"))%> 
</asp:Content> 

Function Index() As ActionResult 
    Dim list As New List(Of SelectListItem) 
    list.Add(New SelectListItem With {.Value = 1, .Text = "Test1"}) 
    list.Add(New SelectListItem With {.Value = 2, .Text = "Test2"}) 
    ViewData("CategoryList") = list 
    Return View() 
End Function 

.당신이 강력한 형식의보기를하고 싶었다 경우

, 푸 유형의 SelectListItem의 속성 카테고리를 가지고 다음이, 다음 변경 :

<%=Html.DropDownList("Category", ViewData("CategoryList"))%> 

<%=Html.DropDownList("Category", Foo.Categories)%> 

ViewData("CategoryList") = list 
    Return View() 

to

Dim foo as New Foo 
    foo.Categories = list 
    Return View(foo) 
+1

동의합니다. 이것은 실제로 어떻게 할 것인가지만 그가 묻는 것처럼 느끼는 것의 직접적인 예로서 나의 대답을주었습니다. 좋은 코멘트와 예제 텍스트. –

1

모델을 DropDownList 도우미에 직접 매핑하는 Html.DropDownList에 대한 고유 한 도우미 메서드 오버로드를 만들 수 있습니다.

그렇다면 실제로 얼마나 많은 도메인 특정 논리에 포함시켜야하는지 스스로 물어야합니다. ViewData는 모델과 도메인 로직을 뷰에서 분리하는 데 도움이됩니다.

예 :

나는이 여전히 이름이 필요하기 때문에, 당신은 단지 드롭 다운의 이름을 문자열을 사용합니다 다른 방법을 원하는 것이라고 생각되지만 자동으로 결합하기 때문에 이것이 "과부하"아니라는 것을 알고 컨트롤에 대한 모델 (IEnumerable이라고 가정). 이것은 HtmlHelper 확장 메소드의 예입니다. 여기

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 
using System.Web.Mvc.Html; 

namespace MvcApplication3.Helpers 
{ 
    public static class ViewHelpers 
    { 
     public static string ModelDropDownList(this HtmlHelper htmlHelper, string name) 
     { 
      var model = htmlHelper.ViewData.Model as IEnumerable<SelectListItem>; 
      if(model == null) 
       return string.Empty; 

      return htmlHelper.DropDownList(name, model); 
     } 
    } 
} 

당신이보기

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<SelectListItem>>" %> 
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 
    <%= Html.ModelDropDownList("Test") %> 
</asp:Content> 
+0

충분히 그렇다면 테이블/등을 채우기 위해 강력하게 형식화 된 뷰가있는 시간이 있기 때문에 ViewData ("list")를 모델과 혼합 할 수 있지만 드롭 다운 목록을 채울 필요가 있습니다. 나는 같은 관점에서 둘 다 할 수 있을까? –

+1

예, 단순히 API에 과부하가 걸리지 만 표준 메소드 서명이 계속 존재할 수 있기 때문에 가능합니다. –

+0

우수! 나는이 방법을 택할 수 있습니다. 왜냐하면 저는 아직 맞춤 헬퍼 메소드 오버로드를 작성하고 있기 때문입니다. (요즘은 webforms에 관해서는 덜 생각하고 있습니다.) –

0

Strongly Typed 메서드를 사용하려면 IEnumerable을 전달할 수있는 SelectList 개체가 있어야합니다. 당신은 T의 텍스트 필드와 값 필드 속성을 지정해야하지만,이 selectList의 객체가 Html.DropDownList 도우미에 직접 할당 할 수 있습니다 : 다음

c# 
IList<Category> categories = new IList<Category>() 
    { 
     new Category() { ID = 1, Name = "Category 1" }, 
     new Category { ID = 2, Name = "Category 2" } 
    }; 

SelectList categoryDropDown = new SelectList(categories, "ID", "Name"); 

ViewData["categoryDropDown"] = categoryDropDown; 

은 수행

c# 
<%=Html.DropDownList("CategoryID", ViewData("categoryDropDown"))%> 

당신이 전달할 수 있습니다 그 방법을 (서비스 레이어, 컨트롤러 와이드 메서드)에서 카테고리의 IList에.

관련 문제