How call OnPropertyChanged in double embedded data in xamarin? - xamarin.forms

I have a Content page, which contain CollectionView inside CarouselView.
First time when the page is loading the double embedded binding is work fine. Show everithing correctly.
But when i try to change embedded property value nothing happen. How update these properties?
formChooseElement.formViewerElements[0].formViewerElementAnswares[0].color=Color.Green;
Like:
<CarouselView ItemsSource="{Binding formViewerElements}">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding text}" />
<CollectionView ItemsSource="{Binding formViewerElements}" >
<CollectionView.ItemTemplate>
<DataTemplate >
<StackLayout BackgroundColor="{Binding color}">
<Label Text="{Binding text}" >
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
BindingContext in code behind:
this.BindingContext = new FormViewerViewModell();
ViewModell:
public class FormViewerViewModell : INotifyPropertyChanged
{
public FormViewerViewModell()
{
GenerateData
}
private FormChooseElement FormChooseElement;
public FormChooseElement formChooseElement
{
get => FormChooseElement;
set
{
FormChooseElement = value;
OnPropertyChanged(nameof(FormChooseElement));
}
}
public ObservableCollection<FormViewerElement> formViewerElements
{
get => formChooseElement.formViewerElements;
set
{ formChooseElement.formViewerElements = value;
OnPropertyChanged(nameof(formChooseElement.formViewerElements));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
FormChooseElement
public class FormChooseElement
{
public ...
public ObservableCollection<FormViewerElement> formViewerElements { get; set; }
}
FormViewerElement
public class FormViewerElement
{
public ...
public ObservableCollection<FormViewerElementAnsware> formViewerElementAnswares { get; set; }
}
FormViewerElementAnsware
public class FormViewerElementAnsware
{
public ...
public Color color { get; set; };

Related

How a user select to display 1 out of two (or more) fields on a single Label in Xamarin

I'm trying to use a single Label to display one of the two data fields alternately in Xamarin Forms. Only Label 1 Displaying the binding field (Contact_Name), while second Label which I am trying to use a variable "DisplayField" is not displaying either 'Contact_Address' or 'Contact_eMail' .
Question posted before and Another user tried to help but it didn't work!
Model Class
public class Contacts
{
[PrimaryKey][Autoincrement]
public int Contact_ID { get; set; }
public string Contact_Name { get; set; }
public string Contact_Address { get; set; }
public string Contact_eMail { get; set; }
}
XAML Page
<StackLayout>
<Button Text="Display Address" FontSize="Large" HorizontalOptions="Center" VerticalOptions="Fill" Clicked="Display_Address" />
<Button Text="Display Email" FontSize="Large" HorizontalOptions="Center" VerticalOptions="Fill" Clicked="Display_eMail" />
<Entry HorizontalOptions="FillAndExpand" Text="{Binding DisplayField}" />
<ListView x:Name="listView" HasUnevenRows="True" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<StackLayout Orientation="Vertical" VerticalOptions="CenterAndExpand" >
<Frame >
<StackLayout Orientation="Vertical" VerticalOptions="Center">
<Label Text="{Binding Contact_Name}" FontSize="Medium" LineBreakMode="WordWrap" />
<Label Text="{Binding DisplayField}" LineBreakMode="WordWrap" />
</StackLayout>
</Frame>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
Code Behind
public partial class FieldSwap : ContentPage
{
readonly FieldViewModel _fieldViewModel;
readonly SQLiteAsyncConnection _connection = DependencyService.Get<ISQLite>().GetConnection();
public ObservableCollection<Contacts> CList { get; set; }
public static string DisplayField { get; private set; }
public static int caseSwitch { get; private set; }
public FieldSwap()
{
InitializeComponent();
_fieldViewModel = new FieldViewModel();
_fieldViewModel.Field = "Contact_Address";
this.BindingContext = _fieldViewModel;
}
public static void SelectField()
{
switch (caseSwitch)
{
case 1:
DisplayField = "Contact_Address";
break;
case 2:
DisplayField = "Contact_eMail";
break;
default:
DisplayField = ("Contact_Address");
break;
}
}
private void Display_Address(object sender, EventArgs e)
{
caseSwitch = 1;
SelectField();
ReadData();
}
private void Display_eMail(object sender, EventArgs e)
{
caseSwitch = 2;
SelectField();
ReadData();
}
public void ReadData()
{
var list = _connection.Table<Contacts>().ToListAsync().Result;
CList = new ObservableCollection<Contacts>(list);
listView.ItemsSource = CList;
}
}
View Model Class
public class FieldViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
String _field;
public string Field
{
set
{
if (!value.Equals(_field, StringComparison.Ordinal))
{
_field = value;
OnPropertyChanged("DisplayField");
}
}
get
{
return _field;
}
}
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new
PropertyChangedEventArgs(propertyName));
}
}
You could use IsVisible property to achieve that, not need to bind only one lable.
Therefore, binding Contact_Address and Contact_eMail with two lables in StackLayout as follows:
<StackLayout Orientation="Vertical" VerticalOptions="Center">
<Label Text="{Binding Contact_Name}" FontSize="Medium" LineBreakMode="WordWrap" />
<Label Text="{Binding Contact_Address}" IsVisible="{Binding AddressVisible}" LineBreakMode="WordWrap" />
<Label Text="{Binding Contact_eMail}" IsVisible="{Binding EMailVisible}" LineBreakMode="WordWrap" />
</StackLayout>
Then in Contacts add two visiable proerty:
public class Contacts: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
...
private bool addressVisible;
public bool AddressVisible
{
set
{
if (addressVisible != value)
{
addressVisible = value;
OnPropertyChanged("AddressVisible");
}
}
get
{
return addressVisible;
}
}
private bool eMailVisible;
public bool EMailVisible
{
set
{
if (eMailVisible != value)
{
eMailVisible = value;
OnPropertyChanged("EMailVisible");
}
}
get
{
return eMailVisible;
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Now in Contentpage, you could modify the visiable propery when button be clicked:
private void Display_Address(object sender, EventArgs e)
{
foreach(var item in CList )
{
item.AddressVisible = true;
item.EMailVisible = false;
}
}
private void Display_eMail(object sender, EventArgs e)
{
foreach (var item in CList )
{
item.AddressVisible = false;
item.EMailVisible = true;
}
}
Here is the effect:

A Single Label can display 2 Data fields alternately select by user

I'm trying to use a single Label to display one of the two data fields alternately in Xamarin Forms. Only Label 1 Display the binding field and second Label which I am trying to use a variable "DisplayField" is not displaying either 'Contact_Address' or 'Contact_eMail'
Model class
public class Contacts
{
[PrimaryKey][Autoincrement]
public int Contact_ID { get; set; }
public string Contact_Name { get; set; }
public string Contact_Address { get; set; }
public string Contact_eMail { get; set; }
public string DisplayField { get; set; }
}
XAML page
<StackLayout>
<Button Text="Display Address" FontSize="Large" HorizontalOptions="Center" VerticalOptions="Fill" Clicked="Display_Address" />
<Button Text="Display Email" FontSize="Large" HorizontalOptions="Center" VerticalOptions="Fill" Clicked="Display_eMail" />
<Entry HorizontalOptions="FillAndExpand" Text="{Binding DisplayField}" />
<ListView x:Name="listView" HasUnevenRows="True" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<StackLayout Orientation="Vertical" VerticalOptions="CenterAndExpand" >
<Frame >
<StackLayout Orientation="Vertical" VerticalOptions="Center">
<Label Text="{Binding Contact_Name}" FontSize="Medium" LineBreakMode="WordWrap" />
<Label Text="{Binding DisplayField}" LineBreakMode="WordWrap" />
</StackLayout>
</Frame>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
Code behind
public partial class FieldSwap : ContentPage
{
readonly FieldViewModel _fieldViewModel;
readonly SQLiteAsyncConnection _connection = DependencyService.Get<ISQLite>().GetConnection();
public ObservableCollection<Contacts> CList { get; set; }
public static string DisplayField { get; private set; }
public static int caseSwitch { get; private set; }
public FieldSwap()
{
InitializeComponent();
_fieldViewModel = new FieldViewModel();
_fieldViewModel.Field = "Contact_Address";
this.BindingContext = _fieldViewModel;
}
public static void SelectField()
{
switch (caseSwitch)
{
case 1:
DisplayField = "Contact_Address";
break;
case 2:
DisplayField = "Contact_eMail";
break;
default:
DisplayField = ("Contact_Address");
break;
}
}
private void Display_Address(object sender, EventArgs e)
{
caseSwitch = 1;
SelectField();
ReadData();
}
private void Display_eMail(object sender, EventArgs e)
{
caseSwitch = 2;
SelectField();
ReadData();
}
public void ReadData()
{
var list = _connection.Table<Contacts>().ToListAsync().Result;
CList = new ObservableCollection<Contacts>(list);
listView.ItemsSource = CList;
}
}
View model class
public class FieldViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
String _field;
public string Field
{
set
{
if (!value.Equals(_field, StringComparison.Ordinal))
{
_field = value;
OnPropertyChanged("DisplayField");
}
}
get
{
return _field;
}
}
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new
PropertyChangedEventArgs(propertyName));
}
}
Screen Shot
Screen Shot 2
If you want to display different value in ListView by user selected, I suggest you can use Picker to choose, I do one sample that you can take a look.
<ContentPage.Content>
<StackLayout>
<Picker x:Name="choose" SelectedIndexChanged="choose_SelectedIndexChanged">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Contact_Address</x:String>
<x:String>Contact_eMail</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
<ListView
x:Name="listview1"
HasUnevenRows="True"
ItemsSource="{Binding items}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" VerticalOptions="Center">
<Label
FontSize="Medium"
LineBreakMode="WordWrap"
Text="{Binding Contact_Name}" />
<Label
IsVisible="{Binding Source={x:Reference root}, Path=BindingContext.selectedm}"
LineBreakMode="WordWrap"
Text="{Binding Contact_eMail}" />
<Label
IsVisible="{Binding Source={x:Reference root}, Path=BindingContext.selecteda}"
LineBreakMode="WordWrap"
Text="{Binding Contact_Address}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
public partial class Page31 : ContentPage, INotifyPropertyChanged
{
public ObservableCollection<Contacts> items { get; set; }
private Boolean _selecteda;
public Boolean selecteda
{
get { return _selecteda; }
set
{
_selecteda = value;
RaisePropertyChanged("selecteda");
}
}
private Boolean _selectedm;
public Boolean selectedm
{
get { return _selectedm; }
set
{
_selectedm = value;
RaisePropertyChanged("selectedm");
}
}
public Page31()
{
InitializeComponent();
items = new ObservableCollection<Contacts>();
for(int i=0;i<20;i++)
{
Contacts contact = new Contacts()
{
Contact_ID = i, Contact_Name = "cherry " + i, Contact_Address = "the street " + i, Contact_eMail = "cherry#outlook.com "+i
};
items.Add(contact);
}
this.BindingContext = this;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
private void choose_SelectedIndexChanged(object sender, EventArgs e)
{
var picker = (Picker)sender;
int selectedIndex = picker.SelectedIndex;
if (selectedIndex ==0)
{
selecteda = true;
selectedm = false;
}
else
{
selectedm = true;
selecteda = false;
}
}
}

Content disappears when adding a DataTemplate to a ContentPage in Xamarin Forms

I have a simple ContentPage with a StackLayout and a child ScrollView. As soon as I add an Items Template and DataTemplate to the page, all other content disappears, even content, such as a Label, that doesn't even use the data from the bound data source.
<ContentPage.Content>
<StackLayout>
<!-- Body -->
<ScrollView>
<StackLayout BindableLayout.ItemsSource="{Binding IdCardCollection }">
<BindableLayout.ItemTemplate>
<DataTemplate>
<!--<Label Text="{Binding IdCard.StateTerritoryCardTitle}" />-->
<Label Text="Test" />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ScrollView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
public partial class TestBinding : ContentPage
{
public TestBinding()
{
InitializeComponent();
BindingContext = new TestIdCardViewModel(1);
}
}
public class TestIdCardViewModel : BaseViewModel
{
private IList<IdCard> _idCards;
public ObservableCollection<IdCard> IdCardCollection { get; private set; }
public IdCard IdCard { get; private set; }
public TestIdCardViewModel()
{
}
public TestIdCardViewModel(int maxListItems) : base(maxListItems)
{
_idCards = new List<IdCard>();
CreateIdCardCollection(MaxListObjects);
}
private void CreateIdCardCollection(int maxListObjects)
{
_idCards.Add(new IdCard {StateTerritoryCardTitle = "Illinois - Proof of Auto Insurance" });
IdCardCollection = new ObservableCollection<IdCard>(_idCards);
IdCard = IdCardCollection.First();
}
}
public class BaseViewModel
{
public int MaxListObjects { get; set; } = (int) NGICConstants.MaxListItems;
public BaseViewModel()
{
}
public BaseViewModel(int maxListItems)
{
// Save the List count limit.
MaxListObjects = maxListItems;
}
}
No matter if I use the bound object or not, the Label does not appear. What am I doing wrong?

SelectedItem binding works in UWP but not in ios

In my Xamarin.Forms app, I have a ListView and am binding to the SelectedItem property:
<ListView x:Name="MyListView" ItemsSource="{Binding MyItems}" IsVisible="{Binding Expanded}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" SelectionMode="Single" SeparatorVisibility="None">
<!-- not relevant code -->
</ListView>
When I run it on UWP, my SelectedItem property in my view model gets set when I select an item in the list. But not in ios. Am I doing something wrong? Or is there a work around?
I wrote a simple demo and it works on my side. Here is the code:
<ListView x:Name="testListView"
Style="{StaticResource ListStyle}" SelectedItem="{Binding YourSelectedItem, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding Name}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Then in your view-model(viewModel should implement INotifyPropertyChanged):
class testViewModel : INotifyPropertyChanged
{
public string Name { get; set; }
private testViewModel _yourSelectedItem { get; set; }
public testViewModel YourSelectedItem
{
get
{
return _yourSelectedItem;
}
set
{
_yourSelectedItem = value;
OnPropertyChanged("YourSelectedItem");
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
And in the MainPage, set the BindingContext = new testViewModel();:
public partial class MainPage : ContentPage
{
ObservableCollection<testViewModel> myModels = new ObservableCollection<testViewModel>();
testViewModel model;
public MainPage()
{
InitializeComponent();
myModels.Add(new testViewModel { Name = "age" });
myModels.Add(new testViewModel { Name = "gender" });
myModels.Add(new testViewModel { Name = "name" });
testListView.ItemsSource = myModels;
BindingContext = new testViewModel();
}
}
Try it and let me know if it works for you.

Showing Empty Screen in FlowListView in Xaml Xamarin.Forms

How to do FlowListView in XAML Xamarin.Forms?
Here is my Code:
XAML:
<flv:FlowListView FlowColumnCount="3" SeparatorVisibility="None" HasUnevenRows="true" x:Name="grid_list" ItemsSource="{Binding list_grid}" HeightRequest="100" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<flv:FlowListView.FlowColumnTemplate>
<DataTemplate>
<Image Source="{Binding Image}" Margin="20" VerticalOptions="Fill" HorizontalOptions="Fill" XAlign="Center" YAlign="Center"/>
</DataTemplate>
</flv:FlowListView.FlowColumnTemplate>
</flv:FlowListView>
CODE.cs
public partial class PlanCampaign_DetailPage : ContentPage
{
ObservableCollection<CarosualImages> list_grid { get; set; }
public PlanCampaign_DetailPage()
{
InitializeComponent();
this.BindingContext = this;
list_grid = new ObservableCollection<CarosualImages>()
{
new CarosualImages { Image="maharastra.jpg"},
new CarosualImages {Image="delhi.jpg"},
new CarosualImages {Image="delhi.jpg"},
new CarosualImages {Image="delhi.jpg"},
new CarosualImages {Image="delhi.jpg"},
};
grid_list.ItemsSource = list_grid;
}
ModelClass:
public class CarosualImages
{
public string Image { get; set; }
}
Could anyone tell that where i did mistake here, this is showing Empty Screen.
Here is the code for INotifyPropertyChanged
public class CarosualImages : INotifyPropertyChanged
{
private string _name = String.Empty;
public CarosualImages()
{
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string ImageName
{
get { return _name; }
set
{
_name= value;
OnPropertyChanged();
}
}
}
Put Public before
ObservableCollection<CarosualImages> list_grid { get; set; }

Resources