Can't update data bindings from object in Xamarin forms - c#

Im trying to update my xamarin bindings from a object in my viewmodel. What am I doing wrong.
When i see look at the page and look at "User", i see my user object is there.
Page:
<StackLayout BindableLayout.ItemsSource="{Binding User}"
Orientation="Horizontal">
<BindableLayout.ItemTemplate>
<DataTemplate x:DataType="model:User">
<StackLayout>
<Label Text="{Binding Name, Mode=OneWay}"/>
<Label Text="{Binding PhoneNumber, Mode=OneWay}"/>
<Label Text="{Binding Adress, Mode=OneWay}"/>
<Label Text="{Binding Email, Mode=OneWay}"/>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
What you need to know about the Viewmodel with mvvhelpers
public User User { get; set; }
public MyProfileViewModel()
{
Title = "MyProfile";
RefreshCommand = new AsyncCommand(Refresh);
AddCommand = new AsyncCommand(Add);
// RemoveCommand = new AsyncCommand<User>(Remove);
User = new User();
}
public async refrsh(){
User = await MyProfileService.GetMyProfile(2);
nameDisplay = User.Name;
}
string nameDisplay;
public string NameDisplay
{
get => nameDisplay;
set => SetProperty(ref nameDisplay, value);
}

According to Jason's opinion, you don't need to use BindableLayout and a DataTemplate if you only have a single User object, you can bind User Object to StackLayout BindingContext directly.
<StackLayout BindingContext="{Binding User}">
<Label Text="{Binding Name, Mode=OneWay}" />
<Label Text="{Binding PhoneNumber, Mode=OneWay}" />
<Label Text="{Binding Adress, Mode=OneWay}" />
<Label Text="{Binding Email, Mode=OneWay}" />
</StackLayout>
If you have collection of IEnumerable User, you can use BindableLayout.ItemsSource and a DataTemplate
You need to implement INotifyPropertyChanged for User properties, it will notify the data changes.
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
The complete code:
<StackLayout>
<StackLayout BindingContext="{Binding User}">
<Label Text="{Binding Name, Mode=OneWay}" />
<Label Text="{Binding PhoneNumber, Mode=OneWay}" />
<Label Text="{Binding Adress, Mode=OneWay}" />
<Label Text="{Binding Email, Mode=OneWay}" />
</StackLayout>
<Button
x:Name="btn1"
Command="{Binding changecommand}"
Text="change user data" />
</StackLayout>
public partial class Page27 : ContentPage
{
public Page27()
{
InitializeComponent();
this.BindingContext = new MyProfileViewModel();
}
}
public class MyProfileViewModel
{
public User User { get; set;}
public ICommand changecommand { get; }
public MyProfileViewModel()
{
User = new User();
User.Name = "cherry";
User.PhoneNumber = "123";
User.Adress = "location 1";
User.Email = "xxxxx.#outlook.com";
changecommand = new Command(() =>
{
User.Name = "barry";
});
}
}
public class User:ViewModelBase
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
RaisePropertyChanged("Name");
}
}
private string _PhoneNumber;
public string PhoneNumber
{
get { return _PhoneNumber; }
set
{
_PhoneNumber = value;
RaisePropertyChanged("PhoneNumber");
}
}
private string _Adress;
public string Adress
{
get { return _Adress; }
set
{
_Adress = value;
RaisePropertyChanged("Adress");
}
}
private string _Email;
public string Email
{
get { return _Email; }
set
{
_Email = value;
RaisePropertyChanged("Email");
}
}
}

Related

OnPropertyChanged not fire with label text

