I'm pretty new at xamarin and I'm trying to read a value out of an editor/entry using MVVM but every time I launch the code and I open the page my initializer gives me a nullreferencexception. From what I think I know I should just bind the editor text to a value in my viewmodel and reference it in my xaml file (xmlns), even looking at the documentation and seeing other people doing it in example code and videos I don't seem to be able to fix this issue.
If anyone knows if I missed a step or don't understand something, it would be a massive help if you could inform me of this.
Thank you for your time and help.
this is what my xaml looks like:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:student_app.ViewModels"
x:Class="student_app.Views.AddCategoryPage"
xmlns:model="clr-namespace:student_app.Models" >
<ContentPage.BindingContext>
<local:AddCategoryViewModel/>
</ContentPage.BindingContext>
<RefreshView x:DataType="local:AddCategoryViewModel" Command="{Binding LoadCategoriesCommand}" IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
<StackLayout>
<Label Text="Add Category:"/>
<Editor Grid.Row="1" Grid.Column="0" Width="300" Text="{Binding CategoryNameEditor}" Placeholder="enter category name"/>
<Button x:Name="saveButton" Text="Save" Command="{Binding SaveCommand}"/>
</StackLayout>
</RefreshView>
</ContentPage>
this is what my code behind looks like:
namespace student_app.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class AddCategoryPage : ContentPage
{
AddCategoryViewModel _viewModel;
public AddCategoryPage()
{
InitializeComponent();
this.BindingContext = _viewModel = AppContainer.Resolve<AddCategoryViewModel>();
}
protected override void OnAppearing()
{
base.OnAppearing();
_viewModel.OnAppearing();
}
}
}
viewmodel code:
namespace student_app.ViewModels
{
public class AddCategoryViewModel : BaseViewModel
{
private readonly IToastService _toastService;
private readonly INavigationService _navigationService;
private readonly ICategoryService _categoryService;
public string categoryName;
public Command SaveCommand { get; }
public Command LoadCategoriesCommand { get; }
public event PropertyChangingEventHandler PropertyChanged;
public string CategoryNameEditor
{
get => categoryName;
set
{
categoryName = value;
var args = new PropertyChangingEventArgs(nameof(CategoryNameEditor));
PropertyChanged?.Invoke(this, args);
}
}
public AddCategoryViewModel(IToastService toastService, INavigationService navigationService, ICategoryService categoryService)
{
_toastService = toastService;
_navigationService = navigationService;
_categoryService = categoryService;
SaveCommand = new Command(async () => await ExecuteSaveCommandCommand());
LoadCategoriesCommand = new Command(async () => await ExecuteLoadCategoriesCommand());
}
public async Task ExecuteLoadCategoriesCommand()
{
IsBusy = true;
try
{
categoryName = string.Empty;
}
catch (Exception ex)
{
await _toastService.DisplayToastAsync(ex.Message);
}
finally
{
IsBusy = false;
}
}
public async Task ExecuteSaveCommandCommand()
{
IsBusy = true;
try
{
_categoryService.addCategory(categoryName);
categoryName = string.Empty;
await _navigationService.NavigateAsync("CalanderPage");
}
catch (Exception ex)
{
await _toastService.DisplayToastAsync(ex.Message);
}
finally
{
IsBusy = false;
}
}
public void OnAppearing()
{
IsBusy = true;
}
}
}
Related
My first try with Xamarin, and stuck on the basic.
Build Master-View, all working fine, can add new items.
However when click on existing item it is read only.
I have implemented edit button, but do not know how to make item editable in the detail view.
My ItemDetailPage.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="DataCollector.Views.ItemDetailPage"
Title="{Binding Title}">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Delete" Clicked="ToolbarItem_Clicked" />
<ToolbarItem Text="Edit" Clicked="Edit_Clicked" />
</ContentPage.ToolbarItems>
<StackLayout Spacing="20" Padding="15">
<Label Text="WTN Number:" FontSize="Medium" />
<Label Text="{Binding Item.WTNNumber}" d:Text="Item name" FontSize="Small"/>
<Label Text="Description:" FontSize="Medium" />
<Label Text="{Binding Item.Description}" d:Text="Item description" FontSize="Small"/>
</StackLayout>
</ContentPage>
and ItemDetailPage.xaml.cs
using System;
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using DataCollector.Models;
using DataCollector.ViewModels;
namespace DataCollector.Views
{
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(false)]
public partial class ItemDetailPage : ContentPage
{
ItemDetailViewModel viewModel;
public ItemDetailPage(ItemDetailViewModel viewModel)
{
InitializeComponent();
BindingContext = this.viewModel = viewModel;
}
public ItemDetailPage()
{
InitializeComponent();
var item = new Item
{
WTNNumber = "Item 1",
Description = "This is an item description."
};
viewModel = new ItemDetailViewModel(item);
BindingContext = viewModel;
}
private void Delete_Clicked(object sender, EventArgs e)
{
}
private void Edit_Clicked(object sender, EventArgs e)
{
}
}
}
and ItemDetailViewModel.cs
using System;
using DataCollector.Models;
namespace DataCollector.ViewModels
{
public class ItemDetailViewModel : BaseViewModel
{
public Item Item { get; set; }
public ItemDetailViewModel(Item item = null)
{
Title = item?.WTNNumber;
Item = item;
}
}
}
How to do it through ItemDetailViewModel changes?
Since you had used MVVM .It would be better to handle the logic in ViewModel .
So you could improve it like following .
in xaml
<ContentPage.ToolbarItems>
<ToolbarItem Text="Delete" Command="{Binding DeleteCommand}"/>
<ToolbarItem Text="Edit" Command="{Binding EditCommand}" />
</ContentPage.ToolbarItems>
in View Model
public class ItemDetailViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Item item;
public Item Item {
get {
return item;
}
set
{
if(item!=value)
{
item = value;
NotifyPropertyChanged("Item");
}
}
}
public ICommand DeleteCommand { get; set; }
public ICommand EditCommand { get; set; }
public ItemDetailViewModel (Item item )
{
var Title = item?.WTNNumber;
Item = item;
DeleteCommand = new Command(()=> {//...
});
EditCommand = new Command(()=> {
Item.WTNNumber = "new item";
Item.Description = "new Description";
// do something when click the edit button
});
}
}
in model
public class Item : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
string wTNNumber;
public string WTNNumber
{
get
{
return wTNNumber;
}
set
{
if (wTNNumber != value)
{
wTNNumber = value;
NotifyPropertyChanged("WTNNumber");
}
}
}
string description;
public string Description
{
get
{
return description;
}
set
{
if (description != value)
{
description = value;
NotifyPropertyChanged("Description");
}
}
}
}
I know this has been asked before but I've spent ages and nothing has helped.
I'm trying to update a progress bar from a ViewModel however it will not update.
Recipe.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="FitnessScript.Views.Recipes">
<ContentPage.Content>
<StackLayout>
<Label Text="Please Enter Ingredients and Requirements!"
HorizontalOptions="Center"
VerticalOptions="Start" HorizontalTextAlignment="Center" TextType="Text"
Margin="0,20,0,0"
FontSize="25"/>
<Label Text="Enter Ingredients" Margin="5"/>
<Entry x:Name="Ingredients"
Text="{Binding Ingredients}"
Placeholder="Ingredients"
PlaceholderColor="LightGray" />
<Label Text="Enter Calories" Margin="5"/>
<Entry x:Name="Calories"
Text="{Binding Calories}"
Placeholder="Calories"
PlaceholderColor="LightGray" />
<Button x:Name="RecipeSearchBtn"
Text="Find Recipes"
Command="{Binding RequestRecipeCommand}" />
<ProgressBar x:Name="ProgressB"
Progress="{Binding ProgressValue}"
ProgressColor="Purple"
IsVisible="True"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Recipes.xmal.cs
namespace FitnessScript.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Recipes : ContentPage
{
RecipeSearchViewModel recipeSearchViewModel;
public Recipes()
{
recipeSearchViewModel = new RecipeSearchViewModel();
InitializeComponent();
BindingContext = recipeSearchViewModel;
}
}
}
RecipeSearchViewModel
namespace FitnessScript.ViewModels
{
public class RecipeSearchViewModel : BaseViewModel
{
private static readonly IRecipeService _recipeService = new RecipeService();
private readonly BackgroundWorker worker;
#region Getters/Setters
string _ingredients;
public string Ingredients
{
get { return _ingredients; }
set
{
_ingredients = value;
OnPropertyChanged("Ingredients");
}
}
int _calories;
public int Calories
{
get { return _calories; }
set
{
_calories = value;
OnPropertyChanged("Calories");
}
}
float _progressValue;
public float ProgressValue
{
get { return _progressValue; }
set
{
_progressValue = value;
OnPropertyChanged("ProgressValue");
}
}
#endregion
public RecipeSearchViewModel()
{
this.worker = new BackgroundWorker();
}
public Command RequestRecipeCommand
{
get
{
return new Command(async () => await RequestRecipe());
}
}
private async Task RequestRecipe()
{
await Task.Run(() =>
{
Device.BeginInvokeOnMainThread(() =>
{ ProgressValue = 1; }
);
});
List<string> ingredientsList = await _recipeService.GetRecipe(Ingredients, Calories);
App.Current.MainPage.DisplayAlert("Success", $"{Ingredients}, {Calories}", "Close");
}
}
}
I Have tired many different alternatives, such as setting ProgressValue to Double and Decimal, forcing the UI thread, with and without adding a parameter to OnPropertyChange(). I've attempted background works too, just nothing sadly.
I'm debugging using a S10+ via USB as I prefer it to emulation.
The overall aim is to press the RecipeSearchBtn, do the logic, and update the progress bar along with it, however for debugging purposes I just want to change the progress to 100% when the button command executes
Any help would be appreaciated, thanks
Also I have tried the Activity Indicator however similar issues, it never showed while debugging though my phone when setting the visibility ect to true through binding IsBool
About binding ActivityIndicator isvisible, I do one sample that you can take a look:
Please take a look the following code, ActivityIndicator display firstly, clicking button to load data, setting ActivityIndicator isVisible and IsRunning as false.
<StackLayout>
<Button
x:Name="btn1"
Command="{Binding command1}"
Text="load data" />
<ActivityIndicator
HeightRequest="50"
IsRunning="{Binding isvisible}"
IsVisible="{Binding isvisible}"
WidthRequest="50"
Color="Red" />
<ListView ItemsSource="{Binding students}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding name}" />
<Label Text="{Binding age}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
public partial class Page2 : ContentPage
{
public Page2()
{
InitializeComponent();
this.BindingContext = new studentviewmodel();
}
}
public class studentviewmodel:ViewModelBase
{
public ObservableCollection<studentmodel> students { get; set; }
public Command command1 { get; set; }
private bool _isvisible;
public bool isvisible
{
get { return _isvisible; }
set
{
_isvisible = value;
RaisePropertyChanged("isvisible");
}
}
public studentviewmodel()
{
command1 = new Command(loaddata);
isvisible = true;
students = new ObservableCollection<studentmodel>();
}
private async void loaddata()
{
//call service to do other something.
await Task.Delay(5000);
students.Add(new studentmodel() { name = "cherry", age = 29 });
students.Add(new studentmodel() { name = "barry", age = 30 });
students.Add(new studentmodel() { name = "annine", age = 15 });
isvisible = false;
}
}
public class studentmodel
{
public string name { get; set; }
public int age { get; set; }
}
The ViewModelBase is the class that implementing INotifyPropertyChanged, to notify data changed.
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 screenshot:
In our edit page, we have an issue to populate the value into Selected Item in picker and it won't select for some reason from the LoadCourses() or LoadRoundCategories() either.
Any ideas?
Here's the code:
ViewModel
public class EditGolfRoundViewModel : INotifyPropertyChanged
{
ApiServices _apiServices = new ApiServices();
private string _message;
private ObservableCollection<GolfCourse> _courses;
private ObservableCollection<GolfRoundCategory> _roundCategories;
private object_selectedGolfCourse;
private GolfRoundCategory _selectedGolfRoundCategory;
private GolfRound _golfRound;
public EditGolfRoundViewModel()
{
_selectedGolfCourse = new GolfCourse();
_selectedGolfRoundCategory = new GolfRoundCategory();
LoadCourses();
LoadRoundCategories();
}
public GolfRound GolfRound
{
get { return _golfRound; }
set
{
_golfRound = value;
OnPropertyChanged();
}
}
public string Message
{
get { return _message; }
set
{
_message = value;
OnPropertyChanged();
}
}
public ObservableCollection<GolfCourse> GolfCourses
{
get { return _courses; }
set
{
if (_courses != value)
{
_courses = value;
OnPropertyChanged();
}
}
}
public ObservableCollection<GolfRoundCategory> GolfRoundCategories
{
get { return _roundCategories; }
set
{
_roundCategories = value;
OnPropertyChanged();
}
}
public object SelectedGolfCourse
{
get { return _selectedGolfCourse; }
set
{
_selectedGolfCourse = value;
var golfCourse = _selectedGolfCourse as GolfCourse;
Guid tempGolfCourseID = golfCourse.GolfCourseID;
OnPropertyChanged("SelectedGolfCourse");
}
}
public GolfRoundCategory SelectedGolfRoundCategory
{
get { return _selectedGolfRoundCategory; }
set
{
_selectedGolfRoundCategory = value;
OnPropertyChanged();
}
}
public ICommand EditCommand
{
get
{
return new Command(async() =>
{
GolfRound.GolfCourseID = SelectedGolfCourse.GolfCourseID;
GolfRound.GolfCourse = SelectedGolfCourse;
GolfRound.GolfRoundCategoryID = SelectedGolfRoundCategory.GolfRoundCategoryID;
GolfRound.GolfRoundCategory = SelectedGolfRoundCategory;
GolfRound.LastModifiedUTC = System.DateTime.Now;
await _apiServices.PutGolfRoundAsync(GolfRound, Settings.AccessToken);
});
}
}
public ICommand DeleteCommand
{
get
{
return new Command(async () =>
{
await _apiServices.DeleteGolfRoundAsync(GolfRound.GolfRoundID, Settings.AccessToken);
});
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private async void LoadCourses()
{
GolfCourses = new ObservableCollection<GolfCourse>(await _apiServices.GetGolfCoursesAsync(Settings.AccessToken));
}
private async void LoadRoundCategories()
{
GolfRoundCategories = new ObservableCollection<GolfRoundCategory>(await _apiServices.GetGolfRoundCategoriesAsync(Settings.AccessToken));
}
}
View - XAML
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModels="clr-namespace:AthlosifyMobile.ViewModels.Golf"
x:Class="AthlosifyMobile.Views.EditGolfRoundPage">
<StackLayout Orientation="Vertical" VerticalOptions="Center" Spacing="30" Padding="30">
<Entry Text="{Binding GolfRound.Name}" Placeholder="name" FontSize="Default" />
<Entry Text="{Binding GolfRound.Notes}" Placeholder="notes" FontSize="Default" />
<Entry Text="{Binding GolfRound.DailyHandicap}" Placeholder="daily handicap" FontSize="Default" />
<Label Text="Date" />
<DatePicker Date="{Binding GolfRound.TeeOffUTC}"
Format="D"
Margin="30, 0, 0, 30" />
<Picker x:Name="pCourse" Title="Course" ItemsSource="{Binding GolfCourses}"
SelectedItem="{Binding SelectedGolfCourse, Mode=TwoWay}"
ItemDisplayBinding="{Binding Name}"></Picker>
<Entry Text="{Binding GolfRound.GolfCourse.Name}" Placeholder="selected golf course" FontSize="Default" />
<Picker x:Name="pCategory" Title="Category" ItemsSource="{Binding GolfRoundCategories}"
SelectedItem="{Binding SelectedGolfRoundCategory, Mode=TwoWay}"
ItemDisplayBinding="{Binding Name}"></Picker>
<Entry Text="{Binding SelectedGolfRoundCategory.Name}" Placeholder="selected round category" FontSize="Default" />
<Button Command="{Binding EditCommand}" Text="Edit Round" />
<Button Command="{Binding DeleteCommand}" Text="Delete Round" />
<Label Text="{Binding Message}" ></Label>
</StackLayout>
View - code behind
public partial class EditGolfRoundPage : ContentPage
{
public EditGolfRoundPage (GolfRound round)
{
var editGolfRoundViewModel = new EditGolfRoundViewModel();
editGolfRoundViewModel.GolfRound = round;
BindingContext = editGolfRoundViewModel;
InitializeComponent ();
//var editGolfRoundViewModel = new EditGolfRoundViewModel();
//editGolfRoundViewModel.GolfRound = round;
//editGolfRoundViewModel.SelectedGolfCourse = round.GolfCourse;
//BindingContext = editGolfRoundViewModel;
}
}
Implement IEquatable for class of property used in SelectedItem:
public class GolfCourse : IEquatable<GolfCourse>
{
...
public bool Equals(GolfCourse other)
{
if (other == null) return false;
return (this.Name.Equals(other.Name));
}
}
Usage, assuming ItemsSource contains an object with value of Name as shown below:
SelectedGolfCourse = new GolfCourse { Name = "Course 2" };
The following is true as of Xamarin Forms v4.7.
See if you are doing this:
<Picker x:Name="DefaultEntitlement" Title="Entitlement"
SelectedItem="{Binding SelectedOwnerEntitlement, Mode=TwoWay}"
ItemsSource="{Binding OwnerEntitlements, Mode=TwoWay}">
</Picker>
Instead of this:
<Picker x:Name="DefaultEntitlement" Title="Entitlement"
ItemsSource="{Binding OwnerEntitlements, Mode=TwoWay}"
SelectedItem="{Binding SelectedOwnerEntitlement, Mode=TwoWay}">
</Picker>
you are binding view model before Initialise page so that is wrong thing we can not bind data without Initialise page fro that you need to change code of xaml.cs like below
public EditGolfRoundPage (GolfRound round)
{
InitializeComponent ();
BindingContext = editGolfRoundViewModel;
BindingContext.GolfRound = round;
}
that will work for you
Happy Coding :)
Xaml
<Picker x:Name="ProductPicker" WidthRequest="220" HeightRequest="35" Title="Select" ItemsSource="{Binding ProductList}" SelectedItem="{Binding ProductSelected}" ItemDisplayBinding="{Binding ProductName}"> </Picker>
ViewModel
public List<ProductModel> ProductList { get; set; }
Populating Data in Datasource in Viewmodel
ProductList = Products.Result.ToList();
Getting Selected Data
private object _ProductSelected;
public object ProductSelected
{
get { return _ProductSelected; }
set
{
_ProductSelected = value;
ProductSelected_SelectedIndex.Execute(value);
OnPropertyChanged("ProductSelected"); //in case you are using MVVM Light
}
}
private Command ProductSelected_SelectedIndex
{
get
{
return new Command((e) =>
{
}}}
private object _CitySelectedFromList;
public object CitySelectedFromList
{
get { return _CitySelectedFromList; }
set
{
_CitySelectedFromList = value;
var cityid = _CitySelectedFromList as CityMasterModel;
tempcityids = Convert.ToInt32(cityid.Id);
}
}
Can you try once replacing your Viewmodel. I have changed the type from Object to actual type. Set the Default item while loading the items from endpoint.
public class EditGolfRoundViewModel : INotifyPropertyChanged
{
ApiServices _apiServices = new ApiServices();
private string _message;
private ObservableCollection<GolfCourse> _courses;
private ObservableCollection<GolfRoundCategory> _roundCategories;
private GolfCourse _selectedGolfCourse;
private GolfRoundCategory _selectedGolfRoundCategory;
private GolfRound _golfRound;
public EditGolfRoundViewModel()
{
LoadCourses();
LoadRoundCategories();
}
public GolfRound GolfRound
{
get { return _golfRound; }
set
{
_golfRound = value;
OnPropertyChanged();
}
}
public string Message
{
get { return _message; }
set
{
_message = value;
OnPropertyChanged();
}
}
public ObservableCollection<GolfCourse> GolfCourses
{
get { return _courses; }
set
{
if (_courses != value)
{
_courses = value;
OnPropertyChanged();
}
}
}
public ObservableCollection<GolfRoundCategory> GolfRoundCategories
{
get { return _roundCategories; }
set
{
_roundCategories = value;
OnPropertyChanged();
}
}
public GolfCourse SelectedGolfCourse
{
get { return _selectedGolfCourse; }
set
{
_selectedGolfCourse = value;
OnPropertyChanged("SelectedGolfCourse");
}
}
public GolfRoundCategory SelectedGolfRoundCategory
{
get { return _selectedGolfRoundCategory; }
set
{
_selectedGolfRoundCategory = value;
OnPropertyChanged();
}
}
public ICommand EditCommand
{
get
{
return new Command(async () =>
{
GolfRound.GolfCourseID = SelectedGolfCourse.GolfCourseID;
GolfRound.GolfCourse = SelectedGolfCourse;
GolfRound.GolfRoundCategoryID = SelectedGolfRoundCategory.GolfRoundCategoryID;
GolfRound.GolfRoundCategory = SelectedGolfRoundCategory;
GolfRound.LastModifiedUTC = System.DateTime.Now;
await _apiServices.PutGolfRoundAsync(GolfRound, Settings.AccessToken);
});
}
}
public ICommand DeleteCommand
{
get
{
return new Command(async () =>
{
await _apiServices.DeleteGolfRoundAsync(GolfRound.GolfRoundID, Settings.AccessToken);
});
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private async void LoadCourses()
{
GolfCourses = new ObservableCollection<GolfCourse>(await _apiServices.GetGolfCoursesAsync(Settings.AccessToken));
if (GolfCourses != null && GolfCourses.Count() > 0)
SelectedGolfCourse = GolfCourses[0];
}
private async void LoadRoundCategories()
{
GolfRoundCategories = new ObservableCollection<GolfRoundCategory>(await _apiServices.GetGolfRoundCategoriesAsync(Settings.AccessToken));
if (GolfRoundCategories != null && GolfRoundCategories.Count() > 0)
SelectedGolfRoundCategory = GolfRoundCategories[0];
}
}
You can try:
make sure your prop support INotifyPropertyChanged
make sure Selected Item variable has initial value
try debug your selected item variable, make sure has value
1. Initials
Take a look your code:
public EditGolfRoundViewModel()
{
_selectedGolfCourse = new GolfCourse();
_selectedGolfRoundCategory = new GolfRoundCategory();
LoadCourses();
LoadRoundCategories();
}
If you try to initial value Selected Item, don't do this:
_selectedGolfCourse = new GolfCourse();
_selectedGolfRoundCategory = new GolfRoundCategory();
let it null, is fine. You can do like this:
SelectedGolfRoundCategory = new GolfRoundCategory();
//or
SelectedGolfRoundCategory = dataFromAPI;
2. Assign
Take a look your code:
public ICommand EditCommand
{
get
{
return new Command(async() =>
{
GolfRound.GolfCourseID = SelectedGolfCourse.GolfCourseID;
GolfRound.GolfCourse = SelectedGolfCourse;
GolfRound.GolfRoundCategoryID = SelectedGolfRoundCategory.GolfRoundCategoryID;
GolfRound.GolfRoundCategory = SelectedGolfRoundCategory;
GolfRound.LastModifiedUTC = System.DateTime.Now;
await _apiServices.PutGolfRoundAsync(GolfRound, Settings.AccessToken);
});
}
}
You trying selected item variable insert into to object GolfRound, like this part:
GolfRound.GolfRoundCategoryID = SelectedGolfRoundCategory.GolfRoundCategoryID;
GolfRound.GolfRoundCategory = SelectedGolfRoundCategory;
Make sure you have INotifyPropertyChanged implement this model GolfRound for prop GolfRoundCategoryID and GolfRoundCategory. If not, it would not work. I have experience for this.
Hope this helpful.
I'm new in xamarin cross platform development in visual studio.
I want to display a list of items on the listView.
<?xml version="1.0" encoding="utf-8" ?>
x:Class="Envelope_Internal.MainAssign">
<ContentPage.BindingContext>
</ContentPage.BindingContext>
<ListView ItemsSource="{ Binding assignmentList }"
HasUnevenRows="True">
</ListView>
namespace Envelope_Internal
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainAssign : ContentPage
{
DataService dataService;
List<AssignListV> assignmentList;
public MainAssign()
{
InitializeComponent();
dataService = new DataService();
RefreshData();
}
async void RefreshData()
{
assignmentList = await dataService.GetAssignmentItemsAsync();
assignmentList.item;
}
}
}
namespace Envelope_Internal
{
public class DataService
{
HttpClient client = new HttpClient();
public DataService()
{
}
public async Task<List<AssignListV>> GetAssignmentItemsAsync()
{
try
{
var response = await client.GetStringAsync("https://munipoiapp.herokuapp.com/api/applications/New");
var assignmentItems = JsonConvert.DeserializeObject<List<AssignListV>>(response);
return assignmentItems;
}
catch (System.Exception exception)
{
return null;
}
}
}
}
Refer this link for showing data in a listview :
https://bsubramanyamraju.blogspot.in/2017/04/xamarinforms-consuming-rest-webserivce_17.html
You missing DataTemplate part in list and wrong using Binding.
From use Binding you can assing exemplar of ViewModel with BindingContext
<ListView
HasUnevenRows="True"
ItemsSource="{Binding ItemsSource}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Name}"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
public partial class MainAssign : ContentPage
{
public MainAssign()
{
InitializeComponent();
BindingContext = new MainAssignViewModel();
}
protected override async void OnAppearing() {
base.OnAppearing();
await (BindingContext as MainAssignViewModel)?.LoadData();
}
}
public class MainAssignViewModel:INotifyPropertyChanged {
List<AssignListModel> _assignmentList;
public MainAssignViewModel() {
_dataService = new DataService();
}
public List<AssignListModel> AssignmentList {
get { return _assignmentList; }
set {
_assignmentList = value;
OnPropertyChanged(nameof(AssignmentList));
}
}
readonly DataService _dataService;
public async Task LoadData() {
AssignmentList = await _dataService.GetAssignmentItemsAsync();
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
I am trying to change the source property of the frame in Page1.xaml when the SampleCommand is excecuted.
How do I acheive this in the View Model?
Page1.xaml:
<r:RibbonTab.Groups>
<r:RibbonGroup GroupSizeDefinitions="{StaticResource RibbonLayout}">
<r:RibbonGroup.Command>
<r:RibbonCommand LabelTitle="RibbonButton"/>
</r:RibbonGroup.Command>
<r:RibbonButton x:Name="RibbonButton1" Command="{Binding Path=SampleCommand}"/>
</r:RibbonGroup>
</r:RibbonTab.Groups>
</r:RibbonTab>
</r:Ribbon>
<Border Name="PageBorder" Grid.Row="0" Grid.Column="1">
<Frame Name="pageFrame" Source="FirstPage.xaml" />
</Border>
</DockPanel>
c#
Page1ViewModel.cs:
RelayCommand _sampleCommand;
public ICommand SampleCommand
{
get
{
// create command ??
return _sampleCommand
}
page1.xaml.cs :
Page1ViewModel pageViewModel;
this.DataContext = pageViewModel; // when pageloads
Have you tried to use is this way?
public class ViewModel{
private SimpleCommand divertCommand;
public ViewModel()
{
testCommand = new SimpleCommand
{
CanExecuteDelegate = x => true,
ExecuteDelegate = x => ExecuteCommand()
};
}
public SimpleCommand DivertCommand
{
get { return divertCommand; }
}
private void ExecuteCommand()
{
DivertCommand.CommandSucceeded = false;
//Your code to execute
DivertCommand.CommandSucceeded = true;
}}
}
please use this project as a reference: link
there is a nice thread here
Good luck
Ric