Как получить фактическое значение и проверить текст CustomTextbox в ViewModel - PullRequest
3 голосов
/ 27 февраля 2012

Я создал пользовательский компонент для отображения текста в режиме «Простой» или «Пароль», намерение разработать этот элемент управления - Silverlight не поддерживает пользовательский режим TextMode (например, «Пароль» или «Текст»).

Это мое требование В дополнение к правам доступа организации смогут указывать ограниченный доступ к определенным полям в базе данных. Ограничение доступа к этим полям будет «Обновлять и редактировать», что означает, что если конкретное поле имеет значение «истина» для «Обновления», то пользователь сможет обновить поле и просматривать его, а если поле имеет значение «истина» для «Отредактировано», то пользователь быть в состоянии видеть только отредактированное значение в поле (возможно, звездочки - * * * * *). Будет возможно установить для поля возможность обновления и отредактировать, что означает, что пользователь увидит отредактированное представление, но все равно сможет перейти и обновить поле с новым значением. Такое требование в основном используется при хранении конфиденциальной информации о контакте или информации, которая может использоваться для дискриминации контакта.

Я создал пользовательский элемент управления для этого требования, и он работает отлично. Я могу установить TextMode динамически, но я не смог получить исходное значение в моей ViewModel. (Я могу получить исходное значение в View, но не могу в ViewModel)

Если я получаю доступ к исходному значению в представлении, используя следующее, то это работа.

string s = UserName.Text;

но не получая это значение во ViewModel, оно дает мне как **.

Ниже приведен полный код для PasswordTextBox control.

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 голосов
/ 02 марта 2012

Я решил использовать следующий код.

Мне не хватает Mode = TwoWay в LoginView.xaml:

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

Спасибо, Imdadhusen

0 голосов
/ 28 февраля 2012

Не проще ли построить свои собственные UserControl вокруг обычных TextBox и PasswordBox и просто переключать их видимость при изменении свойства зависимости TextMode? После этого вы можете иметь одну виртуальную машину для UserControl со свойством Value и связывать в режиме TwoWay как TextProperty TextBox, так и свойство Password PasswordBox.

...