2012-02-29 15 views
2

TextBoxとPasswordBoxを含むカスタムユーザーコントロールを作成しました。私はTextBoxをUserNameとPassowrdBoxにもバインドします。 UserNameはLoginViewModelクラスで[必須]属性で定義されています。今、私のカーソルがTextBoxから値を入力せずにUserNameプロパティを入力しなくても、プロパティが変更されました(INotifyPropertyChanged)、 しかし、赤い枠線で私のテキストボックス(ユーザコントロールの中にあります)をマークしません。検証が実行されましたが、Silverlight 4でユーザーコントロールに赤い枠線が表示されません

以下は私のユーザーコントロールのコードです。

RestrictedBox.xaml

<Grid x:Name="LayoutRoot" Background="Transparent" Margin="0" > 
     <TextBox x:Name="txtTextBox" HorizontalAlignment="Stretch" Height="25" /> 
     <PasswordBox x:Name="txtPasswordBox" HorizontalAlignment="Stretch" Height="25" /> 
</Grid> 

RestrictedBox.xaml.cs

public partial class RestrictedBox : UserControl 
    { 
     #region Properties 
     public string Value 
     { 
      get { return (string)GetValue(ValueProperty); } 
      set { SetValue(ValueProperty, value); } 
     } 
     public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(RestrictedBox), new PropertyMetadata("", ValueChanged)); 
     private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
     } 
     public bool Updateable 
     { 
      get { return (bool)GetValue(UpdateableProperty); } 
      set { SetValue(UpdateableProperty, value); } 
     } 
     public static readonly DependencyProperty UpdateableProperty = DependencyProperty.Register("Updateable", typeof(bool), typeof(RestrictedBox), new PropertyMetadata(UpdateableChanged)); 
     private static void UpdateableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
     } 
     public bool Redactable 
     { 
      get { return (bool)GetValue(RedactableProperty); } 
      set { SetValue(RedactableProperty, value); } 
     } 
     public static readonly DependencyProperty RedactableProperty = DependencyProperty.Register("Redactable", typeof(bool), typeof(RestrictedBox), new PropertyMetadata(RedactableChanged)); 
     private static void RedactableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
     } 
     #endregion 
     #region Constructors 
     public RestrictedBox() 
     { 
      InitializeComponent(); 
      txtTextBox.SetBinding(TextBox.TextProperty, new Binding { Source = this, Path = new PropertyPath("Value"), Mode = BindingMode.TwoWay}); 
      txtTextBox.SetBinding(TextBox.VisibilityProperty, new Binding("Redactable") { Source = this, Converter = new BoolToVisibilityConverterReverse() }); 
      txtPasswordBox.SetBinding(PasswordBox.PasswordProperty, new Binding { Source = this, Path = new PropertyPath("Value"), Mode = BindingMode.TwoWay }); 
      txtPasswordBox.SetBinding(TextBox.VisibilityProperty, new Binding("Redactable") { Source = this, Converter = new BoolToVisibilityConverter() }); 
     } 
     #endregion 
    } 

後、私はLoginView.xaml

私のカスタムユーザーコントロールを使用するコードです

<Control:RestrictedBox x:Name="UserName" VerticalAlignment="Top" TabIndex="2" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" Height="40" Value="{Binding Path=LoginModelValue.UserName, Mode=TwoWay, ValidatesOnNotifyDataErrors=True, ValidatesOnExceptions=True, 
ValidatesOnDataErrors=True, NotifyOnValidationError=True}" Validatevalue:UpdateSourceTriggerHelper.UpdateSourceTrigger="True" Redactable="True" Updateable="True" /> 

LoginView.xaml.cs

[Export(typeof(LoginView))] 
    [PartCreationPolicy(CreationPolicy.NonShared)] 
    public partial class LoginView : UserControl, IPageTitle 
    { 
     #region Constuctors 
     public LoginView() 
     { 
      InitializeComponent(); 
     } 
     [Import] 
     public LoginViewModel ViewModel 
     { 
      get {return this.DataContext as LoginViewModel;}    
      set { DataContext = value; } 
     } 
     #endregion 
    } 

LoginViewModel.cs

[Export] 
    [PartCreationPolicy(CreationPolicy.NonShared)] 
    public class LoginViewModel : INotifyPropertyChanged, IRegionMemberLifetime 
    { 
     private LoginModel _LoginModelValue; 
     public LoginModel LoginModelValue 
     { 
      get { return _LoginModelValue; } 
      set 
      { 
       _LoginModelValue = value; 
       OnPropertyChanged("LoginModelValue"); 
      } 
     } 
     #region INotifyPropertyChanged 
     public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
     private void OnPropertyChanged(string propertyName) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
     void LoginModelValue_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
     { 
      if (LoginModelValue.IsValidObject()) 
      { 
       LoginCommand.RaiseCanExecuteChanged(); 
       IsEnabled = LoginModelValue.IsValidObject(); 
       SetIncorrectLogin(!IsEnabled); 
      } 
     } 
     #endregion 
    } 

