WPF binding to another property's binding in a style

Jordan0Day picture Jordan0Day · Nov 25, 2009 · Viewed 18.3k times · Source

I'm not sure the best way to ask this question (sorry for the ambiguous question title), but essentially I'd like to set the MaxLength property on a TextBox using a value converter that is passed in a property from the data context, and the property on the passed-in property as the converter parameter. I'd like to do all this in a style, as opposed to on a control-by-control basis. Here's an example of doing this in a non-styled manner:

<TextBox Text="{Binding MyPropertyName.TheirPropertyName}" MaxLength="{Binding MyPropertyName, Converter={StatocRespirceMyCoolConverter}, ConverterParameter=TheirPropertyName}" />

(In case you're wondering, TheirPropertyName represents a property on the type of MyPropertyName that has an attribute like [StringMaxLength(15)], which I'd be able to get to and return inside the value converter.) Additionally, is there any way to pass in the type of MyPropertyName as opposed to the instance? I only need the type to do the StringMaxLength attribute lookup.

Anyway, how could I go about doing something like this in a style? I've gotten as far as:

<Setter Property="MaxLength">
    <Setter.Value>
        <Binding Converter="{StaticResource textFieldMaxLengthConverter}" />
    </Setter.Value>
</Setter>

But that passes the overall datacontext in to the value converter, as opposed to the MyPropertyName object, and I really have no clue if I can have it parse the MyPropertyName.TheirPropertyName part of the binding to pass TheirPropertyName in on the ConverterParameter attribute of the binding.

Any guidance would be really appreciated!

Answer

Jordan0Day picture Jordan0Day · Nov 25, 2009

Ok, after some more digging, I've figured this out to my satisfaction. I'm binding to RelativeSource Self and then parsing the binding expression on the Text property (since this is a TextFieldMaxLength converter, I am presuming I'm working against a TextBox.

The styling up in the resource dictionary:

<Style TargetType="TextBox"> 
  <Setter Property="MaxLength">
    <Setter.Value>
      <Binding Converter="{StaticResource textFieldMaxLengthConverter}" RelativeSource="{RelativeSource Self}" />
    </Setter.Value>
  </Setter>
</Style>

The usage (basically showing nothing special needs to be done since it's all in the style):

<TextBox Text="{Binding MyPropertyName.TheirPropertyName}" />

The Convert Method for the textFieldMaxLengthConverter:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
  Control control = value as Control;
  BindingExpression be = control.GetBindingExpression(TextBox.TextProperty);
  if (be != null)
  {
    string boundPropertyName = be.ParentBinding.Path.Path;
    // .. boundPropertyName here is MyPropertyName.TheirPropertyname, do some parsing and return a value based on that
  }
}

(Obviously my actual implementation is a bit more complex/handles unexpected input/uses reflection as per my original question's statement).

Anyway, thought I would post this solution in case anyone else tries to do something similar, or if there might be a better way to do this than I am using.