Basic data binding (Xamarin Forms) - c#

I'm trying to achieve the most basic form of data binding in Xamarin forms though the text that I set in my code are not shown on the labels at all. Any pointers would be great.
CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XamarinOuderportaal
{
public partial class LoginPage : ContentPage
{
public string UsernamePlaceHolder { get; set; }
public string PasswordPlaceHolder { get; set; }
public LoginPage()
{
this.UsernamePlaceHolder = "gebruikersnaam";
this.PasswordPlaceHolder = "wachtwoord";
InitializeComponent();
}
}
}
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:local="clr-namespace:XamarinOuderportaal"
x:Class="XamarinOuderportaal.LoginPage">
<StackLayout VerticalOptions="Center" HorizontalOptions="Fill" Spacing="20" Padding="20">
<Entry Placeholder="This is the placeholder" HorizontalOptions="Fill" IsVisible="{Binding ShouldDisplayUrl}"/>
<Entry Placeholder="{Binding UsernamePlaceHolder}" HorizontalOptions="Fill"/>
<Entry Placeholder="{Binding PasswordPlaceHolder}" HorizontalOptions="Fill" IsPassword="true"/>
<Button Text="test 2" HorizontalOptions="Fill"/>
</StackLayout>
</ContentPage>

Assign the bindingcontext and onpropertychange event for member variable in the viewmodel file
Check it basic of Xamarin binding
http://www.c-sharpcorner.com/article/quick-start-tutorial-creating-universal-apps-via-xamarin-binding-in-xaml-par/

Binding seeks on the instance of the source object, so the properties must not be static.
If you want to use static binding then you must use the Static extension:
<Entry Placeholder="{x:Static local:LoginPage.UsernamePlaceHolder}" HorizontalOptions="Fill"/>
EDIT: You have edited the question and removed the "static" definition, so the code must work now.

Related

Putting Title into Navigation Back bar in Xamrin forms

Hi I seem to be having issues getting my title to appear in the back bar part of the navigation area.
This is my code in my xaml:
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Project.Settings">
<NavigationPage.TitleView>
<Label Text="Settings" HorizontalTextAlignment="Center"/>
</NavigationPage.TitleView>
<ContentPage.Content>
</ContentPage.Content>
This is my code in my xaml.cs:
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace Project
{
public partial class Settings : ContentPage
{
public Settings()
{
InitializeComponent();
NavigationPage.SetHasBackButton(this, true);
NavigationPage.SetHasNavigationBar(this, true);
NavigationPage.GetTitleView(this);
}
}
}
This is what my code is doing:
I want to do this:

Using WebView to display local page html in my crossplatform xamarin app

i'm new in developing app with xamarin. I'm developing my first crossplatform app using xamarin forms. If you can give me the simpliest solution for my problem with examples.
i have a MainPage.xaml with some stacklayout. in one of this stacklayout i want to display a local page.html using a Webview (i think).
thanks you
my page xaml is this
<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="App1.info"
Title="WebView">
<ContentPage.Content>
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<WebView x:Name="webview" Source="{Binding mySource}" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
my page.xaml.cs is this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace App1
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class info : ContentPage
{
public HtmlWebViewSource mySource { get; set; }
public info()
{
InitializeComponent();
BindingContext = this;
mySource = new HtmlWebViewSource
{
Html = #"<html><body>
<h1>Xamarin.Forms</h1>
<p>Welcome to WebView.</p>
</body></html>"
};
}
}
}
in xaml
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<WebView x:Name="webview" Source="{Binding mySource}" />
</StackLayout>
in code behind or ViewModel
public HtmlWebViewSource mySource { get; set; }
public MainPage()
{
InitializeComponent();
webview.Source = "#"<html><body>
<h1>Xamarin.Forms</h1>
<p>Welcome to WebView.</p>
</body></html>";";
}
Or you can use data binding(MVVM) .

Why is no content displaying after passing SelectedItem as Custom Object into new page?

