Привязка данных к TextBox WPF MVVM с использованием IDataErrorInfo

265
18 октября 2018, 08:00

Написал приложение. Все хорошо работало, свойства во вьюмодель биндил к текстовым полям вью Text

Text= "{Binding PersonName}"

Потом захотел сделать валидацию вводимых данных. Валидация работает, данные из полей в свойства не пишутся.

 <Window.Resources>
    <viewModels:RegistrationFormViewModel x:Key="RegistrationFormViewModel" />
    <converters:BitmapToImageSourceConverter x:Key="BitmapToImageSourceConverter"/>
    <viewModels:RegistrationFormViewModel x:Key="NameInstance" PersonName="" />
    <viewModels:RegistrationFormViewModel x:Key="LastNameInstance" PersonLastName="" />
    <viewModels:RegistrationFormViewModel x:Key="DepartmentInstance" PersonDepartment="" />
    <!-- IData Error style  -->
    <Style x:Key="TextErrorStyle" TargetType="{x:Type TextBox}">
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate x:Name="TextErrorTemplate">
                    <DockPanel>
                        <Border BorderBrush="Red" BorderThickness="2">
                            <AdornedElementPlaceholder/>
                        </Border>
                        <TextBlock FontSize="20" Foreground="Red">*!*</TextBlock>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="True">
                <!--<Setter Property="Background" Value="Red"/>-->
                <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.Errors)[0].ErrorContent}"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

Текст бокс

 <TextBox Background="Transparent" BorderBrush="Black" Height="30" Width="140" Style="{StaticResource TextErrorStyle}" 
                              TextAlignment="Center" Foreground="White" HorizontalAlignment="Center">
            <TextBox.Text>
                <Binding Path="PersonName" Source="{StaticResource NameInstance}" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <ExceptionValidationRule></ExceptionValidationRule>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
            <TextBox.ToolTip>
                <ToolTip HasDropShadow="True" Content="{Binding EnterPersonName}" />
            </TextBox.ToolTip>
        </TextBox>

Кусок вью модели

public class RegistrationFormViewModel : BaseViewModel, IDataErrorInfo
{
    #region TextBox properties
    /// <summary>
    /// Binding person name to TextBox
    /// </summary>
    [Required(AllowEmptyStrings = false)]
    public string PersonName { get; set; }
    /// <summary>
    /// Binding person last name TextBox
    /// </summary>
    [Required(AllowEmptyStrings = false)]
    public string PersonLastName { get; set; }
    /// <summary>
    /// Binding person department TextBox
    /// </summary>
    [Required(AllowEmptyStrings = false)]
    public string PersonDepartment { get; set; }
    /// <summary>
    /// Error indexer
    /// </summary>
    /// <param name="columnName"></param>
    /// <returns></returns>
    public string this[string columnName]
    {
        get
        {
            string error = String.Empty;
            switch (columnName)
            {
                case "PersonName":
                    if (PersonName == null || PersonName == "")
                    {
                        error = "Введите имя!";
                    }
                    break;
                case "PersonLastName":
                    if (PersonLastName == null || PersonLastName == "")
                    {
                        error = "Введите Фамилию!";
                    }
                    break;
                case "PersonDepartment":
                    if (PersonDepartment == null || PersonDepartment == "")
                    {
                        error = "Введите название отдела!";
                    }
                    break;
            }
            return error;
        }
    }
    /// <summary>
    /// Error exception throwing
    /// </summary>
    public string Error => "Введите данные!";

Базовый класс-наблюдатель

 /// <summary>
/// Class for view notification
/// </summary>
public abstract class NotificationObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    protected void SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (!EqualityComparer<T>.Default.Equals(field, value))
        {
            field = value;
            OnPropertyChanged(propertyName);
        }
    }
}
Answer 1

Сделал так.Убрал все статические ресурсы.

<!-- Это все убираем 
<viewModels:RegistrationFormViewModel x:Key="NameInstance" PersonName="" />
<viewModels:RegistrationFormViewModel x:Key="LastNameInstance" 
 PersonLastName="" />
<viewModels:RegistrationFormViewModel x:Key="DepartmentInstance" 
PersonDepartment="" /> -->

Далее:

<TextBox.Text>
            <Binding Path="PersonName" Source="{StaticResource 
            NameInstance}" ValidatesOnDataErrors="True" 
            UpdateSourceTrigger="PropertyChanged">

Заменил на

<TextBox.Text>
            <Binding Path="PersonName" ValidatesOnDataErrors="True" 
            UpdateSourceTrigger="PropertyChanged">

И все заработало как надо.

READ ALSO
отправка сообщения из C# в WhatsApp

отправка сообщения из C# в WhatsApp

Можно ли отправить сообщение из С# кода на WhatsApp?

341
Выполнить код одновременно

Выполнить код одновременно

Анимация идет друг за другом, а как ее выполнить одновременно? Пробовал потоки, но нельзя обращаться к GUI

199
Вывести Json object в HTML на JQuery. Asp.Net Core

Вывести Json object в HTML на JQuery. Asp.Net Core

Сначала покажу более ранению версию на бекенде, которая работала

295
Прочитать все данные из Com порта

Прочитать все данные из Com порта

Есть устройство которое возвращает по одной команде либо 26 либо 10 байтИспользую класс SerialPort

236