Bonjour, dans une solution WPF j'ai un userControl qui contient une TextBox et un label, un Model qui implémente mes variables et une vue qui montre le résultat. Comme suit :

User control :
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
<UserControl
    x:Class="ControlsLibrary.CtrTextBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:ControlsLibrary"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    d:DesignHeight="50"
    d:DesignWidth="400"
    mc:Ignorable="d">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/Dictionaries;component/Styles/ControlsStyle.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid HorizontalAlignment="Right" DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:CtrTextBox}}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Label Content="{Binding TextBoxEntitled}" />
        <TextBox
            x:Name="TB"
            Grid.Column="1"
            Width="{Binding TextBoxWidth}"
            HorizontalAlignment="Right"
            VerticalContentAlignment="Center"
            CharacterCasing="{Binding TextBoxCharacterCasing}"
            GotFocus="TB_GotFocus"
            IsEnabled="{Binding TextBoxEnabledState}"
            MaxLength="{Binding TextBoxMaxLength}"
            MouseEnter="TB_MouseEnter"
            PreviewKeyDown="TB_PreviewKeyDown"
            Style="{StaticResource TextBoxStyle}"
            Text="{Binding TextBoxText}"
            TextWrapping="Wrap" />
    </Grid>
</UserControl>
et son code :

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
87
88
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
 
namespace ControlsLibrary
{
    /// <summary>
    /// Logique d'interaction pour CtrTextBox.xaml
    /// </summary>
    public partial class CtrTextBox : UserControl
    {
        public CtrTextBox()
        {
            InitializeComponent();
        }
        public TextBox InternalTextBox { get => TB; }
        public static readonly DependencyProperty TextBoxTextProperty =
          DependencyProperty.Register("TextBoxText", typeof(string), typeof(CtrTextBox), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
        public string TextBoxText
        {
            get => (string)GetValue(TextBoxTextProperty); set => SetValue(TextBoxTextProperty, value);
        }
        public static readonly DependencyProperty TextBoxEntitledProperty =
            DependencyProperty.Register("TextBoxEntitled", typeof(string), typeof(CtrTextBox), new PropertyMetadata(null));
        public string TextBoxEntitled
        {
            get => (string)GetValue(TextBoxEntitledProperty); set => SetValue(TextBoxEntitledProperty, value);
        }
        public static readonly DependencyProperty TextBoxEnabledStateProperty =
            DependencyProperty.Register("TextBoxEnabledState", typeof(bool), typeof(CtrTextBox), new PropertyMetadata(true));
        public bool TextBoxEnabledState
        {
            get => (bool)GetValue(TextBoxEnabledStateProperty);
            set => SetValue(TextBoxEnabledStateProperty, value);
        }
        public static readonly DependencyProperty TextBoxWidthProperty =
            DependencyProperty.Register("TextBoxWidth", typeof(double), typeof(CtrTextBox), new PropertyMetadata(new double()));
        public double TextBoxWidth
        {
            get => (double)GetValue(TextBoxWidthProperty); set => SetValue(TextBoxWidthProperty, value);
        }
        public static readonly DependencyProperty TextBoxCharacterChasingProperty =
            DependencyProperty.Register("TextBoxCharacterChasing", typeof(CharacterCasing), typeof(CtrTextBox), new PropertyMetadata(CharacterCasing.Normal));
        public CharacterCasing TextBoxCharacterCasing
        {
            get => (CharacterCasing)GetValue(TextBoxCharacterChasingProperty);
            set => SetValue(TextBoxCharacterChasingProperty, value);
        }
        public static readonly DependencyProperty TextBoxMaxLengthProperty =
            DependencyProperty.Register("TextBoxMaxLength", typeof(int), typeof(CtrTextBox), new PropertyMetadata(new int()));
        public int TextBoxMaxLength
        {
            get => (int)GetValue(TextBoxMaxLengthProperty); set => SetValue(TextBoxMaxLengthProperty, value);
        }
 
        private void TB_GotFocus(object sender, RoutedEventArgs e)
        {
            ((TextBox)sender).SelectAll();
            e.Handled = true;
        }
 
        private void TB_MouseEnter(object sender, MouseEventArgs e)
        {
            if (!string.IsNullOrEmpty(((TextBox)sender).Text))
            {
                ((TextBox)sender).SelectAll();
                e.Handled = true;
            }
        }
 
        private void TB_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            TextBox currentTxtBox = sender as TextBox;
            if ((e.Key == Key.OemComma || e.Key == Key.OemPeriod || e.Key == Key.Decimal) && (currentTxtBox.Text.IndexOf(",") > -1 || currentTxtBox.Text.Length == 0))
            {
                e.Handled = true;
                return;
            }
            if (e.Key == Key.Decimal)
            {
                e.Handled = true;
                int LastLocation = currentTxtBox.SelectionStart;
                currentTxtBox.Text = currentTxtBox.Text.Insert(LastLocation, ",");
                currentTxtBox.SelectionStart = LastLocation + 1;
            }
        }
    }
}
le Model :

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
using System.ComponentModel;
using System.Windows;
 
namespace Email_Configuration.Models
{
    public class TestModel : INotifyPropertyChanged
    {
        private string _testString;
        public string TestString
        {
            get => _testString;
            set
            {
                _testString = value;
                OnPropertyChanged(nameof(TestString));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            MessageBox.Show($"Property changed : {propertyName}");
        }
    }
}
avec le messageBox qui va servir a tester le changement de ma variable

et la vue :

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
<Page
    x:Class="Email_Configuration.Views.TestPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="clr-namespace:ControlsLibrary;assembly=ControlsLibrary"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:Email_Configuration.Views"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:model="clr-namespace:Email_Configuration.Models"
    Title="TestPage"
    d:DataContext="{d:DesignInstance Type=model:TestModel}"
    d:DesignHeight="450"
    d:DesignWidth="800"
    mc:Ignorable="d">
 
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <controls:CtrTextBox
            x:Name="TestUC"
            TextBoxText="{Binding TestString, UpdateSourceTrigger=PropertyChanged}"
            TextBoxWidth="100" />
    </Grid>
</Page>
et son code :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
public partial class TestPage : Page
{
    private TestModel _testModel = new TestModel();
    public TestPage()
    {
        InitializeComponent();
        DataContext = _testModel;
    }
}
Je n'ai aucune erreur de compilation mais le comportement de la TextBox est bizzare , en effet le messageBox qui affiche le changement de la variable ne s'affiche que lorsque je quitte la zone de saisie de la textbox alors que UpdateSourceTrigger est défini sur OnPropertyChanged...

Je ne vois pas trop se qui cloche. Merci de votre aide