What's wrong with my Xamarin.Forms project? - c#

I'm trying to make a Xamarin.Forms project where I have a BoxView and an Entry field and a Button. I want to enter the name of a color into my Entry field, press the button, and have my BoxView change to the color that I input. Here is the code I have written till now:
Views/MainView.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestGround.MainView">
<ContentPage.Content>
<StackLayout VerticalOptions="Center">
<Label
Text="Enter a color:"
VerticalOptions="Center"
HorizontalOptions="Center"
/>
<BoxView
Color="{Binding Color}"
/>
<Entry
Text="{Binding Name}"
/>
<Button
Text="Enter"
Command="{Binding SetColorCommand}"
/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
ViewModels/MainViewModel.cs
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
namespace TestGround
{
public class MainViewModel :INotifyPropertyChanged
{
private string _color; //backing field for Greeting
public string Color //implementation for Greeting method
{
get { return _color; }
set
{
_color = value;
OnPropertyChanged ("Color"); //Notify view that change has taken place
}
}
public string Name { get; set; } //Name method for Entry field
public ICommand SetColorCommand { get; set; } //ICommand binds to buttons in XAML
public void SetColor() //Need a regular method to add to ICommand
{
Color = Name;
}
//Main VIEW MODEL
public MainViewModel ()
{
//Color = Name;
Name = "Enter color here";
SetColorCommand = new Command(SetColor); //Regular command added to ICommand
}
#region PropertyChangedRegion
public void OnPropertyChanged (string propertyName)
{
if (PropertyChanged != null)
PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}
Here is the error I get:
Java.Lang.RuntimeException: java.lang.reflect.InvocationTargetException
I want to know if my approach is wrong and how can I go about fixing it and making this pretty simple program.

According to the BoxView Documentation, the property "Color" must actually be a color... where as you have it defined as a string named color. Your types are mixed up. It should be something like Colors.Blue.

You can use class ColorTypeConverter for change string to Color.
I 've simplified your problem to this source code
//You simplified model
public class bModel : BindableObject
{
private Color _realColor;
public Color Color
{
get { return _realColor; }
set
{
_realColor = value;
OnPropertyChanged ("Color");
}
}
public string _stringColor;
public string StringColor {
get {
return _stringColor;
}
set {
_stringColor = value;
Color = (Color)(new ColorTypeConverter ()).ConvertFrom (_stringColor);
}
}
public bModel ()
{
StringColor = "Blue";
}
}
}
//Your simplified page xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="s2c.MyPage">
<ContentPage.Content>
<BoxView x:Name="box" Color="{Binding Color}"/>
</ContentPage.Content>
</ContentPage>
//Your simplified page csharp
public partial class MyPage : ContentPage
{
public MyPage ()
{
InitializeComponent ();
this.BindingContext = new bModel ();
}
}

Related

.net Maui binding values multiple levels deep

How can I Pass a Binding from a Page to a View?
I have this Page(Xaml)
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:DataBindingTests.Views"
xmlns:model="clr-namespace:DataBindingTests.ViewModels"
x:Class="DataBindingTests.Pages.CoolePage"
Title="CoolePage"
x:DataType="model:CoolesModel">
<VerticalStackLayout>
<Label Text="{Binding YourName}"></Label>
<views:MainView YourName="{Binding YourName}"></views:MainView>
<Button Command="{Binding ChangeNameCommand}"></Button>
</VerticalStackLayout>
</ContentPage>
And its CodeBehind:
using DataBindingTests.ViewModels;
namespace DataBindingTests.Pages;
public partial class CoolePage : ContentPage
{
public CoolePage()
{
this.BindingContext = new CoolesModel();
InitializeComponent();
}
}
If I pass a String into my MainView it works and all events are fired. When I use the binding it doesn't. In this simple test, the app should display two times the same name, but only the Label of the ContentPage has the YourName property printed
<views:MainView YourName="Lars"></views:MainView> <-- Works
<views:MainView YourName="{Binding YourName}"></views:MainView> <-- doesn't work
This is the Xaml of the MainView
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:DataBindingTests.Views"
x:Class="DataBindingTests.Views.MainView">
<VerticalStackLayout>
<Label Text="{Binding YourName}"
VerticalOptions="Center"
HorizontalOptions="Center" />
</VerticalStackLayout>
</ContentView>
This is the CodeBehind of the MainView
namespace DataBindingTests.Views;
public partial class MainView : ContentView
{
public String YourName
{
get
{
String value = (String)GetValue(MainView.YourNameProperty);
return value;
}
set
{
SetValue(MainView.YourNameProperty, value);
}
}
public static readonly BindableProperty YourNameProperty = BindableProperty.Create(nameof(YourName)
, typeof(String)
, typeof(MainView), defaultBindingMode:BindingMode.TwoWay, propertyChanged: OnYourNameChanged);
static void OnYourNameChanged(BindableObject bindable, object oldValue, object newValue)
{
Console.WriteLine(newValue);
}
public MainView()
{
this.BindingContext = this; // Ignore ParentContext
InitializeComponent();
}
}
You can just remove code this.BindingContext = this; from the constructor of MainView.xaml.cs:
public MainView()
{
//this.BindingContext = this;
InitializeComponent();
}
Update:
the above code would only work because the Property in the View and
the Page have the same name.
In this condition, you can modify the code of MainView.xaml as follows:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp929.MainView"
x:Name="TestControlView"
>
<VerticalStackLayout>
<Label Text="{Binding Source={x:Reference TestControlView}, Path=YourName}"
VerticalOptions="Center"
HorizontalOptions="Center" />
</VerticalStackLayout>
</ContentView>
MainView.xaml.cs
public partial class MainView : ContentView
{
public String YourName
{
get
{
String value = (String)GetValue(YourNameProperty);
return value;
}
set
{
SetValue(YourNameProperty, value);
}
}
public static readonly BindableProperty YourNameProperty = BindableProperty.Create(nameof(YourName)
, typeof(String)
, typeof(MainView), defaultBindingMode: BindingMode.TwoWay, propertyChanged: OnYourNameChanged);
static void OnYourNameChanged(BindableObject bindable, object oldValue, object newValue)
{
Console.WriteLine("-----------------> "+newValue);
}
public MainView()
      {
            InitializeComponent();
// this.BindingContext = this;
}
}
CoolesModel.cs
public class CoolesModel
{
// public string YourName { get; set; }
public string Name { get; set; }
public string TestName { get; set; }
public ICommand ChangeNameCommand => new Command(changeMethod);
private void changeMethod()
{
}
public CoolesModel() {
//YourName = "abc";
Name = "abc";
TestName = "test123...";
}
}
MainPage.xaml.cs
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mauiapp929="clr-namespace:MauiApp929"
x:Class="MauiApp929.MainPage">
<ScrollView>
<VerticalStackLayout>
<Label Text="{Binding Name}"></Label>
<mauiapp929:MainView YourName="{Binding TestName}"></mauiapp929:MainView>
<Button Command="{Binding ChangeNameCommand}"></Button>
</VerticalStackLayout>
</ScrollView>
</ContentPage>
In this simple test, the app should display two times the same name, but only the Label of the ContentPage has the YourName property printed
You're overwriting your binding context half way through for some reason, and the context your page binding resolves (the normal way of using it, the parent context) is different than what you actually see on the screen (which is your this.BindingContext = this). And you never set your second context's property.

ListView Label Binding does not read Data, but show the length of string - Xamarin Form

=>Output image
My Label Binding in ListView does not read data from the AllNotes list, but it does show the length of input string.
Is it because my AllNotes list is empty or is there any error in my code?
I also don't find any error or exception while running the code too.
public ObservableCollection AllNotes { get; set; } = new
ObservableCollection();
#XAML
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-
namespace:App19.ViewModel"
x:Class="App19.MainPage">
<ContentPage.BindingContext>
<local:MainPageViewModel/>
</ContentPage.BindingContext>
<Grid RowDefinitions="*,auto">
<ListView ItemsSource="{Binding AllNotes}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame>
<Label Text="{Binding .}" TextColor="Red"
FontSize="20" LineBreakMode="WordWrap" BackgroundColor="Purple"
HorizontalOptions="StartAndExpand"/>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackLayout Grid.Row="1">
<Entry Placeholder="Enter new user name: " x:Name="userEntry" Text="{Binding GetName}"/>
<Button Text="Delete" Command="{Binding Delete}"/>
<Button Text="Save" Command="{Binding Change}"/>
</StackLayout>
</Grid>
</ContentPage>
#C-Sharp
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
using System.Threading.Tasks;
using Xamarin.Essentials;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace App19.ViewModel
{
public class MainPageViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public MainPageViewModel()
{
Delete = new Command(() =>
{
Name = string.Empty;
GetName = string.Empty;
});
Change = new Command(() =>
{
if (GetName != string.Empty)
{
Name = GetName;
AllNotes.Add(GetName);
GetName = string.Empty;
}
});
}
public ObservableCollection<string> AllNotes { get; set; } = new
ObservableCollection<string>();
public string GetName
{
get => name;
set
{
name = value;
var args = new PropertyChangedEventArgs(nameof(GetName));
PropertyChanged?.Invoke(this, args);
}
}
public string Name
{
get => name;
set
{
name = value;
var args = new PropertyChangedEventArgs(nameof(Name));
PropertyChanged?.Invoke(this, args);
}
}
public string name;
public Command Delete { get; }
public Command Change { get; }
}
}
You're setting the data in your AllNotes Observable Collection AFTER construction. This means you effectively want to update the contents of the ObservableCollection but you haven't triggered the PropertyChanged event in your set method.
Every time you wish to make a change to a field AFTER construction, you have to include;
PropertyChanged?.Invoke(this, args);
Make the following change to your code;
private ObservableCollection<string> _allNotes = new ObservableCollection<string>();
public ObservableCollection<string> AllNotes
{
get => _allNotes;
set
{
_allNotes = value;
var args = new PropertyChangedEventargs(nameof(AllNotes));
PropertyChanged?Invoke(this, args);
}
}
Depending on what your use case is, you could also opt to use CollectionView, but this is optional. it will reduce your code complexity and also included some additional Commands and features that ListView does not have.
Try replacing the listview with the collectionview. And also replace the ViewCell with a StackLayout or a Grid when using collectionview.
You can check the documentation here below.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/layout

