如何在ViewModel中获取CustomTextbox文本的实际值和验证

时间:2012-02-27 06:17:52

标签: mvvm silverlight-4.0 custom-component prism-4

我创建了自定义组件,用于显示简单或密码模式的文本,开发此控件的意图是 Silverlight不支持自定义TextMode(如密码或文本)。

这是我的要求 除了访问权限之外,组织还可以指定对数据库中某些字段的受限访问。对这些字段的访问限制将是Update和Redacted,这意味着如果某个特定字段对Update更新,那么用户将能够更新该字段并查看它,如果该字段对Redacted为真,那么用户将只能在字段中看到编辑的值(可能是星号 - * * * * *)。可以将字段设置为可更新和已编辑,这意味着用户将看到编辑的视图,但仍然可以使用新值更新字段。这种要求主要用于保存针对联系人的敏感信息或可用于区分联系的信息。

我已经为此要求创建了自定义控件,它运行正常。我能够动态设置TextMode,但我无法在ViewModel中获取原始值。 (我能够在View中获得原始值但在ViewModel中无法获得原始值)

如果我使用以下方式在View中访问原始值,则可以正常工作。

string s = UserName.Text;

但是没有在ViewModel中获取此值,它给了我 **

以下是 PasswordTextBox 控件的完整代码。

namespace QSys.Library.Controls
{
    public partial class PasswordTextBox : TextBox
    {
        #region Variables
        private string text = string.Empty;
        private string passwordChar = "*";
        private int selectionLength = 0;
        #endregion

        #region Properties
        /// <summary>
        /// The text associated with the control.
        /// </summary>
        public new string Text
        {
            get { return text; }
            set
            {
                text = value;
                DisplayMaskedCharacters();
            }
        }
        /// <summary>
        /// Indicates the character to display for password input.
        /// </summary>
        public string PasswordChar
        {
            get { return passwordChar; }
            set { passwordChar = value; }
        }
        /// <summary>
        /// Indicates the input text mode to display for either text or password.
        /// </summary>
        public Mode TextMode
        {
            get { return (Mode)GetValue(TextModeProperty); }
            set { SetValue(TextModeProperty, value); }
        }
        public static readonly DependencyProperty TextModeProperty = DependencyProperty.Register("TextMode", typeof(Mode), typeof(PasswordTextBox), new PropertyMetadata(default(Mode)));
        #endregion

        #region Constructors
        public PasswordTextBox()
        {
            this.Loaded += new RoutedEventHandler(PasswordTextBox_Loaded);
        }
        #endregion

        #region Event Handlers
        void PasswordTextBox_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            if (this.TextMode == Mode.Password)
            {
                text = base.Text;
                this.TextChanged += new TextChangedEventHandler(PasswordTextBox_TextChanged);
                this.KeyDown += new KeyEventHandler(PasswordTextBox_KeyDown);
                this.SelectionChanged += new RoutedEventHandler(PasswordTextBox_SelectionChanged);
                DisplayMaskedCharacters();
            }
            this.Loaded -= PasswordTextBox_Loaded;
        }
        void PasswordTextBox_SelectionChanged(object sender, RoutedEventArgs e)
        {
            selectionLength = this.SelectionLength;
        }
        public void PasswordTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (base.Text.Length >= text.Length)
                text += base.Text.Substring(text.Length);
            else
            {
                int cursorPosition = this.SelectionStart;
                selectionLength = (selectionLength > 1) ? selectionLength : 1;
                text = text.Remove(cursorPosition, selectionLength);
            }
            DisplayMaskedCharacters();
            selectionLength = 0;
        }
        public void PasswordTextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            int cursorPosition = this.SelectionStart;
            // Handle Delete and Backspace Keys Appropriately
            if (e.Key == System.Windows.Input.Key.Back && cursorPosition > 0)
            {
                DeleteAt(cursorPosition);
            }
            else if (e.Key == System.Windows.Input.Key.Delete)
            {
                DeleteAt(cursorPosition);
            }
            else
            {
                if (selectionLength > 0) text = text.Remove(cursorPosition, selectionLength);
                base.Text = text;
                this.Select((cursorPosition > text.Length ? text.Length : cursorPosition), 0);
                DisplayMaskedCharacters();
            }
            selectionLength = 0;
        }
        #endregion

        #region Private Methods
        private void DisplayMaskedCharacters()
        {
            int cursorPosition = this.SelectionStart;
            // This changes the Text property of the base TextBox class to display all Asterisks in the control
            base.Text = new string(passwordChar.ToCharArray()[0], text.Length);
            this.Select((cursorPosition > text.Length ? text.Length : cursorPosition), 0);
        }
        private void DeleteAt(int position)
        {
            if (text.Length > position)
            {
                text = text.Remove(position, 1);
                base.Text = base.Text.Remove(position, 1);
            }
        }
        #endregion
    }
}

