p0lar_bear
p0lar_bear

Reputation: 2275

DataBinding the Enabled property of a control to a string field

I've got a C#.NET project using strongly-typed DataSets and TableAdapters and such, and I have UserControls dedicated to handling the editing of records via BindingSource.

I'm wondering if it's at all possible for me to bind the Enabled property of a TextBox to dynamically enable or disable it based on the contents of another [string] field in the current record of a BindingSource, e.g. if the field contains a word or is a certain value, or if I should resort to just good old event handling?

Some code to (hopefully) illustrate what I'm attempting:

//An instance of a custom StronglyTypedDataSet "ds" already exists
//with a table called "table" defined in it with at least one record.
BindingSource bs = new BindingSource(ds, "table");
bs.Position = 0;

//A TextBox txtField2 exists on the form.
//txtField2.Text is bound to the value of ds.table.Field2, and I want it to enable
//itself if the contents of ds.table.Field1 meet certain criteria.
txtField2.DataBindings.Add("Text", bs, "Field2");
txtField2.DataBindings.Add("Enabled", bs, "Field1", true, DataSourceUpdateMode.Never,
    false, "WHAT GOES HERE?");

Upvotes: 2

Views: 604

Answers (1)

Peter Duniho
Peter Duniho

Reputation: 70691

Absolutely. While I find a lot of the specifics incredibly complicated much of the time, one of the beautiful things about WPF is that you can pretty much bind anything to anything else, as long as you have a clear idea of what that binding would mean.

In your case, it seems you want to take as input a string value (i.e. the value of the TextBox.Text property), and bind it to a bool property based on some known criteria.

Here is an example of how you might do that. First, you need to write the shim that converts from the string to the bool. For example:

class StringToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string text = value as string;

        if (text != null)
        {
            string matchText = (string)parameter;

            return text == matchText;
        }

        return Binding.DoNothing;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Note that here, I allow the binding to pass a parameter, and do a simple equality comparison. But you are free to do anything here you want, as long as you take the string input and return a bool value. You can hard-code the entire logic in the converter itself, or you can come up with a way to represent your criteria as a parameter and pass it to the converter that way (or of course make use of some state elsewhere in the program, but IMHO it makes more sense to pass the criteria as a parameter if you want to customize it).

With the converter done, it's trivial to then configure the binding so that it uses that. For example:

<Window x:Class="TestSO28075399ConvertStringToBoolean.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestSO28075399ConvertStringToBoolean"
        Title="MainWindow" Height="350" Width="525">
  <StackPanel>
    <StackPanel.Resources>
      <local:StringToBooleanConverter x:Key="stringToBooleanConverter1" />
    </StackPanel.Resources>
    <Border BorderBrush="Black" BorderThickness="1">
      <TextBox x:Name="textBox1" />
    </Border>
    <Button Content="Click me!" Width="100" HorizontalAlignment="Left"
            IsEnabled="{Binding ElementName=textBox1,
                                Path=Text,
                                Converter={StaticResource stringToBooleanConverter1},
                                ConverterParameter=Hello}" />
  </StackPanel>
</Window>

When declaring it as a resource, the converter object can be anywhere in the resource chain. It doesn't have to be in the StackPanel itself.

With the above code, the "Click me!" button will be enabled only if the user types exactly the text "Hello" into the TextBox.

If this has to be set up dynamically in a way that isn't supported via XAML, you can of course do all of the above programmatically as well. Just translate the relevant XAML to its equivalent in C# code.

Upvotes: 1

Related Questions