I am in a Xamarin app I which I have to make a to-do list. I am using listview. I have to set a label text dynamically every time I add a new to-do like so: Number of tasks 2/4 where 2 are the done tasks and 4 are the total ones. Everything goes right but I found some issues when I have to update the label text. I am using the MVVM pattern. In XAML I bind the text value to SetInfoDoneText. In MainPage, I have the bindigContext set to VM(TodoListViewModel). I use INotifyPropertyChanged with OnPropertyChanged. I made a method in which the value of setInfoDoneText is changed. The problem is that the set and get is called only once and when the setInfoDoneText is updated by the method OnPropertyChanged does not fire again. Here is the code.
THE PROBLEM IS WHEN I TRY TO UPDATE lblDoneInfo text (
)
class TodoListViewModel: INotifyPropertyChanged
{
public ObservableCollection<TodoItem> todoItems { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public String setInfoDoneText;
public String SetInfoDoneText
{
get => setInfoDoneText;
set
{
setInfoDoneText = value;
OnPropertyChanged("SetInfoDoneText");
}
}
protected void OnPropertyChanged(string propertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
int doneTask = 0;
int totalTask = 0;
public TodoListViewModel()
{
this.todoItems = new ObservableCollection<TodoItem>();
setInfoDoneText = "Number of tasks: " + doneTask + "/" + totalTask;
}
public ICommand AddTodoCommand => new Command(AddTodoItem);
public String newTodoInputValue { get; set; }
public String selectedItem { get; set; }
public bool highPriority { get; set; }
public bool midPriority { get; set; }
public bool lowPriority { get; set; }
Color newColor = new Color();
public void AddTodoItem()
{
if (highPriority)
{
newColor = Color.Red;
AddNewItem(newColor);
highPriority = false;
}
if (midPriority)
{
newColor = Color.Orange;
AddNewItem(newColor);
midPriority = false;
}
if (lowPriority)
{
newColor = Color.Yellow;
AddNewItem(newColor);
lowPriority = false;
}
}
public TodoItem AddNewItem(Color newColor)
{
TodoItem newItem = new TodoItem(newTodoInputValue,
false,
highPriority,
midPriority,
lowPriority,
newColor);
todoItems.Add(newItem);
UpdateDoneInfo();
return newItem;
}
public ICommand RemoveTodoCommand => new Command(RemoveTodoItem);
public void RemoveTodoItem(object o)
{
TodoItem todoItemBeingRemoved = o as TodoItem;
todoItems.Remove(todoItemBeingRemoved);
}
public ICommand EditTodoCommand => new Command(EditTodoItem);
public void EditTodoItem(object o)
{
TodoItem todoItemBeingEdited = o as TodoItem;
int newIndex = todoItems.IndexOf(todoItemBeingEdited);
todoItems.Remove(todoItemBeingEdited);
TodoItem updatedTodo = AddNewItem(newColor);
//todoItems.Add(updatedTodo);
int oldIndex = todoItems.IndexOf(updatedTodo);
todoItems.Move(oldIndex, newIndex);
}
public String UpdateDoneInfo()
{
totalTask = todoItems.Count;
foreach (TodoItem item in todoItems)
{
if (item.complete) doneTask++;
}
return setInfoDoneText = "Number of tasks: " + doneTask + "/" + totalTask;
}
}
<ContentPage.BindingContext>
<local:TodoListViewModel/>
</ContentPage.BindingContext>
<StackLayout>
<Entry
x:Name="inputField"
Text="{Binding newTodoInputValue}"
Placeholder="Enter a todo..."
/>
<Label x:Name="lblDoneInfo" Text="{Binding SetInfoDoneText, Mode=TwoWay }">
</Label>
<FlexLayout AlignItems="Center" JustifyContent="SpaceBetween">
<input:CheckBox x:Name="highP"
IsChecked="{Binding highPriority}"
CheckChangedCommand="{Binding AddTodoCommand}"
Margin="0,0,20,0" />
<Label Text="High Priority" FontSize="Medium"/>
<input:CheckBox x:Name="midP"
IsChecked="{Binding midPriority}"
CheckChangedCommand="{Binding AddTodoCommand}"
Margin="0,0,20,0" />
<Label Text="Medium Priority" FontSize="Medium"/>
<input:CheckBox x:Name="lowP"
IsChecked="{Binding lowPriority}"
CheckChangedCommand="{Binding AddTodoCommand}"
Margin="0,0,20,0" />
<Label Text="Low Priority" FontSize="Medium"/>
</FlexLayout>
<ListView x:Name="todoList" ItemsSource="{Binding todoItems}" SelectedItem="{Binding selectedItem}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="20">
<FlexLayout JustifyContent="SpaceBetween" AlignItems="Center" Padding="20,0">
<ContentView>
<FlexLayout AlignItems="Center">
<input:CheckBox IsChecked="{Binding complete}" Margin="5" />
<Label x:Name="todoText" TextColor="{Binding color}" Text="{Binding todoText}" FontSize="Large"/>
</FlexLayout>
</ContentView>
<ImageButton
Source="editar_24.png"
BackgroundColor="Transparent"
WidthRequest="100"
HeightRequest="100"
Margin="0,0,20,0"
Command="{Binding Path=BindingContext.EditTodoCommand,
Source={x:Reference todoList}}"
CommandParameter="{Binding .}"/>
<ImageButton
Source="basura_24.png"
BackgroundColor="Transparent"
WidthRequest="100"
HeightRequest="100"
Command="{Binding Path=BindingContext.RemoveTodoCommand,
Source={x:Reference todoList}}"
CommandParameter="{Binding .}"/>
</FlexLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
PropertyChanged only fires when you set the value of the public property SetInfoDoneText. Your code is setting the value of the field setInfoDoneText (lowercase).
It is generally best practice to make the field private to prevent this
private String setInfoDoneText;

