MTR
MTR

Reputation: 1740

How to trigger a new validation when a textbox gets enabled?

In a wpf dialog window I have a checkbox that enables and disables a textbox. The textbox has ValidatesOnDataErrors set to True. Via IDataErrorInfo I check the value of this textbox only, if the checkbox is checked.

My problem is that if the user checks the checkbox there is no new validation on textbox performed and therefor I dont get this red frame indicating an error.

For demonstration here is a small sample:

<Window x:Class="Validation.ValidationWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ValidationWindow" Height="300" Width="300">
<DockPanel LastChildFill="False">
    <CheckBox DockPanel.Dock="Top" IsChecked="{Binding InputAllowed}">Input allowed</CheckBox>
    <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
        <Label>InputValue</Label>
        <TextBox Text="{Binding InputValue, ValidatesOnDataErrors=True}" IsEnabled="{Binding InputAllowed}" Width="50"/>
    </StackPanel>
    <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
        <Label>InputValue2</Label>
        <TextBox Text="{Binding InputValue2, ValidatesOnDataErrors=True}" Width="50"/>
    </StackPanel>
    <Button DockPanel.Dock="Bottom" Click="OnOk">Ok</Button>
</DockPanel>
</Window>

code behind:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Validation
{
/// <summary>
/// Interaction logic for ValidationWindow.xaml
/// </summary>
public partial class ValidationWindow : Window, IDataErrorInfo
{
    public bool InputAllowed
    {
        get { return (bool)GetValue(InputAllowedProperty); }
        set { SetValue(InputAllowedProperty, value); }
    }
    public static readonly DependencyProperty InputAllowedProperty =
        DependencyProperty.Register("InputAllowed", typeof(bool), typeof(ValidationWindow), new PropertyMetadata(false));

    public int InputValue
    {
        get { return (int)GetValue(InputValueProperty); }
        set { SetValue(InputValueProperty, value); }
    }
    public static readonly DependencyProperty InputValueProperty =
        DependencyProperty.Register("InputValue", typeof(int), typeof(ValidationWindow), new PropertyMetadata(0));

    public int InputValue2
    {
        get { return (int)GetValue(InputValue2Property); }
        set { SetValue(InputValue2Property, value); }
    }
    public static readonly DependencyProperty InputValue2Property =
        DependencyProperty.Register("InputValue2", typeof(int), typeof(ValidationWindow), new PropertyMetadata(0));


    public ValidationWindow()
    {
        InitializeComponent();
        DataContext = this;
    }

    private void OnOk(object sender, RoutedEventArgs e)
    {
        string msg = Error;
        if(!string.IsNullOrEmpty(Error))
        {
            MessageBox.Show(Error);
            return;
        }
        DialogResult = true;
    }

    #region IDataErrorInfo Members

    public string Error
    {
        get { return ((IDataErrorInfo)this)[null]; }
    }

    public string this[string columnName]
    {
        get
        {
            string msg = string.Empty;

            if(string.IsNullOrEmpty(columnName))
            {
                msg += ((IDataErrorInfo)this)["InputValue"];
                msg += ((IDataErrorInfo)this)["InputValue2"];
            }
            else
            {
                switch(columnName)
                {
                case "InputValue":
                    if(InputAllowed)
                    {
                        if(InputValue <= 0)
                        {
                            msg += "InputValue must be greater that 0!";
                        }
                    }
                    break;
                case "InputValue2":
                    if(InputValue2 <= 0)
                    {
                        msg += "InputValue2 must be greater that 0!";
                    }
                    break;
                }
            }

            return msg;
        }
    }

    #endregion

}
}

Upvotes: 0

Views: 1121

Answers (2)

Dbl
Dbl

Reputation: 5894

No actual difference from stijn's solution but since we're all a little lazy:

public static class DependencyPropertyExtensions
{
    public static bool UpdateSource(this FrameworkElement source, DependencyProperty property)
    {
        var binding = source.GetBindingExpression(property);
        if (binding != null)
        {
            binding.UpdateSource();
            return true;
        }

        return false;
    }
}

Upvotes: 1

stijn
stijn

Reputation: 35901

We've been using this to force validation after programatcially changing text, should work as well if you call it in reponse to your checkbox's events:

var binding = someTextBox.GetBindingExpression( TextBox.TextProperty );
if( binding == null )
  return;
binding.UpdateSource();

Upvotes: 2

Related Questions