I try to use a databinding in a Xamarin Application List.
I am following : https://developer.xamarin.com/guides/xamarin-forms/user-interface/listview/data-and-databinding/.
Visual Studio give me this error : CS0103 C# The name "ELementView" does not exist in the current context.
I think it is a problem about the xmlns:local in xaml fil but I don't know.
Xaml code :
<?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:App4;assembly=listeElements"
x:Class="App4.Page1"
Title="ListView Demo Page">
<ListView x:Name="ELementView">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
listeElements code :
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace App4
{
public class Element
{
private string element;
public string Name
{
get { return element; }
set { element = value; }
}
ObservableCollection<Element> Elements = new ObservableCollection<Element>();
public void ElementListPage()
{
ELementView.ItemsSource = Elements;
Elements.Add(new Element { Name = "oooo" });
}
}
};
Thanks for your help
You could also use this:
public Page1()
{
InitializeComponent();
Elemenet e = new Element();
e.ElementListPage();
this.BindingContext = e;
}
but make sure your ObservableCollection<Element> has {get; set;};
Then you can add an ItemsSource-Binding to your ListView like this:
<ListView ItemsSource="{Binding Elements}">
as you definded the DataContext for Page1 it will look for a Property called Elements in your DataContext (which is the class Element) - there it gets the ElementsCollection and adds the Name to your CellTemplate
Just by giving the ListView a name doesn't mean you can reference it from anywhere. You can now reference ELementView from the code-behind of your Page1 XAML page.
To get there, open your Solution window, go to Page1.xaml click the arrow to the left of it and double-click Page1.xaml.cs.
In this page you could do something like this:
using System.Collections.ObjectModel;
using Xamarin.Forms;
public Page1()
{
InitializeComponent();
ObservableCollection<Element> Elements = new ObservableCollection<Element>();
ELementView.ItemsSource = Elements;
Elements.Add(new Element { Name = "oooo" });
}
Although this would work, it probably isn't the best approach. You are trying to use MVVM which is good! But you can take it a step further.
Maybe try using a MVVM framework like MvvmCross or FreshMvvm. I have done a blogpost on the later. You can find it here. Although new versions have come out, this should get you started with the basics.
Related
Hello,
I'm running into very annoying problem, what I need is simple but I'm getting an unexpected problem, here is what I'm trying to do:
I have a listview containing 2 labels in the ViewCell, both labels show same field but the difference is that the first is visible and the font is normal and the second is invisible and the font is bold, what I wanted to do is when I click on the item to change the property named: "Selected" from false to true and vise versa so that the bold label show/hide to inform the user that the item is selected.
In order to achieve this I wrote my code and I deploy the simple app on my android device and it worked like a charm, but after that I noticed that if I scroll the listview to an item that was not shown on the screen and click on that item, the first normal label disappeared which is an expected behavior but the second bold label doesn't shown
The following is my code:
testVisibilityProblem.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:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
xmlns:local="clr-namespace:CPALMSStandardsViewer;assembly=CPALMSStandardsViewer"
xmlns:b="clr-namespace:Prism.Behaviors;assembly=Prism.Forms"
xmlns:converters="clr-namespace:CPALMSStandardsViewer.Converters"
xmlns:Helpers="clr-namespace:CPALMSStandardsViewer.Helper"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="CPALMSStandardsViewer.Views.testVisibilityProblem">
<Grid>
<ListView Margin="10,0,10,0"
BackgroundColor="White"
SeparatorColor="Gray"
ItemsSource="{Binding CustomEntities}"
VerticalOptions="Fill"
SelectionMode="None"
HasUnevenRows="True">
<ListView.Behaviors>
<b:EventToCommandBehavior EventName="ItemTapped"
Command="{Binding SelectCustomEntity}"
EventArgsConverter="{converters:ItemTappedEventArgsConverter}" />
</ListView.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Label Grid.Column="0" Grid.Row="0" Text="{Binding Name}" TextColor="Black" IsVisible="{Binding IsSelected, Converter={Helpers:InverseBoolConverter}}"></Label>
<Label Grid.Column="0" Grid.Row="0" Text="{Binding Name}" TextColor="Black" FontAttributes="Bold" IsVisible="{Binding IsSelected}"></Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</ContentPage>
testVisibilityProblemViewModel.cs
using CPALMSStandardsViewer.Models;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace CPALMSStandardsViewer.ViewModels
{
public class testVisibilityProblemViewModel : ViewModelBase
{
public ObservableCollection<CustomEntity> CustomEntities { get; set; }
public testVisibilityProblemViewModel(INavigationService navigationService)
: base(navigationService)
{
Title = "Test Visibility Problem!";
CustomEntities = new ObservableCollection<CustomEntity>();
for (int i = 0; i < 50; i++)
{
CustomEntities.Add(new CustomEntity() { Name = "Item " + i, IsSelected = false });
}
}
private DelegateCommand<CustomEntity> _SelectCustomEntity;
public DelegateCommand<CustomEntity> SelectCustomEntity => _SelectCustomEntity ?? (_SelectCustomEntity = new DelegateCommand<CustomEntity>(ExecuteSelectCustomEntityCommand));
private void ExecuteSelectCustomEntityCommand(CustomEntity paramData)
{
paramData.IsSelected = !paramData.IsSelected;
}
}
}
CustomEntity.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
namespace CPALMSStandardsViewer.Models
{
public class CustomEntity : INotifyPropertyChanged
{
public virtual string Name { get; set; }
private bool _IsSelected;
public bool IsSelected { get { return _IsSelected; } set { _IsSelected = value; OnPropertyChanged("IsSelected"); } }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string name = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
I searched a lot concerning this problem and all what I found is something related to the OnPropertyChanged(), someone miss use the observable collection, other one miss the use of OnPropertyChanged(), other one used it in wrong way...
But my problem is different, it's not about binding because the top items worked as expected and also as I already mentioned the first label becomes hidden which is expected, my problem is that when you turn the IsVisible from false to true for an item that was not rendered on the screen, it simply not working.
I may know the problem but I tried a lot to get it solved but none of the solutions I tried work for me.
Please note that UWP worked as expected, my problem is on android platform.
Please HELP!
I reed a lot about namespace but still facing a problem / misunderstanding.
I would like to bind a Listview to an Observablecollection which resides in a static class in another namespace. It works but I can't succeed without code. I'm sure there is a better way to do this entirely in the XAML file.
So, this is my XAML file (...a part of - I delete a lot to be clear ...) :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ToolBox"
x:Class="ToolBox.MainPage">
<StackLayout>
<ListView x:Name="listToolBox">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}"
Detail="{Binding CreateDate}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
I set up the binding context of the "listToolBox" in the code behind:
...
using ToolBox.Model;
namespace ToolBox
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
listToolBox.ItemsSource = ToolBox.Model.EBis.ToolBoxList;
}
...
It refers to a member of a static class:
namespace ToolBox.Model
{
public static class EBis
{
public static ObservableCollection<cDocuments> ToolBoxList = new ObservableCollection<cDocuments>
{
new cDocuments{ Id = -1, Name = "Pas (encore) de connection aux serveurs ..."}
};
...
MY QUESTION:
What are the binding instructions I have to write in the XAML elements in order to delete this line of code behind
listToolBox.ItemsSource = ToolBox.Model.EBis.ToolBoxList;
To be complete, the structure of my "Toolbox" APP is here:
Thanks a lot for your advice
Use the x:Static markup extension:
<ListView ItemsSource=“{x:Static local:Model.EBis.ToolBoxList}”>
I want to have a SwitchCell within a ListView which is able to "remember" the state of the last SwitchCell event (Toggled) when the page is changed or the App closes and opens up again.
I have a class called Relays where I implemented the variables for binding to the SwitchCell properties of On and Text.
I am able to Bind the properties in the code behind RelayControl.xaml.cs class but I want to have a variable (or equivalent) to analyze/check the On state of the SwitchCell when the Page is opened.
I know the solution might be simple but I am very new to Xamarin and C# and I have been reading the Data Binding Basics on the Microsoft site (among other sources) and I can't seem to relate them to my current problem. Any help/examples/suggestions will be greatly appreciated.
My Relays.cs class is as follows:
using System;
using System.Collections.Generic;
using System.Text;
namespace Socket.Models
{
public class Relays
{
public Boolean isOn { get; set; } // Set the state of
the switch
public string State { get; set; } // Get the state of
the switch based on the isOn property
public string Name { get; set; } // Set the name of the
relay in the list
}
}
The RelayControl.xaml is as follows:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Socket.RelayControl"
Title="Relay Control Page">
<ContentPage.Content>
<StackLayout Padding="10,0,0,0">
<ListView x:Name="lstView" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<SwitchCell x:Name="Sw1" Text="{Binding Name,
Mode=TwoWay}" On="{Binding isOn, Mode=TwoWay}"
OnChanged="OnChanged_2"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
the RelayControl.xaml.cs is as follows:
using Socket.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Socket
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class RelayControl : ContentPage
{
public RelayControl()
{
InitializeComponent ();
loadSampleData();
}
private void loadSampleData()
{
// Create sample data
ObservableCollection<Relays> listRelays = new
ObservableCollection<Relays>();
listRelays.Add(new Relays { Name ="Relay 1", State = "",
isOn=false });
listRelays.Add(new Relays { Name ="Relay 2", State = "",
isOn=false });
listRelays.Add(new Relays { Name ="Relay 3", State = "",
isOn=false });
lstView.ItemsSource = listRelays;
}
private void OnChanged_2(object sender, ToggledEventArgs e)
{
var selectedItem = ((SwitchCell)sender).BindingContext as
Relays;
if (true)
{
bool IsToggled = e.Value;
string name = IsToggled.ToString();
if (name == "True")
{
//DisplayAlert("ON", "Relay 1 On", "Cancel");
BackgroundColor = Color.Silver;
//Set the switch Property to ON state (toggled)
selectedItem.isOn = true;
//Check if the switch has been toggled and change the
states accordingly
if (selectedItem.isOn == true)
{
BackgroundColor = Color.Gold;
}
}
else
{
//DisplayAlert("OFF", "Relay 1 OFF", "Cancel");
BackgroundColor = Color.LightSkyBlue;
}
}
}// OnChanged event
}// partial class
}
You seem to be following the MVVM pattern so, I will give you a basic run through:
First, your Relays class should be your binding context so that the properties there would be accessible to your XAML file which can be set in two ways
Through Xaml something like this :
<ContentPage.BindingContext>
<local:Relays/>
</ContentPage.BindingContext>
Where local is the namespace of your class and Relays is your class name.
Through C# something like this :
public RelayControl()
{
InitializeComponent ();
loadSampleData();
this.BindingContext=new Relays();
}
Now in your ListView Do the Following Changes :
<ListView x:Name="lstView" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<SwitchCell x:Name="Sw1" Text="{Binding Name,
Mode=TwoWay}" On="{Binding BindingContext.isOn,Source={x:Reference lstView}, Mode=TwoWay}"
OnChanged="OnChanged_2"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
After that, it should work like a charm
In case of issues revert
Good Day. I'm having trouble on how am I going to show all the records I have created in my ASP.NET WEB API to Xamarin.Forms Application. I tried creating pre-defined list of Employee's Name and Department and it worked. But what I want to do is Create a Record in ASP.NET Web Application and make it appear to my mobile application. Any help will be highly appreciated. Thanks in advance.
I watch a video tutorial regarding this matter. Refer to this link if needed. (https://www.youtube.com/watch?v=Lir75oNAeiM&index=2&list=PLpbcUe4chE7-uGCH1S0-qeuCWOMa2Tmam)
Here's my code.
MainPageMain.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="XamarinDemo.Views.MainPageMain"
xmlns:ViewModels="clr-namespace:XamarinDemo.ViewModels;assembly=XamarinDemo"
BackgroundColor="Teal">
<ContentPage.BindingContext>
<ViewModels:MainViewModel/>
</ContentPage.BindingContext>
<ListView ItemsSource="{Binding EmployeesList}"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical"
Padding="12,6">
<Label Text="{Binding Name}"
FontSize="24"/>
<Label Text="{Binding Department}"
FontSize="18"
Opacity="0.6"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
MainViewModel.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using XamarinFormsDemo.Models;
using XamarinFormsDemo.Services;
namespace XamarinFormsDemo.ViewModels
{
public class MainViewModel : INotifyPropertyChanged
{
private List<Employee> _employeesList;
public List<Employee> EmployeesList
{
get { return _employeesList; }
set
{
_employeesList = value;
OnPropertyChanged();
}
}
public MainViewModel()
{
InitializeDataAsync();
}
private async Task InitializeDataAsync()
{
var employeesServices = new EmployeesServices();
EmployeesList = await employeesServices.GetEmployeesAsync();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
EmployeesServices.cs
using Plugin.RestClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XamarinFormsDemo.Models;
namespace XamarinFormsDemo.Services
{
public class EmployeesServices
{
public async Task<List<Employee>> GetEmployeesAsync()
{
RestClient<Employee> restClient = new RestClient<Employee>();
var employeesList = await restClient.GetAsync();
return employeesList;
}
}
}
Here is a helpful post about the correct way to do this:
http://arteksoftware.com/end-to-end-mvvm-with-xamarin/
If your records are not being displayed completely on your mobile app you can test your ASP web service using POSTMAN and double check if it is working correctly and successfully returning the correct data, then bind the List or Observable collection correctly on your View Model and then update the list/Observable Collection property properly in order to show the latest records.
I've got a weird error when trying to create a simple sample using the latest version of Reactive UI.
The window opens and I get a system error
Couldn't find view for 'Hi Bob!'
note: 'Hi Bob!' is the first item in the list.
What am I missing here?
Thanks.
versions
ReactiveUI 6.5.0
Splat 1.6.2
.net 4.5
Sample code
xaml
<Window x:Class="ListBind.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel Orientation="Horizontal">
<ListBox Name="ListBox1"></ListBox>
</StackPanel>
</Grid>
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ReactiveUI;
namespace ListBind
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, IViewFor<ViewModel>
{
public MainWindow()
{
ViewModel = new ViewModel();
DataContext = ViewModel;
InitializeComponent();
this.OneWayBind(ViewModel, m => m.Items, v => v.ListBox1.ItemsSource);
}
public ViewModel ViewModel
{
get { return (ViewModel)GetValue(ViewModelProperty); }
set { SetValue(ViewModelProperty, value); }
}
public static readonly DependencyProperty ViewModelProperty =
DependencyProperty.Register("ViewModel", typeof(ViewModel), typeof(MainWindow), new PropertyMetadata(null));
object IViewFor.ViewModel
{
get { return ViewModel; }
set { ViewModel = (ViewModel)value; }
}
}
public class ViewModel : ReactiveObject
{
public ReactiveList<string> Items = new ReactiveList<string>(new[] { "Hi Bob!", "Two", "Three" });
}
}
The thing with ReactiveUI when you bind to things like a ListBox using the OneWayBind method, is that it will try to automatically apply a custom template for the data based upon the views it finds with Splat.Locator.Resolve. In your case, it is trying to find and build a view based on the "Hi Bob!" ViewModel, which obviously doesn't exist.
What you should do is force it to use a custom data template so that it doesn't try to apply a non-existing template. With a template below, it shouldn't try and resolve a view for you, but rather stick the "Hi Bob!" value into the TextBlock.
<ListBox x:Name="ListBox1">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
There is a slim chance that ReactiveUI will still ignore that (I cannot verify right now), so if that is the case, replace the OneWayBind binding with the traditional ItemSource={Binding Data}.