Laden...

XAML Binding Path mit Index aktualisieren

Erstellt von Flachmann vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.258 Views
F
Flachmann Themenstarter:in
4 Beiträge seit 2018
vor 5 Jahren
XAML Binding Path mit Index aktualisieren

Ich habe mal wieder eine Frage an die Gurus, da ich einfach nicht weiter weiß. X(

Ich habe in meiner XAML mehrere Button, deren Eigenschaften an eine IList<Digit> gebinden sind. Eine List habe ich verwendet, weil die einfach zu indizieren ist, alle Button ansonsten gleichartig und gut anzusprechen sind.

<Button x:Name="Digit2" Text="{Binding Path=Digits[2].Text}" CommandParameter="2" Clicked="DigitClicked" 
                        BorderColor="{Binding Path=Digits[2].BorderColor}" />
public class Digit
{
	public char Text { get; set; }
	public bool IsMarked { get; set; }
	public Color BorderColor => IsMarked ? Color.Yellow : Color.Transparent;
        
	public Digit(char text, bool isMarked)
	{
		Text = text;
		IsMarked = isMarked;
	}
}

Und in der ContenPage selbst:

public IList<Digit> Digits { get; set; } = new List<Digit>();
private int _activeDigit = 0;

Im Constructor:

Digits.Add(new Digit("2", false)); 

_activeDigit enthält die Nummer des Button, der aktiv/markiert ist.
Ich will nun eine Aktualisierung des Button erreichen, so dass z.B. BorderColor geändert wird, wenn er markiert wird. Dieser Clicked-Event wird aufgerufen und die Werte gesetzt.

private void DigitClicked(object sender, EventArgs e)
{
	Digits[_activeDigit].IsMarked = false;
	OnPropertyChanged("Digit" + _activeDigit);  // alte Markierung aufheben
	
	_activeDigit = int.Parse((sender as Button).CommandParameter as string);
	Digits[_activeDigit].IsMarked = true;

	OnPropertyChanged("Digit" + _activeDigit);  // neue Markierung setzen
}

Leider feuert der OnPropertyChanged()-Event hier nicht und der zugehörige Schalter wird nicht aktualisiert.

Wahrscheinlich denke ich irgendwie hier falsch. Vielleicht geht auch alles viel einfacher. Dieses Data-Binding macht mich echt noch fertig. 😉

Ich hatte zuerst auch versucht den logischeren Fall umzusetzen, also Digit als INotifyPropertyChanged zu implementieren und das OnPropertyChanged() beim Setzen von IsMarked aufzurufen. Das funktionierte aber auch nicht, weil ich eigentlich nicht weiß, welchen richtigen Parameter ich für den OnPropertyChanged() mitgeben muss.

Gruß,


/
/lachmann

F
Flachmann Themenstarter:in
4 Beiträge seit 2018
vor 5 Jahren

Ok, hab's selbst raus gefunden, auch wenn ich es mal wieder absolut nicht verstehe. Wie geschrieben: dieses Binding macht mich noch fertig! 🙁

Ich habe es wieder "klassisch" implementiert und die OnPropertyChanged() in die Properties übernommen. So sollte es ja auch sein und ergibt einen saubereren Code:

private void DigitClicked(object sender, EventArgs e)
{
	Digits[ActiveDigit].IsMarked = false;

	ActiveDigit = int.Parse((sender as Button).CommandParameter as string);

	Digits[ActiveDigit].IsMarked = true;
}

public class Digit : INotifyPropertyChanged
{
	private bool _isMarked;
        
	public bool IsMarked
	{
		get => _isMarked; 
		set
		{
			if (_isMarked == value) return;
			_isMarked = value;
	
			OnPropertyChanged("BorderColor");
		}
	}
	
	public Color BorderColor => IsMarked ? Color.Yellow : Color.Transparent;
	// {...]
}

Warum ich aber OnPropertyChanged("BorderColor") eingeben kann und dann nur dieser eine, gebundene Button geändert wird, verstehe ich irgendwie nicht; sitze wohl mal wieder auf dem Schlauch.

Gruß,


/
/lachmann

5.657 Beiträge seit 2006
vor 5 Jahren

Hi Flachmann,

OnPropertyChanged informiert nur über die Änderung des Wertes einer Eigenschaft, und übergibt nur den Namen der Eigenschaft. Daher kannst du die Methode auch an einer beliebigen Stelle mit einem beliebigen Eigenschaftsnamen aufrufen.

Wenn durch die Änderung einer Eigenschaft auch andere Eigenschaften ihre Werte ändern, dann solltest du OnPropertyChanged auch mehrmals aufrufen, jeweils einmal für jede geänderte Eigenschaft. In deinem Fall also:

 
    public bool IsMarked
    {
        get => _isMarked;
        set
        {
            if (_isMarked == value) 
                return;
            _isMarked = value;
            OnPropertyChanged("IsMarked");
            OnPropertyChanged("BorderColor");
        }
    }

Weeks of programming can save you hours of planning