Bonjour,

je développe un petit composant qui est grosso modo une TextBox wrappée dans une Border et accolée à une Image;
la Border et l'Image changeant en fonction de l'état de validation du contenu de la TextBox.

Cependant je voudrais que l'utilisateur puisse passer en propriété du composant un objet Binding sur lequel se basera la validation.
Autant passer un objet de type string ne pose aucun problème autant un objet Binding semble être interprété par WPF et ne pas être transmis comme un vrai objet au composant.

Voilà le code du composant :
Le XAML :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<UserControl
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="Test.ValidationTextBox"
    x:Name="Self"
 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 
    xmlns:Test="clr-namespace:Test"
>
    <UserControl.Resources>
        <Test:IsNullOrEmptyTester x:Key="IsNullOrEmptyTester" />
    </UserControl.Resources>
 
    <StackPanel Orientation="Horizontal">
        <Border Name="TextBoxBorder" BorderThickness="1" Width="{Binding ElementName=TextBox,Path=Width}" HorizontalAlignment="Left">
            <Border.Style>
                <Style TargetType="Border">
                    <Style.Triggers>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding ElementName=TextBox,Path=(Validation.HasError)}" Value="True" />
                                <Condition Binding="{Binding ElementName=TextBox,Path=Text,Converter={StaticResource IsNullOrEmptyTester}}" Value="False" />
                            </MultiDataTrigger.Conditions>
                            <Setter Property="BorderBrush" Value="Red" />
                        </MultiDataTrigger>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding ElementName=TextBox,Path=(Validation.HasError)}" Value="False" />
                                <Condition Binding="{Binding ElementName=TextBox,Path=Text,Converter={StaticResource IsNullOrEmptyTester}}" Value="False" />
                            </MultiDataTrigger.Conditions>
                            <Setter Property="BorderBrush" Value="Green" />
                        </MultiDataTrigger>
                    </Style.Triggers>
                </Style>
            </Border.Style>
            <TextBox
                    Name="TextBox"
                    Width="100"
                    MaxLength="10"
                    Validation.ErrorTemplate="{x:Null}"
                >
 
                <TextBox.Style>
 
                    <Style TargetType="TextBox">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.HasError)}" Value="True">
                                <Setter Property="ToolTip"
                                            Value="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.Errors)[0].ErrorContent}"
                                    />
                            </DataTrigger>
                            <DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.HasError)}" Value="False">
                                <Setter Property="ToolTip" Value="{Binding ElementName=Self,Path=DefaultToolTipText}" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
 
                </TextBox.Style>
 
            </TextBox>
        </Border>
 
        <Image>
            <Image.Style>
                <Style TargetType="Image">
                    <Style.Triggers>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding ElementName=TextBox,Path=(Validation.HasError)}" Value="True" />
                                <Condition Binding="{Binding ElementName=TextBox,Path=Text,Converter={StaticResource IsNullOrEmptyTester}}" Value="False" />
                            </MultiDataTrigger.Conditions>
                            <Setter Property="Source" Value="/media/images/error.png" />
                        </MultiDataTrigger>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding ElementName=TextBox,Path=(Validation.HasError)}" Value="False" />
                                <Condition Binding="{Binding ElementName=TextBox,Path=Text,Converter={StaticResource IsNullOrEmptyTester}}" Value="False" />
                            </MultiDataTrigger.Conditions>
                            <Setter Property="Source" Value="/media/images/noError.png" />
                        </MultiDataTrigger>
                    </Style.Triggers>
                </Style>
            </Image.Style>
        </Image>
    </StackPanel>
</UserControl>
Le code-behind :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
 
namespace Test
{
    /// <summary>
    /// Interaction logic for ValidationTextBox.xaml
    /// </summary>
    public partial class ValidationTextBox : UserControl
    {
        public static readonly DependencyProperty BindingProperty
            = DependencyProperty.Register("Binding", typeof(Binding), typeof(ValidationTextBox));
 
        public Binding Binding
        {
            get
            {
                return (Binding)this.GetValue(BindingProperty);
            }
            set
            {
                this.SetValue(BindingProperty, value);
                this.TextBox.SetBinding(TextBox.TextProperty, value);
            }
        }
 
        public static readonly DependencyProperty DefaultToolTipTextProperty
            = DependencyProperty.Register("DefaultToolTipText", typeof(string), typeof(ValidationTextBox));
 
        public string DefaultToolTipText
        {
            get
            {
                return (string)this.GetValue(DefaultToolTipTextProperty);
            }
            set
            {
                this.SetValue(DefaultToolTipTextProperty, value);
            }
        }
 
        public ValidationTextBox()
        {
            InitializeComponent();
        }
    }
}
Et une tentative d'utilisation :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
<test:ValidationTextBox Grid.Row="3" Grid.Column="1" DefaultToolTipText="Test" Binding="{DynamicResource DateBinding}">
	<test:ValidationTextBox.Binding>
		<Binding Path="Date" UpdateSourceTrigger="PropertyChanged">
			<Binding.ValidationRules>
				<test:ISODateFormatRule />
			</Binding.ValidationRules>
			<Binding.Converter>
				<test:DateTimeConverter />
			</Binding.Converter>
		</Binding>
	</test:ValidationTextBox.Binding>
</test:ValidationTextBox>
Le composant se comporte bien quand la TextBox est vide : il n'y a ni bordure ni image, mais s'il y a des données, quelles qu'elles soient, la Border est verte et l'Image celle de la validation passée.
Le débuggage avec VS2008 montre bien que le Binding n'est pas utilisé : ni le IValueConverter ni la ValidationRule ne sont invoqués.


1) Quelle est la source du problème ?
2) Comment y remédier et transmettre tel quel le Binding ?



Merci d'avance.