I'm very new to Xamarin and C#. So if What I am asking is rookie I apologize. But I have scoured the interwebz and Stack Overflow looking for why what I am doing isn't working and can't figure it out. As far as I can tell it should be working fine but maybe/hopefully I'm just missing something simple.
I'm using MVVM (mostly) and I have a ListView made up of objects called MobileBoardUser. That List View is set up like this
<ListView
ItemsSource="{Binding BoardUsers}"
HasUnevenRows="True"
ItemSelected="StatusBoardPageListView_ItemSelected" >
<ListView.ItemTemplate >
<DataTemplate>
<ViewCell>
//then the various StackLayout and Label objects etc.
In the code behind I am trying to use the ItemSelected method to pass the selected Item into a new page where all of it's properties will be displayed.
private void StatusBoardPageListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
{
return;
}
MobileBoardUser userSelected = e.SelectedItem as MobileBoardUser;
Navigation.PushAsync(new BoardUserPage(userSelected));
}
The BoardUserPage Code Behind looks like this
using EIOBoardMobile.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace EIOBoardMobile.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class BoardUserPage : ContentPage
{
public class UserProp
{
public string userprop { get; set; }
}
public class UserValue
{
public string uservalue { get; set; }
}
public ObservableCollection<UserProp> SelectedUserProps { get; set; } = new ObservableCollection<UserProp>();
public ObservableCollection<UserValue> SelectedUserValues { get; set; } = new ObservableCollection<UserValue>();
public BoardUserPage(MobileBoardUser selectedUser)
{
InitializeComponent();
BindingContext = this;
MobileBoardUser shownUser = selectedUser;
foreach (var prop in shownUser.GetType().GetProperties())
{
if (prop.GetType() == typeof(String))
{
UserProp NewUserProp = new UserProp
{
userprop = prop.Name.ToString()
};
SelectedUserProps.Add(NewUserProp);
}
}
foreach (var prop in shownUser.GetType().GetProperties())
{
if (prop.GetType() == typeof(String))
{
UserValue NewUserValue = new UserValue
{
uservalue = prop.GetValue(shownUser, null).ToString()
};
SelectedUserValues.Add(NewUserValue);
}
}
}
}
}
As you can see I have created two lists of objects, one to represent the property names and one to represent the actual values of those properties so they can be used in the xaml. In production these will be dynamic so it is important I be able to do it this way. To this end the BoardUserPage xaml looks like this
<?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:EIOBoardMobile.Views"
x:Class="EIOBoardMobile.Views.BoardUserPage">
<ContentPage.Content>
<StackLayout Padding="20">
<ListView
ItemsSource="{Binding SelectedUserProps}"
HasUnevenRows="True" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" >
<Label Text="{Binding userprop}" HorizontalOptions="StartAndExpand" TextColor="Black" />
<ListView ItemsSource="{Binding SelectedUserValues}" HorizontalOptions="EndAndExpand" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding uservalue}" HorizontalOptions="EndAndExpand" TextColor="Blue" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
All of this compiles and I get no unhandled exceptions or run time errors. The code behind that passes the SelectedItem as MobileBoardUser into the new page works to navigate to BoarduserPage but when I get there the page is empty and doing nothing.
What have I done wrong?
Ok after some trial and error I was actually able to figure this out. I had to make some changes to the code. The typeof statements were not constructed properly. For the SelectedUserProps I was getting the typeof the property rather the value. So I had to change that. Also the nested ListView inside another ListView was causing exceptions and failing to generate. Passing e.SelectedItem after casting actually DID work. It was the foreach comparison statements that were causing me grief. So the major changes I made were to the BoardUserPage code behind and the BoardUserPage xaml. Here are those changes. Primarily using one ObservableCollection instead of two (hence now only one foreach statement and correcting the type comparison so that I was comparing values rather than the properties themselves to typeof(String). Here is the code behind
using EIOBoardMobile.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace EIOBoardMobile.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class BoardUserPage : ContentPage
{
public class UserProp
{
public string userprop { get; set; }
public string uservalue { get; set; }
}
public ObservableCollection<UserProp> SelectedUserProps { get; set; } = new ObservableCollection<UserProp>();
public BoardUserPage(MobileBoardUser selectedUser)
{
InitializeComponent();
BindingContext = this;
foreach (var prop in selectedUser.GetType().GetProperties())
{
if (prop.GetValue(selectedUser).GetType() == typeof(String))
{
UserProp NewUserProp = new UserProp
{
userprop = prop.Name.ToString(),
uservalue = prop.GetValue(selectedUser).ToString()
};
SelectedUserProps.Add(NewUserProp);
}
}
}
}
}
and here is the View (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:local="clr-namespace:EIOBoardMobile.Views"
x:Class="EIOBoardMobile.Views.BoardUserPage">
<StackLayout Padding="20" >
<ListView
x:Name="Parent"
ItemsSource="{Binding SelectedUserProps}"
HasUnevenRows="True" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" Padding="10" HeightRequest="100">
<Label Text="{Binding userprop}" HorizontalOptions="StartAndExpand" VerticalOptions="StartAndExpand" TextColor="Black" />
<Label Text="{Binding uservalue}" HorizontalOptions="EndAndExpand" VerticalOptions="EndAndExpand" TextColor="Blue" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
This displays the property names on the left and values on the right of only those properties which are strings. This was necessary to avoid displaying IDs and othe integer based key values from the database that would just be meaningless clutter to end users.

Xamarin ToolbarItem Icon not showing in Android

I have a problem when trying to load the Icon of a ToolbarItem in Xamarin: It doesn't show up. The toolbar certainly exists. I have handled the Click method and it works, but the Icon is not visible. the ".ico" file exists in all the "drawable" folders in the Android project. It's the same .ico file I use in another solution and there it works just fine as the icon of a ToolbarItem, but here it doesn't work. I have tried to load an embedded image, but it doesn't work either. If I set its Text property, it is shown properly. I have a HomePage which is a MasterDetailPage, and the detail of this page is RootPage. On RootPage I have the ToolbarItem. Here are my xaml codes and the code behind:
HomePage:
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:ITEC.Views;assembly=ITEC"
x:Class="ITEC.Views.HomePage"
IsPresented="True">
<MasterDetailPage.Master>
<ContentPage Title="Home" Padding="0,20,0,0">
<StackLayout>
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<views:RootPage/>
</MasterDetailPage.Detail>
</MasterDetailPage>
Code behind:
using ITEC.Services;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace ITEC.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class HomePage : MasterDetailPage
{
private OptionService _optionService;
public HomePage()
{
InitializeComponent();
Detail=new NavigationPage(new RootPage());
_optionService = new OptionService();
listView.ItemsSource = _optionService.GetOptions();
}
}
}
RootPage:
<?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:embedded="clr-namespace:ITEC.MarkupExtensions"
x:Class="ITEC.Views.RootPage">
<ContentPage.ToolbarItems>
<ToolbarItem Icon="settings.ico" Clicked="MenuItem_OnClicked"></ToolbarItem>
</ContentPage.ToolbarItems>
<StackLayout>
<Label>Hello world</Label>
</StackLayout>
</ContentPage>
Code behind:
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace ITEC.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class RootPage : ContentPage
{
public RootPage()
{
InitializeComponent();
}
private void MenuItem_OnClicked(object sender, EventArgs e)
{
DisplayAlert("Hello", "OK", "No");
}
}
}
Try png file for your icon. i think it might be work.