は、誰もが、私は赤い枠を取得していない午前理由アイデアがある私のTextBoxに囲まれていますができます私のカスタムユーザーコントロールの中に?

ご質問、ご意見、ご感想をお寄せください。

おかげで、

Imdadhusen

+0

は検証があなたの全体の制御ではなく、そのコントロールを構成する個々のコンポーネントです。 – ChrisF

+0

あなたは何を言っているのか分かりませんので、少し深く説明できますか?迅速な返信をありがとう。 – imdadhusen

+1

データをバインドするコントロールに依存関係プロパティを作成する必要があります。その後、内部的に、そのプロパティの適切なプロパティを個々のコントロールにバインドします。 *そのバインディングにバリデーションを含めると、赤いボックスが正しい場所に表示されます。 – ChrisF

答えて

1

次のコードを使用して問題を解決しました。 Iは、次のコード

this.MapBinding(RestrictedControl.ValueProperty, txtTextBox, TextBox.TextProperty); 

とライン

txtTextBox.SetBinding(TextBox.VisibilityProperty, new Binding("Redactable") { Source = this, Converter = new BoolToVisibilityConverterReverse() }); 

以下に置き換えて、コメントを追加しました。それでおしまい。

namespace QSys.Library.Helpers 
{ 
    public static class FrameworkElementExtension 
    { 
     public static void MapBinding(this FrameworkElement element, DependencyProperty firstProperty, FrameworkElement targetElement, DependencyProperty secondProperty) 
     { 
      BindingExpression firstExpression = element.GetBindingExpression(firstProperty); 
      if (firstExpression != null && firstExpression.ParentBinding != null) 
      { 
       targetElement.SetBinding(secondProperty, firstExpression.ParentBinding); 
      } 
     } 
    } 
} 

私は特にこれを探していました。私は非常に感謝していますRakesh Gunijan(http://www.codeproject.com/Articles/293302/Silverlight-user-control-validation)非常に明確にどのようにexpain。

おかげで、

Imdadhusen

1

私はすでに言ったように、検証が結合1に対してのみ機能し、あなたの場合のように、結果としてbindignsによって継承されません。

最も簡単な方法は、あなたのコントロールのValueプロパティに直接Required注釈を追加して、もう一度それを検証するために、次のようになります。

[Required] 
public string Value 
{ 
    get { return (string)GetValue(ValueProperty); } 
    set { SetValue(ValueProperty, value); } 
} 
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(RestrictedBox), new PropertyMetadata("", ValueChanged)); 
private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    var rb = d as RestrictedBox; 
    Validator.ValidateProperty(rb.Value, new ValidationContext(rb, null, null) { MemberName = "Value" }); 
} 

をされており、検証が動作するようにあなたのバインディングにValidatesOnExceptions属性を追加します。

txtTextBox.SetBinding(TextBox.TextProperty, new Binding { Source = this, Path = new PropertyPath("Value"), Mode = BindingMode.TwoWay, 
    ValidatesOnExceptions = true }); 
//... 
txtPasswordBox.SetBinding(PasswordBox.PasswordProperty, new Binding { Source = this, Path = new PropertyPath("Value"), Mode = BindingMode.TwoWay, 
    ValidatesOnExceptions = true }); 
//... 

もう1つの方法:すべてのプロパティを削除し、RestrictedBoxコントロールをビューモデルに直接バインドします。

<TextBox x:Name="txtTextBox" HorizontalAlignment="Stretch" Height="25" 
     Text="{Binding LoginModelValue.UserName, Mode=TwoWay, ValidatesOnExceptions=True}" /> 
<PasswordBox x:Name="txtPasswordBox" HorizontalAlignment="Stretch" Height="25" 
      Password="{Binding LoginModelValue.UserName, Mode=TwoWay, ValidatesOnExceptions=True}" /> 

これらのソリューションは、理想からかけ離れ思えますが、実際にはデータの注釈による検証は、設計によって良くありません。 INotifyDataErrorInfoインターフェイスを使用することをお勧めします。

+0

**完全な説明をいただきありがとうございます。**ありますが、検証属性は修正されていません。 **このカスタムコントロールは完全に動的なので、値の提出が必要ではなく、ある程度時間がかかる場合は、任意のモデルをバインドすることができます。 ** – imdadhusen

+0

@imdadhusenあなたのケースでは、データアノテーションが最悪の解決策であり、私はあなたのようなシナリオでそれらを使用することがいつでも可能であるとは確信していません。コントロールを一時的なコントロールとして書き直すか、INotifyDataErrorInfoインターフェイスを使用します。 – vorrtex

+0

あなたの絶え間ないサポートに感謝します。いくつかの代替案を見つけることができます。 +1の私の投票 – imdadhusen

関連する問題