Xamarin Forms Binding with namespace declaration error - c#

I'm new to Xamarin and I'm trying to bind my ViewModel to the View but I couldn't do it yet.
Here's the code.
(Model)
namespace CadastroProdutos
{
public class Produto
{
public string Codigo { get; set; }
public string Identificacao { get; set; }
public string Tipo { get; set; }
}
}
(Observable Model)
namespace CadastroProdutos
{
public class ObservableProduto : INotifyPropertyChanged
{
Produto produto;
public ObservableProduto()
{
}
public event PropertyChangedEventHandler PropertyChanged;
public string Codigo
{
set
{
if (!value.Equals(produto.Codigo, StringComparison.Ordinal))
{
produto.Codigo = value;
OnPropertyChanged("Codigo");
}
}
get
{
return produto.Codigo;
}
}
public string Identificacao
{
set
{
if (!value.Equals(produto.Identificacao, StringComparison.Ordinal))
{
produto.Identificacao = value;
OnPropertyChanged("Identificacao");
}
}
get
{
return produto.Identificacao;
}
}
public string Tipo
{
set
{
if (!value.Equals(produto.Tipo, StringComparison.Ordinal))
{
produto.Tipo = value;
OnPropertyChanged("Tipo");
}
}
get
{
return produto.Tipo;
}
}
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler == null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
(ViewModel)
namespace CadastroProdutos
{
public class ListProdutoViewModel
{
ObservableCollection<ObservableProduto> produtos;
public ListProdutoViewModel()
{
produtos = new ObservableCollection<ObservableProduto>();
}
public ObservableCollection<ObservableProduto> Produtos
{
set
{
if (value != produtos)
{
produtos = value;
}
}
get
{
return produtos;
}
}
}
}
(View)
<?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:CadastroProdutos;assembly=CadastroProdutos"
x:Class="CadastroProdutos.ListProduto"
Title="Listagem de Produtos">
<ContentPage.Content>
<ListView x:Name="listView" Margin="20,40,20,20" ItemsSource="{Binding Produtos}">
<ListView.BindingContext>
<local:ListProdutoViewModel />
</ListView.BindingContext>
<ListView.Header>
<StackLayout Orientation="Vertical" >
<Label Text="Produtos" HorizontalOptions="Center"/>
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal" >
<TextCell Text="{Binding Identificacao}"/>
</StackLayout>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
Getting an error "Xamarin.Forms.Xaml.XamlParseException Position 10:6. Type local:ListProdutoViewModel not found in xmlns clr-namespace:CadastroProdutos;assembly=CadastroProdutos".
What am I missing on the namespace declaration?
Thanks in advance.

Ensure that whether ListProdutoViewModel is deifined under the namespace - CadastroProdutos.
Also, you no need to mention the assembly there in, local: assembly=CadastroProdutos. So try to run the application after removing the above assembly code. Like as below,
local="clr-namespace:CadastroProdutos"

Related

Xamarin list of RadioBox set GroupName from view model

All the examples for RadioButtons I've found so far have the values hard-coded in the xaml for the page. I'm looking to feed a list of strings (for now) from a database and running into an issue with the GroupName.
My data template for a radio display type:
<DataTemplate x:Key="RadioTemplate">
<StackLayout>
<Label
Text="{Binding Name}"
Style="{StaticResource LabelStyle}">
</Label>
<ListView ItemsSource="{Binding Choices.Choices}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<RadioButton Value="{Binding}"
Content="{Binding}"
GroupName="someGroupName"
CheckedChanged="OnRadioChanged">
</RadioButton>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</DataTemplate>
MainPageViewModel.cs
using System;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Xamarin.Forms;
using FieldDataTemplateSelectorSample.Validations;
namespace FieldDataTemplateSelectorSample
{
public class MainPageViewModel : ValidationViewModelBase
{
public MainPageViewModel()
{
_fields = new ObservableCollection<FieldViewModel>();
}
private ObservableCollection<FieldViewModel> _fields;
public ObservableCollection<FieldViewModel> Fields
{
get { return _fields; }
set
{
_fields = value;
RaisePropertyChanged();
}
}
private bool _showValidationSummary;
public bool ShowValidationSummary
{
get { return _showValidationSummary; }
set
{
_showValidationSummary = value;
RaisePropertyChanged();
}
}
ICommand _submitCommand;
public ICommand SubmitCommand
{
get => _submitCommand ?? (_submitCommand = new Command(ValidateAndSave));
}
private void ValidateAndSave(object obj)
{
ValidateAll();
if (ErrorStateManager.HasError)
{
ShowValidationSummary = true;
}
else
{
ShowValidationSummary = false;
}
}
}
}
using System.Collections.Generic;
using Xamarin.Forms;
using FieldDataTemplateSelectorSample.Validations;
namespace FieldDataTemplateSelectorSample
{
public class FieldViewModel : ValidationViewModelBase
{
public FieldViewModel()
{
_choices = new ChoiceViewModel();
}
private string _value;
public long Id { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public string Code { get; set; }
public string Value
{
get
{
return _value;
}
set
{
_value = value;
RaisePropertyChanged();
Validate();
}
}
public string PlaceholderText { get; set; }
public int SortOrder { get; set; }
public string DisplayType { get; set; }
public bool IsReadOnly { get; set; }
public bool IsEnabled { get; set; }
private ChoiceViewModel _choices;
public ChoiceViewModel Choices
{
get
{
return _choices;
}
set
{
_choices = value;
RaisePropertyChanged();
}
}
void OnChoicesRadioButtonCheckedChanged(object sender, CheckedChangedEventArgs e)
{
// what else do we need to do? Update value?
RaisePropertyChanged();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace FieldDataTemplateSelectorSample
{
public class ChoiceViewModel
{
public ChoiceViewModel()
{
Choices = new List<string>();
}
public string Code { get; set; }
public List<string> Choices { get; set; }
}
}
As long as I hard-code the GroupName for the RadioButton in the ViewCell, everything works but that I'll end up with one group name for every single radio button on the page. I've tried adding the property to the StackLayout in the template:
<StackLayout RadioButtonGroup.GroupName="someGroup">
and taking it out out of the RadioButton but when I put a breakpoint in OnRadioChanged, the GroupName comes in as null.
I'd like to use the Code property in the ChoiceViewModel as the group name but haven't gotten the relative binding correct yet. Any help with the binding or different way to do the DataTemplate is appreciated.
you could use a bindable StackLayout which will give you more control over the containter
<StackLayout>
<Label Text="{Binding Name}" Style="{StaticResource LabelStyle}" />
<StackLayout RadioButtonGroup.GroupName="{Binding Name}"
BindableLayout.ItemsSource="{Binding Choices.Choices}" >
<BindableLayout.ItemTemplate>
<DataTemplate>
<ViewCell>
<RadioButton Value="{Binding}" Content="{Binding}"
CheckedChanged="OnRadioChanged" />
</ViewCell>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>

Xamarin.Forms Update Binding Label inside CarouselView

I have this label like so:
<Label x:Name="QuestionText" FontSize="62" Text="{Binding question}" HorizontalTextAlignment="Center" Padding="0,20,0,0" />
This is inside a CarouselView:
<CarouselView
x:Name="Questions"
HeightRequest="475">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout HorizontalOptions="Center" Padding="10">
<Label x:Name="QuestionText" FontSize="62" Text="{Binding question}" HorizontalTextAlignment="Center" Padding="0,20,0,0" />
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
And I am populating the CarouselView like so:
protected override async void OnAppearing()
{
base.OnAppearing();
questions = await webService.GetTaskQuestions(taskcategory);
List<QuestionsClass> currentPage = new List<QuestionsClass>();
currentPage.Add(questions[currentPageIndex]);
Questions.ItemsSource = currentPage;
}
And I am trying to update my text like so:
questions[currentPageIndex].question = questions[currentPageIndex].question.Replace("_", questions[currentPageIndex].answer);
I have even tried:
Device.BeginInvokeOnMainThread(() =>
{
questions[currentPageIndex].question = questions[currentPageIndex].question.Replace("_", questions[currentPageIndex].answer);
});
And still nothing, here is my class:
public class QuestionsClass
{
public string question { get; set; }
public string answer { get; set; }
}
How do I update a label inside a CarouselView?
UPDATE
I have tried with INotifyPropertyChanged:
public class QuestionsClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string question { get; set; }
public string actualQuestion
{
get
{
return question;
}
set
{
question = value;
OnPropertyChanged();
}
}
public string answer { get; set; }
protected void OnPropertyChanged([CallerMemberName] string quetion = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(question));
}
}
Here is my label:
<Label FontSize="62" Text="{Binding actualQuestion}" HorizontalTextAlignment="Center" Padding="0,20,0,0" />
and here is how I am updating it:
questions[currentPageIndex].question = questions[currentPageIndex].question.Replace("_", questions[currentPageIndex].answer);
UPDATE
My class was wrong, this is the correct class and is now working:
public class QuestionsClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _question;
public string question {
get
{
return _question;
}
set
{
_question = value;
NotifyPropertyChanged("question");
}
}
public string answer { get; set; }
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

after implementing iNotifypropertychanged in ViewModel SelectedItem is not working on listview

Hello I am using MVVM in Xamarin Forms. I am trying to Bind my Listview's SeletedItem to my ViewModel. I binded it and worked fine. but when i have implemented INotifyPropertyChanged to update the view for some other component it stopped working.
I want it to work even INotifyPropertyChanged is implemented in my ViewModel. I am figuring out the problem why its happened. I searched on internet and Xamarin's documentation and could not find the reason.
My View
<ListView ItemsSource="{Binding PersonsList}"
CachingStrategy="RecycleElement"
HasUnevenRows="True"
SelectionMode="None"
SelectedItem="{Binding SelectedPerson}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="5">
<Label Text="{Binding FullName}"
FontSize="Medium"
TextColor="Orange"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ViewModel
public class PersonViewModel : INotifyPropertyChanged
{
public PersonViewModel()
{
PersonsList = new ObservableCollection<User>
{
new User(){ UserId = 1, FullName = "John" },
new User(){ UserId = 2, FullName = "Alex" },
new User(){ UserId = 3, FullName = "Ellen" },
new User(){ UserId = 4, FullName = "Grace" }
};
}
public ObservableCollection<User> PersonsList { get; set; }
private User _selectedPerson { get; set; }
public User SelectedPerson
{
get { return _selectedPerson; }
set
{
if (_selectedPerson != value)
{
_selectedPerson = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Model
public class User
{
public int UserId { get; set; }
public string FullName { get; set; }
}
Hope to get some useful advice.
Change your SelectedPerson property to call OnPropertyChanged().
private User _selectedPerson { get; set; }
public User SelectedPerson
{
get { return _selectedPerson; }
set
{
if (_selectedPerson != value)
{
_selectedPerson = value;
OnPropertyChanged();
}
}
}

Xamarin Forms Binding not showing on ListView

I'm new to Xamarin and I'm trying to bind my ViewModel to the View but I couldn't do it yet.
Here's the code.
(Model)
namespace CadastroProdutos
{
public class Produto
{
public string Codigo { get; set; }
public string Identificacao { get; set; }
public string Tipo { get; set; }
}
}
(Observable Model)
namespace CadastroProdutos
{
public class ObservableProduto : INotifyPropertyChanged
{
Produto produto;
public ObservableProduto()
{
produto = new Produto()
{
Identificacao = "Primeiro",
Codigo = "123456"
};
produto = new Produto()
{
Identificacao = "Segundo",
Codigo = "123456"
};
produto = new Produto()
{
Identificacao = "Terceiro",
Codigo = "123456"
};
}
public event PropertyChangedEventHandler PropertyChanged;
public string Codigo
{
set
{
if (!value.Equals(produto.Codigo, StringComparison.Ordinal))
{
produto.Codigo = value;
OnPropertyChanged("Codigo");
}
}
get
{
return produto.Codigo;
}
}
public string Identificacao
{
set
{
if (!value.Equals(produto.Identificacao, StringComparison.Ordinal))
{
produto.Identificacao = value;
OnPropertyChanged("Identificacao");
}
}
get
{
return produto.Identificacao;
}
}
public string Tipo
{
set
{
if (!value.Equals(produto.Tipo, StringComparison.Ordinal))
{
produto.Tipo = value;
OnPropertyChanged("Tipo");
}
}
get
{
return produto.Tipo;
}
}
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler == null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
(ViewModel)
namespace CadastroProdutos
{
public class ListProdutoViewModel
{
ObservableCollection<ObservableProduto> produtos;
public ListProdutoViewModel()
{
produtos = new ObservableCollection<ObservableProduto>();
}
public ObservableCollection<ObservableProduto> Produtos
{
set
{
if (value != produtos)
{
produtos = value;
}
}
get
{
return produtos;
}
}
}
}
(View)
<?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:CadastroProdutos;"
x:Class="CadastroProdutos.ListProduto"
Title="Listagem de Produtos">
<ContentPage.Content>
<ListView x:Name="listView" Margin="20,40,20,20" ItemsSource="{Binding Produtos}">
<ListView.BindingContext>
<local:ListProdutoViewModel />
</ListView.BindingContext>
<ListView.Header>
<StackLayout Orientation="Vertical" >
<Label Text="Produtos" HorizontalOptions="Center"/>
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal" >
<TextCell Text="{Binding Identificacao}"/>
</StackLayout>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
It not worked, It didn't show those elements on the list. Can someone help me?
Thanks in advance.
You're not quite understanding the MVVM approach, but you're almost there. You don't need to have the ObservableProduto class. You can make your Produto class your model.
This is your Produto model. I went ahead and changed it up for you.
namespace CadastroProdutos
{
public class Produto : INotifyPropertyChanged
{
private string codigo;
public string Codigo
{
get {return codigo;}
set {codigo=value; OnPropertyChanged(); }
}
private string identificacao;
public string Identificacao
{
get {return identificacao;}
set {identificacao=value; OnPropertyChanged(); }
}
private string tipo ;
public string Tipo
{
get {return tipo;}
set {tipo=value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName]string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
You should contain an ObservableCollection of your Produtos in a viewmodel. I see you've done that. I've edited it a bit. You may need to be careful about totally resetting your ObservableCollection on a set.
namespace CadastroProdutos
{
public class ListProdutoViewModel
{
ObservableCollection<Produto> produtos;
public ListProdutoViewModel()
{
produtos = new ObservableCollection<Produto>();
}
public ObservableCollection<Produto> Produtos
{
set
{
if (value != produtos)
{
produtos = value;
}
}
get
{
return produtos;
}
}
}
}
Note: you will need to add items to your ObservableColleciton still.

Xamarin Set Binding of EntryCell

I want to save the values that a user enters in the placeholder of an EntryCell using MVVM.
This is part of my .xaml
<TableView>
<TableView.Root>
<TableSection>
<EntryCell x:Name="HomeEC"
Label="HomeTeam"
Placeholder="{Binding Home, Mode=TwoWay}"
>
</EntryCell>
<EntryCell x:Name="AwayEC"
Label="AwayTeam"
Placeholder="{Binding Away, Mode=TwoWay}"
>
</EntryCell>
<EntryCell x:Name="BetEC"
Label="BetTeam"
Placeholder="{Binding Bet, Mode=TwoWay}"
>
</EntryCell>
<EntryCell x:Name="TypeEC"
Label="BetType"
Placeholder="{Binding Type, Mode=TwoWay}"
>
</EntryCell>
<EntryCell x:Name="OddEC"
Label="Odd"
Placeholder="{Binding Odd, Mode=TwoWay}"
>
</EntryCell>
</TableSection>
</TableView.Root>
</TableView>
And this is my ViewModel class
public string Home
{
set
{
home = value;
OnPropertyChanged("Home");
newMatch.HomeTeam = home;
}
}
public string Away
{
set
{
away = value;
OnPropertyChanged("Away");
newMatch.AwayTeam = away;
}
}
public string Bet
{
set
{
bet = value;
OnPropertyChanged("Bet");
newMatch.Bet = bet;
}
}
public string Type
{
set
{
type = value;
OnPropertyChanged("Type");
newMatch.BetType = type;
}
}
public string Odd
{
set
{
odd = value;
OnPropertyChanged("Odd");
newMatch.Odd = Decimal.Parse(odd);
}
}
public ICommand InsertBet;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
When I enter my values in the field in the UI, they do not get saved here in the VM. What am I doing wrong?
Thanks,
Dragos
InsertMatchVM.cs
public class InsertMatchVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string home, away, bet;
public Match newMatch = new Match();
public string Home
{
set
{
home = value;
OnPropertyChanged("Home");
newMatch.HomeTeam = home;
}
get
{
return home;
}
}
public string Away
{
set
{
away = value;
OnPropertyChanged("Away");
newMatch.AwayTeam = away;
}
get
{
return away;
}
}
public string Bet
{
set
{
bet = value;
OnPropertyChanged("Bet");
newMatch.Bet = bet;
}
get
{
return bet;
}
}
public ICommand InsertBet;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
}
Page1.Xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App2;assembly=App2"
x:Class="App2.Page1">
<ContentPage.BindingContext>
<local:InsertMatchVM/>
</ContentPage.BindingContext>
<TableView>
<TableView.Root>
<TableSection>
<EntryCell x:Name="HomeEC"
Label="HomeTeam"
Text="{Binding Home, Mode=TwoWay}"
Placeholder="Home"
>
</EntryCell>
<EntryCell x:Name="AwayEC"
Label="AwayTeam"
Text="{Binding Away, Mode=TwoWay}"
Placeholder="Away"
>
</EntryCell>
<EntryCell x:Name="BetEC"
Label="BetTeam"
Text="{Binding Bet, Mode=TwoWay}"
Placeholder="Bet"
>
</EntryCell>
</TableSection>
</TableView.Root>
</TableView>
</ContentPage>
App.cs
public class App : Application
{
public App()
{
MainPage = new Page1();
}
}
Match.cs
public class Match
{
public string HomeTeam { get; set; }
public string AwayTeam { get; set; }
public string Bet { get; set; }
}

Categories