Xamarin.Forms accessing controls written in markup from Code

Im trying to add some items to a Listview which i added using Xamarin.Forms markup in an xaml file.
The button can be accessed by hooking with the click event.But since the listview is empty i need the event like ondraw like in winforms, so that i can hook to it when it is drawn.
In the XAML file I have :
<?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="ButtonXaml.ButtonXamlPage">
<StackLayout>
<Button Text="Tap for click count!"
BorderWidth="10"
TextColor="Red"
HorizontalOptions="Center"
Clicked="OnButtonClicked" />
<ListView
HorizontalOptions="Center"
/>
</StackLayout>
</ContentPage>
In the .cs file i have
using System;
using Xamarin.Forms;
namespace ButtonXaml
{
public partial class ButtonXamlPage
{
int count = 0;
public ButtonXamlPage()
{
InitializeComponent();
}
public void OnButtonClicked(object sender, EventArgs args)
{
((Button)sender).Text = "You clicked me";
}
}
}
So should i hook to events in Listview or can i do something like Resource.getElementbyID like we do in android
To access a Forms control in the code-behind, you need to assign it a name, using the x:Name attribute
in XAML:
<ListView HorizontalOptions="Center" x:Name="MyList" />
in code:
MyList.ItemsSource = myData;
There is a bug in Xamarin where VS doesn't see the defined x:Name
http://forums.xamarin.com/discussion/25409/problem-with-xaml-x-name-and-access-from-code-behind
Say you've defined an image in XAML:
<Image x:Name="myImageXName" />
Then this should work in code behind:
this.FindByName<Image>("myImageXName");
In my case the problem was lack of line XamlCompilation(XamlCompilationOptions.Compile)] in .xaml.cs file.
Example:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new MainPageViewModel();
}
...
}

Categories