Laden...

DependencyProperty Validation - Wert aus Button an Textbox übergeben

Erstellt von trib vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.797 Views
T
trib Themenstarter:in
708 Beiträge seit 2008
vor 10 Jahren
DependencyProperty Validation - Wert aus Button an Textbox übergeben

Guten Morgen,

eine Textbox soll ihren Wert aus einem Button bekommen.
Dazu habe ich dem Button die Textbox übergeben:

<TextBox x:Name="PathTextBox" Text="{Binding FilePath, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" />
<my:FileDialog x:Name="PathBrowserDialog" Text="{Binding Text, ElementName=PathTextBox, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, UpdateSourceTrigger=PropertyChanged}" />

Im Code des Buttons gehe ich wie folgt vor:

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(FileDialog),
                                        new FrameworkPropertyMetadata("",
                                                                      FrameworkPropertyMetadataOptions
                                                                          .BindsTwoWayByDefault, TextValueChanged));

        private static void TextValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            var sender = o as FileDialog;
            if (e.NewValue != null)
                if (sender != null) 
                    sender.Text = e.NewValue.ToString();
        }

        public string Text
        {
            get { return (string) GetValue(TextProperty); }
            set
            {
                SetValue(TextProperty, value);
            }
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            Text = GetPathFromDialog();            
        }

Nun klicke ich den Button, wähle einen Pfad aus und dieser wird prompt in der Textbox angezeigt.
Allerdings passiert im CodeBehind nichts und der Pfad wird nicht validiert.

Wie kann ich den Button dazu bringen, dass er den Wert der Textbox an das Binding übergibt?

Dank euch für jede Idee,
trib

R
212 Beiträge seit 2012
vor 10 Jahren

Du musst das in "FrameworkPropertyMetadataOptions" machen 😃.
GEt und set werden bei Bindings nicht ausgeführt sonder nur der PropertyChangedCallback der DependencyProperty was in deinem fall "FrameworkPropertyMetadataOptions" ist.

T
trib Themenstarter:in
708 Beiträge seit 2008
vor 10 Jahren

Du musst das in "FrameworkPropertyMetadataOptions" machen 😃.
GEt und set werden bei Bindings nicht ausgeführt sonder nur der PropertyChangedCallback der DependencyProperty was in deinem fall "FrameworkPropertyMetadataOptions" ist.

Hallo Robin0,

danke für Deinen Tipp. Leider tut sich weiterhin noch nichts. Wenn ich Dich korrekt verstanden habe, dann müsste es doch so funktionieren:

        private static readonly FrameworkPropertyMetadata PropertyMetadata =
                                        new FrameworkPropertyMetadata("",
                                         FrameworkPropertyMetadataOptions.BindsTwoWayByDefault |
                                        FrameworkPropertyMetadataOptions.Journal, 
                                        TextValueChanged,
                                        TextValueCoerceValue,
                                        false, UpdateSourceTrigger.PropertyChanged);

        public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(BrowserDialog),
        PropertyMetadata, TextValueValidate);
        private static void TextValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            var sender = o as BrowserDialog;
            if (e.NewValue != null)
                if (sender != null) 
                    sender.Text = e.NewValue.ToString();
        }

        private static object TextValueCoerceValue(DependencyObject dependencyObj, object val)
        {
            return val;
        }

        private static bool TextValueValidate(object val)
        {
            //Custom validation block which takes in the value of DP
            //Returns true / false based on success / failure of the validation
            return true;
        }

Die Methode TextValueValidate wird auch ausgeführt, sobald ich einen Pfad auswähle.
Meine Vermutung ist aber, dass ich ja im Binding des Buttons den Text der Textbox drin habe und das schlichtergreifend nicht durchgereicht wird. Muss ich dort vielleicht noch etwas basteln?

R
212 Beiträge seit 2012
vor 10 Jahren

private void OnTextValueChangedChanged(String oldValue, String newValue)
        {
                   //Hier bist du in der aktuellen instanz
                   Deinetextbox.Text = newValue
        }

        private static void TextValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
                  ((BrowserDialog)d). OnTextValueChangedChanged((String)e.OldValue, (String)e.NewValue);
        }

T
trib Themenstarter:in
708 Beiträge seit 2008
vor 10 Jahren

Hmm, ich glaube wir reden aneinander vorbei.
Jede Änderung an der Textbox kommt am Button an. Dieser weiß immer korrekt welcher Pfad in der Textbox steht.
Klicke ich auf den Button um einen neuen Pfad auszuwählen, fülle ich den "Text" des Buttons. Dieser Button hat in dem Databinding den Text der Textbox hinterlegt.
Nun wird auch korrekt der neue Pfad angezeigt. Klappt perfekt in beide Richtungen.
Aber:
Das Databinding hinter der Textbox bekommt von der Änderung nichts mit und speichert weiterhin den alten Pfad. Auch wenn schon der neue angezeigt wird.

Daher tippe ich darauf, dass ich entweder im Button ebenfalls auf das Databinding der Textbox verweisen muss (dann klappt die Anzeige aber nicht mehr) oder im Databinding des Buttons mitgeben muss, dass eine Validierung der Textbox ausgeführt werde muss.

Mein Ziel ist eigentlich nur ein Control (Button), das farblich anzeigt ob eine Datei oder ein Pfad exisitiert oder zugreifbar ist. Klickt man drauf, so kommt ein Dialog zum auswählen des Pfades oder der Datei. Dieser soll an eine Textbox gebunden werden, die die Daten enthält.

Gruß
trib

[EDIT:]
Endlich habe ich es!
Es war wirklich das Problem, dass ohne ein explizites Validate der Textbox, das Databinding nicht aktualisiert wird. Das muss ich nun in der TextBox manuell nochmal mitgeben:

<TextBox x:Name="PathTextBox" Text="{Binding DebugPath, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, UpdateSourceTrigger=PropertyChanged}" />

Finde ich jetzt etwas unschön, da meine Idee eigentlich war keine Änderungen an der Textbox vornehmen zu müssen, sondern nur das zusätzliche einbinden des Buttons.
Hauptsache es läuft erstmal!

UpdateSourceTrigger=PropertyChanged

heißt das Zauberwort! Das dann die Daten-Klasse natürlich von INotifyPropertyChanged ableitet, ist selbstverständlich, denke ich.