2010-03-16 4 views
5

Я хотел бы создать функциональность привязки модели, чтобы пользователь мог ввести ',' '.' и т. д. для значений валюты, которые привязаны к двойному значению моего ViewModel.asp.net MVC 1.0 и 2.0 привязка модели валюты

Я смог сделать это в MVC 1.0, создав настраиваемое связующее устройство, однако с момента его обновления до MVC 2.0 эта функция больше не работает.

У кого-нибудь есть идеи или лучшие решения для выполнения этой функции? Лучшим решением было бы использовать некоторую аннотацию данных или пользовательский атрибут.

public class MyViewModel 
{ 
    public double MyCurrencyValue { get; set; } 
} 

Предпочтительным решением было бы что-то вроде этого ...

public class MyViewModel 
{ 
    [CurrencyAttribute] 
    public double MyCurrencyValue { get; set; } 
} 

Ниже мое решение для модели связывания в MVC 1.0.

public class MyCustomModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     object result = null; 

     ValueProviderResult valueResult; 
     bindingContext.ValueProvider.TryGetValue(bindingContext.ModelName, out valueResult); 
     bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueResult); 

     if (bindingContext.ModelType == typeof(double)) 
     { 
      string modelName = bindingContext.ModelName; 
      string attemptedValue = bindingContext.ValueProvider[modelName].AttemptedValue; 

      string wantedSeperator = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator; 
      string alternateSeperator = (wantedSeperator == "," ? "." : ","); 

      try 
      { 
       result = double.Parse(attemptedValue, NumberStyles.Any); 
      } 
      catch (FormatException e) 
      { 
       bindingContext.ModelState.AddModelError(modelName, e); 
      } 
     } 
     else 
     { 
      result = base.BindModel(controllerContext, bindingContext); 
     } 

     return result; 
    } 
} 

ответ

7

Вы могли бы попробовать что-то между строк:

// Just a marker attribute 
public class CurrencyAttribute : Attribute 
{ 
} 

public class MyViewModel 
{ 
    [Currency] 
    public double MyCurrencyValue { get; set; } 
} 


public class CurrencyBinder : DefaultModelBinder 
{ 
    protected override object GetPropertyValue(
     ControllerContext controllerContext, 
     ModelBindingContext bindingContext, 
     PropertyDescriptor propertyDescriptor, 
     IModelBinder propertyBinder) 
    { 
     var currencyAttribute = propertyDescriptor.Attributes[typeof(CurrencyAttribute)]; 
     // Check if the property has the marker attribute 
     if (currencyAttribute != null) 
     { 
      // TODO: improve this to handle prefixes: 
      var attemptedValue = bindingContext.ValueProvider 
       .GetValue(propertyDescriptor.Name).AttemptedValue; 
      return SomeMagicMethodThatParsesTheAttemptedValue(attemtedValue); 
     } 
     return base.GetPropertyValue(
      controllerContext, 
      bindingContext, propertyDescriptor, 
      propertyBinder 
     ); 
    } 
} 

public class HomeController: Controller 
{ 
    [HttpPost] 
    public ActionResult Index([ModelBinder(typeof(CurrencyBinder))] MyViewModel model) 
    { 
     return View(); 
    } 
} 

UPDATE:

Вот улучшение вяжущего (см TODO раздел в предыдущем коде):

if (!string.IsNullOrEmpty(bindingContext.ModelName)) 
{ 
    var attemptedValue = bindingContext.ValueProvider 
     .GetValue(bindingContext.ModelName).AttemptedValue; 
    return SomeMagicMethodThatParsesTheAttemptedValue(attemtedValue); 
} 

В для того, чтобы обрабатывать коллекции вам нужно будет зарегистрировать вяжущего в Application_Start как вы больше не будете иметь возможность украсить список с ModelBinderAttribute:

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 
    RegisterRoutes(RouteTable.Routes); 
    ModelBinders.Binders.Add(typeof(MyViewModel), new CurrencyBinder()); 
} 

И тогда ваше действие может выглядеть следующим образом:

[HttpPost] 
public ActionResult Index(IList<MyViewModel> model) 
{ 
    return View(); 
} 
Подводя итог

важная часть:

bindingContext.ValueProvider.GetValue(bindingContext.ModelName) 

Следующим шагом усовершенствование этого связующего будет обрабатывать проверки (AddModelErro r/SetModelValue)

+0

Если вы имеете дело со списком MyViewModel, это изменит ModelBinder для действия? Публичный индекс активности в действии ([ModelBinder (typeof (CurrencyBinder))] IList модель) – David

+0

См. Мое обновление. –

 Смежные вопросы

  • Нет связанных вопросов^_^