xamarin forms Image does not show up

I have a simple app that has a PicListPage (picture list). The xaml and code behind allow picking a picture from the Android emulator gallery or from taking a picture.
The selected picture (or new picture) does not show up in an Image control. I have not been able to find a solution through a web search. This code was copied from a tutorial. Putting a breakpoint at the NewImage.Source line shows that there is a non-null value for the currentimage.
Any help would be appreciated. The MS Xamarin Forums won't allow me to register or log in so I can't ask the question there.
Jim Durbin
durbinjw#gmail.com
Here is the XAML
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="MyStuff.PicListPage">
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="selectImageButton"
Text="Select Image"
Command="{Binding SelectImageCommand}"/>
<ToolbarItem x:Name="takePicButton"
Text="Take Picture"
Command="{Binding TakePictureCommand}"
CommandParameter="{Binding NewImage}"/>
<ToolbarItem x:Name="deleteButton"
Text="Delete"
Command="{Binding DeletePictureCommand}"
CommandParameter="{Binding SelectedImage}"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<Label Text="Picture List page"
HorizontalOptions="Center"
FontSize="Large"
FontAttributes="Bold"/>
<Frame BorderColor="Black"
WidthRequest="350"
HeightRequest="350"
Margin="10,0,10,0">
<FlexLayout Direction="Row">
**<Image x:Name="NewImage"**
IsVisible="true"
Aspect="AspectFit"
Source="{Binding NewImmage, Mode=TwoWay}"
Margin="10,0,10,0"
WidthRequest="350"
HeightRequest="350"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand">
</Image>
</FlexLayout>
</Frame>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Here is the code behind - first the command code for selecting a picture
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;
namespace MyStuff.ViewModel.Commands
{
public class SelectImageCommand : ICommand
{
private PicListPageVM viewmodel;
public event EventHandler CanExecuteChanged;
public SelectImageCommand(PicListPageVM viewmodel)
{
this.viewmodel = viewmodel;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
viewmodel.SelectImage();
}
}
}
And here is the ViewModel code snippet that copies the image from the emulated Gallery which has 5 pictures in it.
using MyStuff.Model;
using MyStuff.ViewModel.Commands;
using Plugin.Media;
using Plugin.Media.Abstractions;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Xamarin.Forms;
namespace MyStuff.ViewModel
{
public class PicListPageVM : INotifyPropertyChanged
{
public ObservableCollection<PicList> PicLists { get; set; }
public TakePictureCommand TakePictureCommand { get; set; }
public SelectImageCommand SelectImageCommand { get; set; }
public DeletePictureCommand DeletePictureCommand { get; set; }
private Image newimage;
public Image NewImage
{
get { return newimage; }
set
{
newimage = value;
OnPropertyChanged("NewImage");
}
}
public PicListPageVM()
{
SelectImageCommand = new SelectImageCommand(this);
TakePictureCommand = new TakePictureCommand(this);
DeletePictureCommand = new DeletePictureCommand(this);
NewImage = new Image();
NewImage.IsOpaque = false;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public async void SelectImage()
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsPickPhotoSupported)
{
await App.Current.MainPage.DisplayAlert("Information", "Can't select pictures on this device", "OK");
return;
}
var mediaoptions = new PickMediaOptions()
{
PhotoSize = PhotoSize.Small
};
var selectedImageFile = await CrossMedia.Current.PickPhotoAsync(mediaoptions);
if (selectedImageFile == null)
{
await App.Current.MainPage.DisplayAlert("Information", "No image selected.", "OK");
return;
}
**var currentimage = ImageSource.FromStream(() => selectedImageFile.GetStream());
NewImage.Source = currentimage;**
}
first, you misspelt the name of your property ("NewImage") in the binding (TwoWay binding also doesn't make sense here)
<Image x:Name="NewImage" Source="{Binding NewImmage, Mode=TwoWay}" .. />
second, in your VM NewImage is of type Image, which is not right. Image is a UI control, not a data type. Use string instead
private string newimage;
public string NewImage
{
get { return newimage; }
set
{
newimage = value;
OnPropertyChanged("NewImage");
}
}
finally, when you select your image set the VM property to the image path
NewImage = selectedImageFile.AlbumPath;
This issue is resolved. Thanks to #Jason and a little further hacking. The key issues were 1) a typo in the binding 2) The binding needed to point to a property that had datatype string instead of an Image UI element - which in turn pointed to a file path and 3) setting the bound string to point to the selectedImageFile.Path rather than to selectedImageFile.AlbumPath.

DataBindings not updating with OnPropertyChanged

Building my first app with Xamarian.Forms. I have my basic menu and home page built with some labels and a button so that I can bind some data and a method and to make sure the logic code for my game is working. I got my data bindings working as far as the labels go, they appear on screen. However I was unsure if my bindings weren't updating or if my command wasn't binding. So I commented out the ICommand, removed the binding and put the method to advance a turn into the code behind my xaml. Even after this, the data is not updating when the button is clicked which leads me to believe it is a problem with my OnPropertyChanged and the data bindings. I've searched the web and related questions, I've implemented a couple different ways of writing the gets and sets for the bindings, wrote my OnPropertyChanged function a few different ways and still nothing happens when the toolbar button on the home page is clicked.
Here is my HomePageViewModel.cs containing INotifyPropertyChanged
***Edited to reflect changes made since getting the day value to update:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows.Input;
using Engine;
using Xamarin.Forms;
namespace TestApp
{
public class HomePageViewModel : INotifyPropertyChanged
{
public static Player _player = World.Player1;
public string Day = World.TrueDay.ToString();
public string MoneyValue = Convert.ToInt32(Math.Floor(World.Player1.PlayerMoney)).ToString();
public string CurrentLocation = _player.CurrentLocation.Name;
public HomePageViewModel()
{
OnTurn = new Command(execute: On1Turn);
}
public ICommand OnTurn { get; private set; }
public string CurrentDay
{
get { return Day; }
set { Day = value; OnPropertyChanged(); }
}
public string Money
{
get { return MoneyValue; }
set { MoneyValue = value; OnPropertyChanged(); }
}
public string PlayerLocation
{
get { return CurrentLocation; }
set { CurrentLocation = value; OnPropertyChanged(); }
}
void On1Turn()
{
World.TrueDay = World.TrueDay + 1;
CurrentDay = World.TrueDay.ToString();
World.Player1.PlayerMoney = World.Player1.PlayerMoney + 1000;
MoneyValue = Convert.ToInt32(Math.Floor(World.Player1.PlayerMoney)).ToString();
OnPropertyChanged(Money);
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
Here is my HomePage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local1="clr-namespace:TestApp"
mc:Ignorable="d"
x:Class="TestApp.HomePage">
<ContentPage.BindingContext>
<local1:HomePageViewModel/>
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="+24hrs" Clicked="ToolbarItem_Clicked" />
</ContentPage.ToolbarItems>
<StackLayout Padding="20">
<StackLayout Orientation="Horizontal">
<Label Text="Money:" HorizontalOptions="Start"/>
<Label x:Name="lblPlayerMoney" Text="{Binding Money, Mode=OneWay}" HorizontalOptions="FillAndExpand"/>
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="EndAndExpand" Margin="0,-40,0,0">
<Label Text="Current Location:" HorizontalOptions="CenterAndExpand"/>
<Label x:Name="lblPlayerLocation" Text="{Binding PlayerLocation, Mode=OneWay}" HorizontalOptions="CenterAndExpand"/>
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="StartAndExpand">
<Label Text="Current Day:" HorizontalOptions="CenterAndExpand" Margin="30,0,0,0"/>
<Label x:Name="lblCurrentDay" Text="{Binding CurrentDay, Mode=OneWay}" HorizontalOptions="CenterAndExpand"/>
</StackLayout>
</StackLayout>
</ContentPage>
And the HomePage.xaml.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Engine;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace TestApp
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class HomePage : ContentPage
{
public HomePage()
{
InitializeComponent();
//BindingContext = new HomePageViewModel();
}
private void ToolbarItem_Clicked(object sender, EventArgs e)
{
World.TrueDay = World.TrueDay + 1;
World.Player1.PlayerMoney = World.Player1.PlayerMoney + 1000;
}
}
}
Any insight into the issue would be greatly appreciated as I'm new to Xamarian.Forms and the OnPropertyChanged feature in general. Thanks for the time!
EDIT******
Here is the World.cs were I set the properties if it helps
using System;
using System.Collections.Generic;
using System.Text;
namespace Engine
{
public class World
{
public static decimal TrueDay = 1;
//public string LocationText = Player1.CurrentLocation.Name.ToString();
public static Player Player1;
public static readonly List<Location> Locations = new List<Location>();
public const int LOCATION_ID_OSHAWA = 1;
public const int LOCATION_ID_TORONTO = 2;
public static void GenerateWorld()
{
PopulateLocations();
Player1 = new Player("Jordan", LocationByID(LOCATION_ID_OSHAWA), 5000);
}
private static void PopulateLocations()
{
Location oshawa = new Location(LOCATION_ID_OSHAWA, "Oshawa");
Location toronto = new Location(LOCATION_ID_TORONTO, "Toronto");
Locations.Add(oshawa);
Locations.Add(toronto);
}
public static Location LocationByID(int id)
{
foreach (Location location in Locations)
{
if (location.ID == id)
{
return location;
}
}
return null;
}
}
}
Not too understanding logic about project, but if want to change model data can do as follow
HomePage.xaml.cs:
namespace TestApp
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class HomePage : ContentPage
{
HomePageViewModel homePageViewModel = new HomePageViewModel();
public HomePage()
{
InitializeComponent();
BindingContext = homePageViewModel ;
}
private void ToolbarItem_Clicked(object sender, EventArgs e)
{
homePageViewModel.CurrentDay = xxx ;
homePageViewModel.xxxxx = xxxx;
//Something like this can change model data
}
}
}
Here is a sample data binding discussion can be refer to.

Xamarin Data Binding

I genuinely can't work out if I'm being an idiot or not, what I'm to do is so simple!
I have a ViewModel with a public Username field.
Originally I tried to get the Entry to display an initial value but upon looking further I've discovered I can't even get the view to update the viewmodel.
I want the text to reflect the entered username when I click the button and display it in the Alert.
My ViewModel:
public class LoginViewModel
{
public String Username { get; set; }
public String Password { get; set; }
public int UserId { get; set; }
}
My Page:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage Padding="15,15,15,15"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="EngineerApp.LoginPage">
<AbsoluteLayout>
<StackLayout VerticalOptions="EndAndExpand" Orientation="Vertical">
<Image Source="traklogo.png" VerticalOptions="FillAndExpand"></Image>
<Label TextColor="#207cad" Text="Username" />
<Label Text="{Binding Username}"></Label>
<Entry Text="{Binding Username, Mode=TwoWay}" TextColor="Black" Placeholder="Please enter your username..." x:Name="txtUsername" />
</StackLayout>
</AbsoluteLayout>
</ContentPage>
My Page's Code:
public partial class LoginPage : ContentPage
{
public LoginViewModel viewModel = new LoginViewModel();
public LoginPage()
{
InitializeComponent();
BindingContext = viewModel;
btnLogIn.Clicked += delegate
{
DisplayAlert("Test",viewModel.Username,"Okay");
return;
};
}
}
This working snippet from a LoginViewModel that implements INotifyPropertyChanged is in an app published in stores:
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
public string Username
{
get { return username; }
set
{
if (username == value) return;
username = value?.ToLowerInvariant();
OnPropertyChanged();
}
}
And the associated Entry XAML snippet:
<Entry x:Name="UsernameEntry" HeightRequest="45" Keyboard="Email"
Placeholder="{Binding LabelUsername}" Text="{Binding Username}">
I've worked it out. The page BEFORE this page was passing in it's own BindingContext. Removing this resolved my issues.

Categories