2012-01-05 2 views
8

의 ViewModel :WPF TextBox MaxLength - 바운드 필드의 데이터 유효성 검사 최대 길이에 바인딩 할 수있는 방법이 있습니까?

public class MyViewModel 
{ 
    [Required, StringLength(50)] 
    public String SomeProperty { ... } 
} 

XAML :

<TextBox Text="{Binding SomeProperty}" MaxLength="50" /> 

내 뷰 모델을 (그것은 다른 어셈블리에 있기 때문에 변경할 수있는) 일치하는 텍스트 상자의 최대 길이를 설정 피하기 위해 어떤 방법이 있나요 및 StringLength 요구 사항에 따라 자동으로 최대 길이를 설정합니까?

답변

0

한 가지 방법은 SomePropertyMaxLength라는 동일한 viewmodel에서 속성을 만든 다음 MaxLength 속성을 해당 속성에 바인딩하는 것입니다. 나는 완전히 자신의 코드를 작성하지 않을거야 동안

<TextBox Text="{Binding SomeProperty}" MaxLength="{Binding SomePropertyMaxLength}"/> 
+0

예, 저는 그것에 대해 생각해 보았습니다. 그러나 메타 데이터를 반영한 ​​모든 속성을 추가하고 속성을 추가하는 것을 피하고 싶었습니다. 그런 다음 내 모든 xaml을 통과하여 해당 속성에 바인딩했습니다. 표지 "유형의 ... 아마 붙어있는 행동에 의해? – michael

+1

"SomeProperty"를 문자열 값과 maxlength 값을 포함하는 개체로 변경 한 다음 해당 속성에 각각 바인딩 할 수 있습니다. 이렇게하면 새 속성을 만들 필요는 없지만 xaml 변경을 계속해야합니다. – evasilchenko

1

은 하나 개의 아이디어는 속성 이름을하고 StringLengthAttribute 찾고 이상 반영하는 것이다 MarkupExtension 당신의 자신을 만드는 것입니다.

특성이있는 경우 리플렉션을 사용하여 대상을 해당 값에 바인딩하십시오. 그렇지 않은 경우 0을 목표 값에 바인딩합니다 (기본값은 0입니다. 즉 최대 값 없음).

+0

저는이 확장 프로그램을 작성하는 방법을 알아 내려고 노력하면서 시간을 벌었습니다. – michael

14

TextBox를 바인딩 된 속성의 유효성 검사 속성 (있는 경우)에 연결하기 위해 Behavior을 사용했습니다. 동작은 다음과 같습니다

/// <summary> 
/// Set the maximum length of a TextBox based on any StringLength attribute of the bound property 
/// </summary> 
public class RestrictStringInputBehavior : Behavior<TextBox> 
{ 
    protected override void OnAttached() 
    { 
     AssociatedObject.Loaded += (sender, args) => setMaxLength(); 
     base.OnAttached(); 
    } 

    private void setMaxLength() 
    { 
     object context = AssociatedObject.DataContext; 
     BindingExpression binding = AssociatedObject.GetBindingExpression(TextBox.TextProperty); 

     if (context != null && binding != null) 
     { 
      PropertyInfo prop = context.GetType().GetProperty(binding.ParentBinding.Path.Path); 
      if (prop != null) 
      { 
       var att = prop.GetCustomAttributes(typeof(StringLengthAttribute), true).FirstOrDefault() as StringLengthAttribute; 
       if (att != null) 
       { 
        AssociatedObject.MaxLength = att.MaximumLength; 
       } 
      } 
     } 
    } 
} 

당신이 볼 수있는, 행동이 단순히 텍스트 상자의 데이터 컨텍스트를 검색하고 "텍스트"에 대한 바인딩 식. 그런 다음 리플렉션을 사용하여 "StringLength"특성을 얻습니다.

<UserControl 
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 

    <TextBox Text="{Binding SomeProperty}"> 
     <i:Interaction.Behaviors> 
      <local:RestrictStringInputBehavior /> 
     </i:Interaction.Behaviors> 
    </TextBox> 

</UserControl> 

당신은 또한 TextBox을 확장하여이 기능을 추가 할 수 있지만, 나는 그들이 모듈 형이기 때문에 비헤이비어를 사용하여 같은 : 사용법이 같다.

0

분명히 마크 업 확장 기능이 있습니다. 모델 DataType 종속성 속성이있는 Binding이라는 BindingDecoratorBase의 하위 클래스를 만듭니다. MarkupExtensions는 InitializeComponent() 중에 만들어 지므로 DataContext가 아직 설정되지 않았으므로이를 확인할 방법이 없습니다.

모델 유형을 제공하면 모델에 정의 된 속성에 대한 액세스가 허용됩니다. 허용 :

  • 텍스트 상자의 MaxLength 설정.
  • TextBlock에 대한 StringFormat 설정.
  • 구성원 데이터 형식에 따라 기본 변환기 설정.
  • 필요한 유효성 검사 추가. 바인딩의 ValidationRules를 사용하거나 ValidatesOnDataErrors를 설정하여.

마크 업 보이는 같은 : 텍스트 = "{PO : 바인딩 데이터 형식 = 모델 : modAccount, 경로 = 하위 계정}"

포맷, 최대 길이 및 변환 아무것도 변경할 필요없이 하나 개의 패키지로 출시 모델 클래스가 변경됨에 따라

+0

이 하위 클래스의 코드 샘플이 있습니까? – TaterJuice