Xamarin Forms Editing Item with SQL

I have an application where items are added to a collection view and then you can tap on that item where a detail page comes up. With this detail page, you can edit the title and description given and then it should update in the collection view. However, when changes are made to the item, the item is not changed within the observable collection. How do I go about this?
Here is my xaml for the detail page:
<StackLayout Spacing="5" Padding="10" AnchorY="0.5">
<!--<Label Text="Title:" FontSize="Medium" FontAttributes="Bold" TextColor="White"/>-->
<Editor Text="{Binding Text}" FontSize="Title" TextColor="White"/>
<!--<Label Text="Note:" FontSize="Medium" FontAttributes="Bold" TextColor="White"/>-->
<Editor Text="{Binding Description}" FontSize="Small" TextColor="White"/>
<Grid ColumnDefinitions="*,*,*">
<Label Grid.Column="0" Grid.ColumnSpan="2" Text="Due Date:" FontSize="Medium" FontAttributes="Bold" TextColor="White" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand"/>
<Label Grid.Column="0" Grid.ColumnSpan="2" Padding="50,4,0,0" Text="{Binding DueDate}" FontSize="Small" TextColor="White" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"/>
</Grid>
<Button Text="Save"
Command="{Binding SaveChangesCommand}"
VerticalOptions="EndAndExpand"
HorizontalOptions="EndAndExpand"
BackgroundColor="Black"
BorderWidth="1.5"
BorderColor="White"
CornerRadius="50">
</Button>
</StackLayout>
Here is my DataBaseService:
public async Task UpdateItem(Item item)
{
var databasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MyData3.db");
var db = new SQLiteAsyncConnection(databasePath);
await db.UpdateAsync(item);
OnUpdatedItem?.Invoke();
}
OnUpdateItem?.Invoked();
private void LocalDatabaseService_OnUpdatedItem()
{
_ = ExecuteLoadItemsCommand();
}
and here is the OnSaveChanges
private async void OnSaveChanges(Item item)
{
Text = Text;
Description = Description;
DueDate = DueDate;
await LocalDatabaseService.UpdateItem(item);
await Shell.Current.GoToAsync("..");
}
LoadItems:
async Task ExecuteLoadItemsCommand()
{
IsBusy = true;
try
{
Items.Clear();
var items = await LocalDatabaseService.GetAllItems();
foreach (var item in items)
{
Items.Add(item);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
Item Model:
public class Item : INotifyPropertyChanged
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Text
{
get { return Text; }
set
{
Text = value;
if (Text != value)
{
OnPropertyChanged("Text");
Text = value;
}
}
}
public string Description
{
get { return Description; }
set
{ Description = value;
if(Description != value)
{
OnPropertyChanged("Description");
Description = value;
}
}
}
public DateTime DueDate { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
any help is appreciated, Thanks.
From the code you posted, we found the parameter in method OnSaveChanges is useless since it is always null.
You can change your code like this in class ItemDetailViewModel:
public Command SaveChangesCommand { get; }
public ItemDetailViewModel()
{
SaveChangesCommand = new Command(OnSaveChanges);
}
And method OnSaveChanges:
private async void OnSaveChanges()
{
Item item = new Item();
item.Id = Int32.Parse(ItemId);
item.Text = Text;
item.Description = Description;
item.DueDate = DueDate;
await LocalDatabaseService.UpdateItem(item);
await Shell.Current.GoToAsync("..");
}

How to fix ListView not showing contents of ObservableCollecton which is binded to it's ItemSource [duplicate]

This question already has an answer here:
Databindings don't seem to refresh
(1 answer)
Closed 3 years ago.
I am using MVVM pattern in my Xamarin.Forms application. I am trying to fill my page with a list of cards with simple information. For that I am using an ObservableCollection (CardsCollectionViewModel.cs) and objects of the class(CardViewModel) which are stored in the collection.
The Collection is initialized and passed to the MainPage.xaml.cs class. In the MainPage.xaml the collection name is binded to ListView ItemSource and the properties of storing objects are binded to the contents of list.
After the program starts and loads the Cards collections successfull, the page appears to be left empty.
Full project here: https://github.com/InfroLab/barkot/tree/master/Barkot
Here is my card class:
CardViewModel.cs
public class CardViewModel : INotifyPropertyChanged
{
//some code
public CardViewModel(int id, string company, string barcode, string type, string site)
{
//some code
}
private int id;
private string company = "";
private string barcode = "";
private string type = "";
private string site = "";
public int Id { get; set; }
public string Company
{
get { return company; }
set
{
//Console.WriteLine("{0}", Company);
if (company != value)
{
company = value;
OnPropertyChanged("Company");
}
}
}
public string Barcode
{
get { return barcode; }
set
{
if (barcode != value)
{
barcode = value;
OnPropertyChanged("Barcode");
}
}
}
public string Type
{
get { return type; }
set
{
if (type != value)
{
type = value;
OnPropertyChanged("Type");
}
}
}
public string Site
{
get { return site; }
set
{
if (site != value)
{
site = value;
OnPropertyChanged("Site");
}
}
}
}
Here is my collection class:
CarCollectionViewModel.cs
public class CardCollectionViewModel : INotifyPropertyChanged
{
public static ObservableCollection<CardViewModel> Cards { get; set; }
//some code
public static void UpdateCards()
{
//gettingitems from local db
Cards = App.Database.GetItems();
}
public CardCollectionViewModel()
{
Cards = new ObservableCollection<CardViewModel>();
UpdateCards();
//some code
}
}
Here is ListView from MainPage.xaml:
<ListView SeparatorVisibility="None" HasUnevenRows="True" ItemsSource="{Binding Cards}" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Frame Margin="10" HeightRequest="148" Padding="10" CornerRadius="5" HasShadow="True" BackgroundColor="#FFFFFF" InputTransparent="False" >
<StackLayout Orientation="Vertical">
<Button Text="Edit" Command="{Binding EditCardCommand}" BackgroundColor="#EBEBEB" HeightRequest="20" HorizontalOptions="End"/>
<StackLayout Orientation="Horizontal">
<WebView Source="{Binding Site}" HeightRequest="128" WidthRequest="128" VerticalOptions="FillAndExpand"/>
<StackLayout Spacing="5" Orientation="Vertical">
<Label Text="{Binding Company}" FontSize="Small" TextColor="#232323" />
<Label Text="{Binding Barcode}" FontSize="Small" TextColor="#232323" />
<forms:ZXingBarcodeImageView BarcodeFormat="{Binding Type}" BarcodeValue="{Binding Barcode}" HeightRequest="40" WidthRequest="200">
<zx:ZXingBarcodeImageView.BarcodeOptions>
<zxcm:EncodingOptions Width="200" Height="40" PureBarcode="True"/>
</zx:ZXingBarcodeImageView.BarcodeOptions>
</forms:ZXingBarcodeImageView>
</StackLayout>
</StackLayout>
</StackLayout>
</Frame>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I expect to see a loaded list on my page, but the actual content of it is empty.
SOLUTION:
private ObservableCollection<CardViewModel> cards = new ObservableCollection<CardViewModel>();
public ObservableCollection<CardViewModel> Cards
{
get
{
return cards;
}
set
{
if (cards != value)
{
cards = value;
OnPropertyChanged("Cards");
}
}
}
when you update Cards
Cards = App.Database.GetItems();
you are not raising a PropertyChanged event because you are using a default getter for Cards

Not Refreshing Spesific Label While Binding ObservableCollection Listview in Xamarin & MVVM

public class Zicker : INotifyPropertyChanged
{
public class MyClass
{
public string HeyName { get; set; }
public string HeySurname { get; set; }
public int HeyAge { get; set; }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string name = null)
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));
}
}
private ObservableCollection<MyClass> _yourList = new ObservableCollection<MyClass>();
public ObservableCollection<MyClass> YourList
{
get
{
return _yourList;
}
set
{
_yourList = value;
RaisePropertyChanged("YourList");
RaisePropertyChanged("BindMeLabel");
}
}
public int BindMeLabel
{
get { return _yourList.Sum(a => a.HeyAge); }
}
public void WonCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
RaisePropertyChanged("BindMeLabel");
}
public List<string> heresamplenames = new List<string> { "Mohamed", "Zaran", "Ivan" };
public List<string> heresamplesurnames = new List<string> { "Pakou", "Simmone", "Zagoev" };
public List<int> heresampleages = new List<int> { 17,33,50 };
public Zicker()
{
ObservableCollection<MyClass> vs = new ObservableCollection<MyClass>();
for (int i = 0; i < 3; i++)
{ vs.Add(new MyClass { HeyName = heresamplenames[i], HeySurname = heresamplesurnames[i], HeyAge = heresampleages[i] }); }
YourList = vs; YourList.CollectionChanged += WonCollectionChanged;
}
}
<ContentPage.Content>
<StackLayout Orientation="Vertical" HorizontalOptions="Center" VerticalOptions="Center">
<ContentView HorizontalOptions="Fill" VerticalOptions="Fill">
<ListView HorizontalOptions="Center" VerticalOptions="Center" HasUnevenRows="True" ItemsSource="{Binding YourList}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label HorizontalTextAlignment="Center" VerticalTextAlignment="Center" Text="{Binding Path=HeyName}" Grid.Column="0" FontSize="12" TextColor="Black"></Label>
<Label HorizontalTextAlignment="Center" VerticalTextAlignment="Center" Text="{Binding Path=HeySurname}" FontSize="12" TextColor="Black" Grid.Column="1"/>
<Entry HorizontalTextAlignment="Center" VerticalOptions="Center" Text="{Binding Path=HeyAge}" FontSize="12" Keyboard="Numeric" TextColor="Black" Grid.Column="2"/>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentView>
<Label Text="{Binding BindMeLabel}" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" FontSize="40" TextColor="Black"></Label>
</StackLayout>
</ContentPage.Content>
public MainPage()
{
InitializeComponent();
BindingContext = new Zicker();
}
My Problem: In this List, there are three names, surnames, and ages. At the bottom, there is also a label which should be shown as the sum of Ages collection.
When the UI is starting, Label is working well. But, if I try to change any Ages entries, there is a big problem with the binding label.
I want to use MVVM structure but due to this problem, label binding is working just start up.
If you are updating the HeyName property, binding is not updating because the class MyClass does not implement INotifyPropertyChanged.
Try to replace the MyClass class with this code:
public class MyClass : INotifyPropertyChanged
{
private string name;
private string surname;
private int age;
public string HeyName
{
get => name;
set
{
name = value;
RaisePropertyChanged("HeyName");
}
}
public string HeySurname
{
get => surname;
set
{
surname = value;
RaisePropertyChanged("HeySurname");
}
}
public int HeyAge
{
get => age;
set
{
age = value;
RaisePropertyChanged("HeyAge");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string name = null)
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
EDIT:
Sorry, the CollectionChanged is not called when you update the HeyAge property, because it is called only if the collection is changed, but not when a property of an item in the collection changes.
Try to add the OnAgeChanged event into the class MyClass and call it when the HeyAge property change:
public class MyClass : INotifyPropertyChanged
{
public event EventHandler OnAgeChanged;
public int HeyAge
{
get => age;
set
{
age = value;
RaisePropertyChanged("HeyAge");
OnAgeChanged?.Invoke(this, EventArgs.Empty);
}
}
...
...
Then, when you add a new MyClass object into the collection, register the event in the ViewModel like this:
public Zicker()
{
ObservableCollection<MyClass> vs = new ObservableCollection<MyClass>();
for (int i = 0; i < 3; i++)
{
var test = new MyClass()
{
HeyName = heresamplenames[i],
HeySurname = heresamplesurnames[i],
HeyAge = heresampleages[i],
};
test.OnAgeChanged += Test_OnAgeChanged;
vs.Add(test);
}
YourList = vs;
YourList.CollectionChanged += WonCollectionChanged;
}
private void Test_OnAgeChanged(object sender, EventArgs e)
{
RaisePropertyChanged("BindMeLabel");
}
Note that the WonCollectionChanged it's not necessary any more.
Note also that the variable vs is not needed, you can work directly into the YourList object instead.

call a method of the binding class from a button click xamarin.

So i have a View that i have bound to a List of Timer objects called Timers (custom class i have made), and in the view i have added a start and remove button. when a user clicks start i want them to be able to call the relevant timer object method startTimer() associated with the button. How can i do this?
View code:
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<ListView ItemsSource="{Binding Timers, Mode=TwoWay}" SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout HorizontalOptions="StartAndExpand" Orientation="Horizontal">
<StackLayout Padding="10,0,0,0" VerticalOptions="StartAndExpand" Orientation="Vertical">
<Label Text="{Binding _name, Mode=TwoWay}" YAlign="Center"/>
<Label Text="{Binding _startTime, Mode=TwoWay}" YAlign="Center" FontSize="Small"/>
</StackLayout>
<Button Text="Start" //button to associate with method//></Button>
<Button Text="Remove"></Button>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Text="Add New" Clicked="AddNewTimer"/>
</StackLayout>
</ContentPage.Content>
My Binded Class:
public class MainViewModel : INotifyPropertyChanged
{
public MainViewModel ()
{
Timers = DependencyService.Get<ISaveAndLoad> ().LoadTimers ();
if (Timers == null) {
Timers = new ObservableCollection<Timer> ();
}
}
//When property changes notifys everything using it.
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private ObservableCollection<Timer> _timers;
public ObservableCollection<Timer> Timers {
get { return _timers; }
set {
_timers = value;
NotifyPropertyChanged ("Timers");
}
}
private string _title;
public string Title{
get{
return _title;
}
set{
_title = value;
NotifyPropertyChanged ();
}
}
}
And the timer class:
public class Timer
{
public int _startTime { get; set;}
public bool _hasStarted{ get; set; }
public string _name { get; set; }
public Timer (string name, int startTime, bool hasStarted = false)
{
_name = name;
_startTime = startTime;
_hasStarted = hasStarted;
}
public void startTimer(){
//do something here
}
}
Cheers.
On your View XAML code you should add this to your start button:
<Button Text="Start" Command={Binding btnStartCommand} />
Then on your "My Binded Class: " you should create de ICommand property and initialize it on the constructor and then create the Command, something like this:
public ICommand btnStartCommand {get; set;}
public MainViewModel()
{
btnStartCommand = new Command(StartCommand);
}
public void StartCommand()
{
//here you create your call to the startTimer() method
}
Hope this helps you,
Cheers.

Categories