wpfxamldata-bindingstylesvalueconverter

WPF binding to another property's binding in a style


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!


Solution

  • 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.