why_vincent
why_vincent

Reputation: 2262

Accessing XAML from code properly

I'm just getting started with Xamarin.Forms and I'm not finding any documentation that specifies how I manipulate something like the text in a Label from code. I just have an application with a Label, a plus button and a minus button. Plus should increment the value in the Label and minus should do the opposite.

My view is defined in XAML. When I look at https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_binding_basics/ then I don't really find something that matches this. I guess that I should create a "NumberViewModel" that represents the number, then use some PropertyChanged-isch system to bind the data to the view.

If this was Android then I would define my buttons in xml with the expected names of the methods that will handle a button-click(I do the same in Xamarin.Forms). Then the button is clicked then the method in code will be triggered and in the triggered method I will probably retrieve the object I wish to manipulate by calling findViewById(....).

I will adjust to Xamarin.Forms but it would be great with a simple guide that just showes how to bind a string to a label, without hundreds of lines of code. Please tell me that I am just bad at googling, because I've spend a lot of time trying to figure this out.

Upvotes: 1

Views: 2820

Answers (1)

MarcoK
MarcoK

Reputation: 6110

There are two approaches you can go here: the easier, but uglier one, and the little bit more complex, but prettier one.

Directly editing the code behind

(Easier, but uglier due to high coupling)

Say we would have the following XAML:

<StackLayout Orientation="Vertical">
    <Label x:Name="lblOutput" Text="[output]" />
    <StackLayout Orientation="Horizontal">
        <Button x:Name="btnAdd" Text="+" />
        <Button x:Name="btnMinus" Text="-" />
    </StackLayout>
</StackLayout>

You can reference the UI directly in the code behind like so (simplified):

int currentValue = 0;
lblOutput.Text = currentValue.ToString ();
btnAdd.Clicked += delegate {
    currentValue++;
    lblOutput.Text = currentValue.ToString ();
};

btnMinus.Clicked += delegate {
    currentValue--;
    lblOutput.Text = currentValue.ToString ();
};

The trick here is the use of x:Name, allowing you to directly use the element in the code behind.

Using the MVVM approach

(More complex, but more flexible)

Create a new class (your ViewModel) and implement the INotifyPropertyChanged interface. Bind that class to the view in the XAML code behind like so:

this.BindingContext = new ViewModel ();

Now we can have a XAML like this:

<StackLayout Orientation="Vertical">
    <Label Text="{Binding CurrentValue}" />
    <StackLayout Orientation="Horizontal">
        <Button Text="+" Command="{Binding AddCommand}" />
        <Button Text="-" Command="{Binding MinusCommand}" />
    </StackLayout>
</StackLayout>

and the ViewModel would look like this:

public ICommand AddCommand { get; private set; }
public ICommand MinusCommand { get; private set; }

public ViewModel ()
{
    AddCommand = new Command (() => {
        CurrentValue = CurrentValue+1;
    });

    MinusCommand = new Command (() => {
        CurrentValue = CurrentValue-1;
    });
}

public int CurrentValue { get; set; } // You'll need to handle the PropertyChanged events here

You can read more about it here and here.

I hope this helps!

Upvotes: 6

Related Questions