I have a little project with a simulator. In the end the winner should stand in the label. The backcode works fine but the binding doesn't refresh after I set "Winner" to the new string. I let somethings out because they aren't important for the problem.
Here's my xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Risiko.MainPage"
xmlns:local="clr-namespace:Risiko"
x:DataType="local:MainViewModel">
<StackLayout>
<Frame BackgroundColor="Red" Margin="10,10,5,10" CornerRadius="5">
<StackLayout>
<Label Text="Angreifer:" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
<StackLayout>
<Entry Text="{Binding Enemie}" HorizontalOptions="FillAndExpand" Keyboard="Numeric" TextColor="White"/>
<Label Text="Soldaten" HorizontalOptions="EndAndExpand" TextColor="White"/>
</StackLayout>
</StackLayout>
</Frame>
<Frame BackgroundColor="Blue" Margin="10,5,10,10" CornerRadius="5">
<StackLayout>
<Label Text="Verteildiger:i" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
<StackLayout>
<Entry Text="{Binding Defender}" HorizontalOptions="FillAndExpand" Keyboard="Numeric" TextColor="White"/>
<Label Text="Soldaten" HorizontalOptions="EndAndExpand" TextColor="White"/>
</StackLayout>
</StackLayout>
</Frame>
<Button Text="Start" Command="{Binding Start}" Background="green"/>
<Frame BackgroundColor="Gray" Margin="10,5,10,10" CornerRadius="5">
<Label Text="{Binding Winner, Mode=TwoWay}" HorizontalOptions="FillAndExpand" TextColor="White"/>
</Frame>
</StackLayout>
</ContentPage>
Here's my Viewmodel:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using Xamarin.Forms;
namespace Risiko
{
public class MainViewModel
{
private string _defender;
private string _winner;
private string _enemie;
private int[] enemieArray = new int[4];
private int[] defenderArray = new int[3];
Random random = new Random();
private int max;
private int max2;
public Command Start { get; }
public string Defender
{
get => _defender;
set => SetProperty(ref _defender, value);
}
public string Enemie
{
get => _enemie;
set => SetProperty(ref _enemie, value);
}
public string Winner
{
get => _winner;
set => SetProperty(ref _winner, value);
}
public MainViewModel()
{
Start = new Command(OnStart);
}
private void OnStart()
{
if(defenderArray[0] <= 0)
{
Winner = "Gewonnen hat der Angreifer mit nur noch " enemieArray[0] " übrigen Truppen.";
}
else
{
Winner = "Gewonnen hat der Verteildiger mit nur noch " defenderArray[0] " übrigen Truppen.";
}
}
#region INotifyPropertyChanged
protected bool SetProperty<T>(ref T backingStore, T value,
[CallerMemberName] string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
And my backcode cs
namespace Risiko
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new MainViewModel();
}
}
}
CodePudding user response:
the binding mechanism checks to see if the class assigned as the BindingContext
implements INotifyPropertyChanged
. This is what makes binding work. Just calling PropertyChanged
alone won't do anything. You need to add
public class MainViewModel : INotifyPropertyChanged