tags:

views:

26

answers:

2

Is there a way to template Binding.Converter and Binding.ValidationRules within a style?

Eg: I have the following textbox:

            <TextBox x:Name="DepartTime" Height="23" HorizontalContentAlignment="Left" HorizontalAlignment="Left" 
                Margin="3" Width="140" 
                Style="{DynamicResource TimeOfDayTextBox}">
                <TextBox.Text>
                    <!--  Textbox notifies changes when Text is changed, and not focus. -->
                    <Binding Path="FlightDepartTime" StringFormat="{}{0:hh:mm tt}" >
                        <Binding.Converter>
                            <convert:TimeOfDayConverter />
                        </Binding.Converter>
                        <Binding.ValidationRules>
                            <!--  Validation rule set to run when binding target is updated. -->
                            <validate:ValidateTimeOfDay ValidatesOnTargetUpdated="True" />
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>

.. I can't figure out how to incorporate the Converter and the Validation rule into my TimeOfDayTextBox style.

Many Thanks.

+1  A: 

A style can contain only a common set of property which can be applied to multiple controls. In your case, the converter and the validation rule aren't applied to the textbox, but to the content of the binding, so they are specific for a single element and cannot be used in a style.

Maurizio Reginelli
Ah! Of course! Thanks for pointing that out Maurizio :)
Steve Bolton
+1  A: 

Unfortunately, no. The style could only set the Text property itself to a Binding. It cannot set attributes of the binding. Also, since Binding is not a DependencyObject there is no way to style a binding.

One option you have to make your code more concise is to use a custom MarkupExtension that creates the binding you want:

public class TimeOfDayBinding
    : MarkupExtension
{
    public PropertyPath Path { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var binding = new Binding()
        {
            Path = Path,
            Converter = new TimeOfDayConverter(),
        };
        binding.ValidationRules.Add(new ValidateTimeOfDay()
        {
            ValidatesOnTargetUpdated = true,
        });
        return binding.ProvideValue(serviceProvider);
    }
}

Given your control names, you may also want to use a time picker control instead of a TextBox. Check out this question: What is currently the best, free time picker for WPF?

Quartermeister
Thanks Quartermeister. The time picker is exactly what I needed. Also, thanks for the markup extension option. That's something else I've learned today. Cheers.
Steve Bolton