Laden...

Trigger auf eine Zelle eines Datenvektors

Erstellt von BJA-CH vor 6 Jahren Letzter Beitrag vor 6 Jahren 1.384 Views
B
BJA-CH Themenstarter:in
59 Beiträge seit 2017
vor 6 Jahren
Trigger auf eine Zelle eines Datenvektors

Hoi zäme
In einem UserControl bekomme ich über einem DependencyProperty einen Vektor int[] zugeordnet.


        public static readonly DependencyProperty XLayerProperty =
            DependencyProperty.Register("XLayer", typeof(int?[]), typeof(DynamischMemoryBoard),
                new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                    new PropertyChangedCallback(OnXLayerPropertyChanged)));

        public int?[] XLayer
        {
            get { return (int?[])GetValue(XLayerProperty); }
            set { SetValue(XLayerProperty, value); }
        }
         .......
         .......

Da dieser Vektor einen variable Länge hat, erstelle ich das GUI ebenfalls dynamisch. Dabei wird jede Zelle des Vektors einzeln in einem TextBox dargestellt. Dabei sollen die Felder farblich unterschiedlich dargestellt werden, falls sie kleiner oder grösser o sind.
Dazu baue ich die einzelnen TextBox in einer Schlaufe aufgebaut:


            for (int i = 0; i < this.YLayerAnzahl; i++)
            {
                TextBox tb = new TextBox();
                tb.Name = "YLayer" + i;
                tb.Margin = new Thickness(2.0);

                DataTrigger triggerYPlus = new DataTrigger();
                triggerYPlus.Binding = new Binding("YLayer[" + i + "]") { Source = this, Converter = new AssociativMemorySample.GreaterThenNullConverter() };
                triggerYPlus.Value = true;
                triggerYPlus.Setters.Add(new Setter(TextBox.BackgroundProperty, Brushes.LightGreen));
                Style styleY = new Style();
                styleY.Triggers.Add(triggerYPlus);
                DataTrigger triggerYMinus = new DataTrigger();
                triggerYMinus.Binding = new Binding("YLayer[" + i + "]") { Source = this, Converter = new AssociativMemorySample.LessThenNullConverter() };
                triggerYMinus.Value = true;
                triggerYMinus.Setters.Add(new Setter(TextBox.BackgroundProperty, Brushes.LightPink));
                styleY.Triggers.Add(triggerYMinus);
                tb.Style = styleY;

                Grid.SetRow(tb, 0);
                Grid.SetColumn(tb, 3 + i);
                Binding bind = new Binding("YLayer[" + i + "]") { Source = this, Mode = BindingMode.TwoWay };
                bind.Converter = new AssociativMemorySample.IntToStringVorConverter();
                tb.SetBinding(TextBox.TextProperty, bind);
                this.gridBoard.Children.Add(tb);
            }

Wird der Vektor dem UserControl übergeben funktioniert der Trigger, die Farbe des TextBox-Elementes wird geändert. Wird nun aber ein Wert in einer der TextBoxen verändert, so bekommt der Trigger keinen Anstoss, weil das DependencyProperty offenbar die Veränderung nicht erkennt.

Weiss jemand, wie ich mich behelfen kann? Wie kann ich erzwingen, dass bei einer Veränderung der Variable an der Stelle i (Layer_=1) den Trigger auslöst?

1.040 Beiträge seit 2007
vor 6 Jahren

Sieht abgefahren aus, was du da machst...

Läufst du in den IntToStringVorConverter, wenn du den Wert in der TextBox änderst?

Ich denke allerdings, dass du nicht TwoWay an YLayer[n] binden kannst.

B
BJA-CH Themenstarter:in
59 Beiträge seit 2017
vor 6 Jahren

Genau, dieser Converter schreibt die Zahl der Zelle in einen darstellbaren Wert um. Diese Bindung funktioniert richtig.


        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
                return "";
            int zahl = (int)value;
            string wert= String.Format("{0:+0;-0;0}", zahl);
            if (zahl == 0)
                wert = "";
            return wert;
        }

Das Ergebnis siehst du im Anhang. Das Programm ist ein Modell für einen Assoziativ-Speicher....

B
BJA-CH Themenstarter:in
59 Beiträge seit 2017
vor 6 Jahren

Habe eine elegantere Lösung als diesen Trigger gefunden und der funktioniert sogar. Anstelle des Triggers binde ich den BackColor auf den Inhalt der TextBox.


            for (int i = 0; i < this.YLayerAnzahl; i++)
            {
                TextBox tb = new TextBox();
                tb.Name = "YLayer" + i;
                tb.Margin = new Thickness(2.0);

                Binding bindYB = new Binding("Text") { Source = tb, Mode = BindingMode.OneWay };
                bindYB.Converter = new AssociativMemorySample.StringToBrushConverter();
                tb.SetBinding(ToggleButton.BackgroundProperty, bindYB);

                Grid.SetRow(tb, 0);
                Grid.SetColumn(tb, 3 + i);
                Binding bind = new Binding("YLayer[" + i + "]") { Source = this, Mode = BindingMode.TwoWay };
                bind.Converter = new AssociativMemorySample.IntToStringVorConverter();
                tb.SetBinding(TextBox.TextProperty, bind);
                this.gridBoard.Children.Add(tb);
            }

Danke und Gruss!

5.658 Beiträge seit 2006
vor 6 Jahren

Hi BJA-CH,

wenn du statt eines int[] eine ObservableCollection<int> verwendest, dann werden auch die Werte automatisch aktualisiert. Siehe dazu [Artikel] MVVM und DataBinding, Abschnitt 2.4 ViewModel-Auflistungen.

Weeks of programming can save you hours of planning