LoginView.xaml

<control:PasswordTextBox  x:Name="UserName" TabIndex="1" Grid.Row="1" TextMode="Password" Text="{Binding Path=LoginModelValue.UserName, Mode=TwoWay,ValidatesOnNotifyDataErrors=True, ValidatesOnExceptions=True, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="1" Width="200" Height="25" Validatevalue:UpdateSourceTriggerHelper.UpdateSourceTrigger="True"/>

LoginViewModel.cs

public class LoginViewModel : INotifyPropertyChanged, IRegionMemberLifetime
    {
public LoginModel LoginModelValue
        {
            get { return _LoginModelValue; }
            set
            {
                _LoginModelValue = value;
                OnPropertyChanged("LoginModelValue");
            }
        }
}

LoginModel.cs

namespace QSys.Model
{
    public class LoginModel : INotifyPropertyChanged
    {
        #region Variables
        private string _userName;
        private string _password;
        #endregion

        #region Constructor
        public LoginModel()
        {
        }
        #endregion

        #region Properties
        [CustomValidation(typeof(PasswordTextBox), "IsValidUserName")]
        [Required(ErrorMessage = "User Name is required")]
        [Display(Name = "UserName")]
        [StringLength(50)]
        //[RegularExpression(@"^[a-zA-Z\\0-9\\.\\,\\'\s]+$", ErrorMessage = "Please enter right format.")]
        public string UserName
        {
            get { return _userName; }
            set
            {
                _userName = value;
                OnPropertyChanged("UserName");
                ValidateProperty("UserName", value);
            }
        }
        [Required(ErrorMessage = "Password is required")]
        [Display(Name = "Password")]
        [StringLength(10)]
        public string Password
        {
            get { return _password; }
            set
            {
                _password = value;
                OnPropertyChanged("Password");
                ValidateProperty("Password", value);
            }
        }
        #endregion

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged = delegate { };
        private void OnPropertyChanged(string propertyName)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion

        #region Private Methods
        public bool IsValidObject()
        {
            ICollection<ValidationResult> results = new Collection<ValidationResult>();
            return Validator.TryValidateObject(this, new ValidationContext(this, null, null), results, true) && results.Count == 0;
        }
        public void ValidateProperty(string propertyName, object value)
        {
            Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = propertyName });
        }
        #endregion
    }
}

**我正在寻找解决方案,因为两天没有运气。

如果您有任何解决方案,请帮助我,您的意见或建议将受到高度赞赏。**

由于

Imdadhusen

2 个答案:

答案 0 :(得分:0)

在常规UserControlTextBox周围构建自己的PasswordBox并在依赖项属性TextMode发生变化时切换其可见性会不会更容易?然后,您可以为UserControl设置一个具有属性Value的VM,并以TwoWay模式绑定TextProperty TextBoxPassword } PasswordBox的属性。

答案 1 :(得分:0)

我已解决使用以下代码。

我在LoginView.xaml中缺少Mode = TwoWay:

<control:RestrictedBox Type="Text" Value="{Binding Path=UserName,Mode=TwoWay}">

谢谢, Imdadhusen