2

I have three text boxes on my wpf application. When the user enters the value in these text boxes and clicks on Add, these are added to the list and displayed in data grid.

The text boxes are not bound to anything as such and I add these text box values to an observale collection bound to data grid. I want to prevent the user to enter empty values in text boxes. How is that done?

I saw some examples but those all had the text box boudn to values and then used Binding.Validation. How will this be done in my case when there's binding to text box?

I also have a button which has to be freezed when the empty values are being entered. for that, I sed the following approach by making a class and binding the class in the following manner;

<Button.Style>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="IsEnabled" Value="false" />
                    <Style.Triggers>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding ElementName=textBox1, Path=(Validation.HasError)}" Value="false" />
                                <Condition Binding="{Binding ElementName=textBox2, Path=(Validation.HasError)}" Value="false" />
                                <Condition Binding="{Binding ElementName=TextBoxAge, Path=(Validation.HasError)}" Value="false" />                                
                            </MultiDataTrigger.Conditions>
                            <Setter Property="IsEnabled" Value="true" />
                        </MultiDataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>

.cs class

 public class TextBoxNotEmptyValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            string str = value as string;
            if (str != null)
            {
                if (str.Length > 0)
                    return ValidationResult.ValidResult;
            }
            return new ValidationResult(false, Message);
        }
        public string Message { get; set; }
    }
Anatoliy Nikolaev
  • 22,370
  • 15
  • 69
  • 68
user1240679
  • 6,829
  • 17
  • 60
  • 89
  • Why not bind your textboxes to values, as with the examples you've seen? This will encourage you towards better-structured code, which will benfit you longer term. – Dan Puzey Aug 01 '12 at 14:42
  • @DanPuzey: Can you explain how that binding will occur and the values will be added to the observable collection? I kind of didn't get that concept ;-/ – user1240679 Aug 01 '12 at 14:44

1 Answers1

1

If I understand you right you're looking for something like this:

<Button.Style>
    <Style TargetType="{x:Type Button}">
        <Setter Property="IsEnabled" Value="True" />
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding Text, ElementName=textBox1}" Value="{x:Static s:String.Empty}" />
                    <Condition Binding="{Binding Text, ElementName=textBox2}" Value="{x:Static s:String.Empty}" />
                    <Condition Binding="{Binding Text, ElementName=TextBoxAge}" Value="{x:Static s:String.Empty}" />
                </MultiDataTrigger.Conditions>
                <Setter Property="IsEnabled" Value="False" />
            </MultiDataTrigger>
        </Style.Triggers>
    </Style>
</Button.Style>

Add this namespace

xmlns:s="clr-namespace:System;assembly=mscorlib"

Update

Then this will work:

<Button.Style>
    <Style TargetType="{x:Type Button}">
        <Style.Resources>
            <local:MyTextValidationConverter x:Key="MyTextValidationConverter" />
        </Style.Resources>
        <Setter Property="IsEnabled">
            <Setter.Value>
                <MultiBinding Converter="{StaticResource MyTextValidationConverter}">
                    <Binding Path="Text" ElementName="textBox1" />
                    <Binding Path="Text" ElementName="textBox2" />
                </MultiBinding>
            </Setter.Value>
        </Setter>
    </Style>
</Button.Style>

And this Converter code

public class MyTextValidationConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string text1 = values[0] as string;
        if (string.IsNullOrEmpty(text1)) return false;

        string text2 = values[1] as string;
        if (string.IsNullOrEmpty(text2)) return false;

        return true;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
LPL
  • 16,827
  • 6
  • 51
  • 95
  • Looks like filling one of the text box enable the button. I want to enforece the non-empty validation for two of these text boxes. – user1240679 Aug 01 '12 at 16:03
  • Specify what you want. Which two TextBoxes? And do you want the Button enabled if both non empty or only one? – LPL Aug 01 '12 at 16:08
  • `textBox1` and `textBox2` should not accept empty inputs. Both should be filled by the user before the button is enabled. The third text box can be empty though – user1240679 Aug 01 '12 at 16:48
  • That's a pity because there is no "Or"-MultiDataTrigger or any check for NotEmpty. I've edited my answer with a MultiBinding solution. – LPL Aug 01 '12 at 17:18
  • And this is supposed to be better than using code to perform these tasks? WPF boggles my mind... You have replaced a single if statement with ~40 lines of nonsense. – Ed S. Aug 01 '12 at 17:19
  • @EdS. If he would follow MVVM it would be almost as easy. – LPL Aug 01 '12 at 17:29
  • @LPL: ...I just enjoy ranting about WPF, don't take me too seriously :D. I can't stand the fact that they made simple tasks hard in an effort to make previously difficult tasks easier. – Ed S. Aug 01 '12 at 17:32
  • @LPL: Can you mention how it would be easy(ier) with MVVM becuase I am following the pattern right now – user1240679 Aug 01 '12 at 18:00
  • @LPL: And instead of Oe MultiData Trigger, is there an and multidata trigger o so I can make all of the text boxes mandatory – user1240679 Aug 01 '12 at 18:15
  • MultiDataTrigger is "And" by default. All conditions have to be true to trigger. In MVVM you would bind all TextBox.Text and Button.IsEnabled properties to corresponding properties in a ViewModel which you set as DataContext of your View. Then in ViewModel you can access all needed strings to compute if button should be enabled `get { return !string.IsNullOrEmpty(text1) && !string.IsNullOrEmpty(text2); }`. Or you use Commands ... – LPL Aug 01 '12 at 19:06