Edit elements in C# after making them in XAML - xamarin

I have created a couple of entries and buttons in XAML (no C# code yet).
Is it possible to edit or even add elements in C# code to a StackLayout which was made in XAML?
For example, having the following 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:ORTEC_MOBILE"
x:Class="ORTEC_MOBILE.MainPage"
BackgroundColor="#0074ff">
<RelativeLayout>
<StackLayout HorizontalOptions="FillAndExpand"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.25,Constant=0}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width,Factor=1,Constant=0}">
<Label Text="Login" FontSize="36" TextColor="White" HorizontalTextAlignment="Center">
</Label>
<Label Text="Welcome back! Please log into your account." FontSize="12" TextColor="White" HorizontalTextAlignment="Center">
</Label>
</StackLayout>
</RelativeLayout>
Is it possible to add a button to the layout using C# code?

Yes, definitely possible. When you give an element an attribute of x:Name="element" it is available in code-behind as "element". See this sample on the Xamarin site to see how they call elements in code:
https://github.com/xamarin/xamarin-forms-book-samples/tree/master/Chapter08/XamlClock
The x:Name attribute allows an object instantiated in XAML to be given a name. The rules for these names are the same as for C# variable names. Following the return of the InitializeComponent call in the constructor, the code-behind file can refer to these names to access the corresponding XAML element. The names are actually converted by the XAML parser into private fields in the generated partial class.

It is definately possible to add in controls programatically from the code behind, I'll give you an example below.
It's probably useful to give the component you wish to add a control to, a name, that way it can be accessed from the class behind the xaml.
So in this instance I've simply attributed a name to your xaml stack layout.
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:ORTEC_MOBILE"
x:Class="ORTEC_MOBILE.MainPage"
BackgroundColor="#0074ff">
<RelativeLayout>
<StackLayout x:Name="mainStackLayout" HorizontalOptions="FillAndExpand"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.25,Constant=0}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width,Factor=1,Constant=0}">
<Label Text="Login" FontSize="36" TextColor="White" HorizontalTextAlignment="Center">
</Label>
<Label Text="Welcome back! Please log into your account." FontSize="12" TextColor="White" HorizontalTextAlignment="Center">
</Label>
</StackLayout>
</RelativeLayout>
C# Backing Class:
Public void SomeMethodThatsInMyBackingClass()
{
Label newLabel = new Label {
Text = "Hello, Forms!",
FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
},
mainStackLayout.Children.Add(newLabel);
}
Using the above as a rough example should be enough for you to replicate it in your own project. Good luck.

Related

How to bind a nested Layout with external ContentView in Xamarin.Forms?

I have a Page with a StackLayout using BindableLayout.ItemsSource, inside each item I have a ListView, for each item in this nested ListView I need to do a Binding to a property on the Page's ViewModel. I'm trying to use the Source+Path approach but the app crashes as soon as I open the page that contains this structure.
MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="BindableLayoutReferenceBug.ListViewPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:BindableLayoutReferenceBug">
<StackLayout BindableLayout.ItemsSource="{Binding Items}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<local:MessageListViewTemplate />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ContentPage>
MessageListViewTemplate.xaml:
<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
x:Class="BindableLayoutReferenceBug.MessageListViewTemplate"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Name="listView">
<ListView ItemsSource="{Binding Options}">
<ListView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding .}" />
<Button
BackgroundColor="Blue"
Command="{Binding Source={x:Reference Name=listView}, Path=Parent.BindingContext.ShowMessageCommand}"
CommandParameter="{Binding .}"
Text="Show Message" />
</StackLayout>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentView>
The exception shows that there is a problem finding the reference to the x:Name I used: Can not find the object referenced by listView
This only happens when I have a nested structure as I mentioned (StackLayout with BindableLayout > ListView). I'm not sure if this is not a supported scenario or if it is a bug.
I tried using different Paths for the binding, but since this is a problem parsing the XAML not finding the x:Name referenced, I don't think it even starts evaluating my Path.
Am I doing something wrong or is this a bug in Xamarin.Forms?
Xamarin.Forms version used: 3.6.0.293080
Repro sample: https://github.com/akamud/BindableLayoutReferenceBug
Maybe, x:Name wasn't recognized at runtime even though you have set it to your content view in XAML. You could raise an issue on GitHub.
Here I tried this binding using code behind and it works fine. You could use it as an alternative:
public MessageListViewTemplate()
{
InitializeComponent();
listView.ItemTemplate = new DataTemplate(() =>
{
ViewCell viewCell = new ViewCell();
Label label = new Label();
label.SetBinding(Label.TextProperty, new Binding("."));
Button button = new Button() { Text = "Show Message", BackgroundColor = Color.Blue };
button.SetBinding(Button.CommandProperty, new Binding("Parent.BindingContext.ShowMessageCommand", source: ContentView));
button.SetBinding(Button.CommandParameterProperty, new Binding("."));
viewCell.View = new StackLayout
{
Children =
{
label,
button
}
};
return viewCell;
});
}
XAML:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BindableLayoutReferenceBug.MessageListViewTemplate"
x:Name="ContentView">
<StackLayout>
<ListView ItemsSource="{Binding Options}" x:Name="listView" HasUnevenRows="True">
</ListView>
</StackLayout>
</ContentView>
Here, I defined the parent content view as ContentView and named ListView listView.
Please notice that the list view's data template should be a view cell. So I used a view cell to wrap the content here.
It was a bug after all, it is now fixed and the above should work: https://github.com/xamarin/Xamarin.Forms/issues/6192

How to add entry inside picker popup? Xamarin Forms

I have a picker with more than one hundred data. I want to search a particular item. How can I add a entry inside a picker popup? Is it possible? If not, What are the best alternative to search data inside a picker?
What you want might be able to be done via custom renderer, but I personally don't know how that would be done...
If you want custom functionality in a picker, I highly recommend Rg.Plugins.Popup. This package allows a user to define there own custom popup. I use this for all my Popup pages/controls in the application I develop.
GitHub: Rg.Plugins.Popup
Define a PopupPage with an Entry and ListView and you can provide the kind of functionality you are wanting.
There is no out of the box solution for this. But a picker with searchbar can be implemented with rg.plugins.popup.(https://github.com/rotorgames/Rg.Plugins.Popup).
Create a view with label and down arrow.Provide click for that.In that click event call rg.popup.
The design of popup for referance.
<?xml version="1.0" encoding="utf-8" ?>
<pages:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="iVerify.Sample"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
xmlns:animations="clr-namespace:Rg.Plugins.Popup.Animations;assembly=Rg.Plugins.Popup"
BackgroundColor="Transparent" >
<pages:PopupPage.Animation>
<animations:ScaleAnimation
PositionIn="Center"
PositionOut="Center"
ScaleIn="1.2"
ScaleOut="0.8"
DurationIn="400"
DurationOut="300"
EasingIn="SinOut"
EasingOut="SinIn"
HasBackgroundAnimation="False"/>
</pages:PopupPage.Animation>
<StackLayout VerticalOptions="Center" Padding="10" HorizontalOptions="FillAndExpand" Margin="0,20,0,0" >
<StackLayout>
<SearchBar x:Name="Searchbar" />
</StackLayout>
<StackLayout>
<ListView x:Name="ListView" ItemsSource="{Binding}"
ItemSelected="List_Tapped">
ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
// Your controls
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</StackLayout>
</StackLayout>
</pages:PopupPage>
By using Itemselected property you can get the value of tapped view. Then set it to the label of Mainpage(label that clciked to open the popup).This can be achieved by messeging centre.
Sample screenshot
I did it with Telerik though it didn't launch on Android in main project for me and the dropdown behaves strange on UWP - it is dropping up instead of down for some layout constellations.
Telerik is not free though, so if you have it you can use:
<StackLayout Orientation="Horizontal"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<telerikInput:RadAutoCompleteView x:Name="autoCompleteView"
HorizontalOptions="FillAndExpand"
ShowSuggestionView="True"
ShowMoreItems="True"
SuggestMode="Suggest"
Watermark="Search here..." />
<Button Clicked="Button_Clicked"
Text="▼"/>
</StackLayout>
and in code behind
private void Button_Clicked(object sender, System.EventArgs e)
{
autoCompleteView.ShowSuggestions();
}

Show contentview on frame tapgesture

I am developing a cross platform app using xaml forms and have yet to figured out how to call a ContentView ontapGesture. I am able to call ContentView on xaml forms using <local:MailRoomList/> but I cant show a view ontap or on click event.
I have tried to show view on stacklayout using StackLayoutID.Children.Add(new MailRoomList()); but thats not what I want. I want to show full contentview on content page with back button enabled.
Please advise. Thank you
MailRoomList
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="xx.xxxx.xx.Views.MailRoomList">
<ContentView.Content>
<StackLayout>
<Label Text="This is my MailRoom List" />
</StackLayout>
</ContentView.Content>
</ContentView>
OnTapGesture
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="OnRegisterMail" NumberOfTapsRequired="1"/>
</Frame.GestureRecognizers>
CodeBehind
async void OnRegisterMail(object sender, EventArgs e)
{
await Navigation.PushAsync(new MailRoomList());
}
Edit:
Home Page
<?xml version="1.0" encoding="utf-8" ?>
<xf1:BottomBarPage
xmlns:xf1="clr-namespace:xx.xxxx.xx.BottomBar"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:xx.xxxx.xx.Views"
x:Class="xx.xxxx.xx.Views.Home">
<ContentPage x:Name="MailRoomPage" Title="MailRoom" Icon="mailroom.png" xf1:BottomBarPageExtensions.TabColor="Orange" xf1:BottomBarPageExtensions.BadgeCount="5">
<local:MailRoom/>
</ContentPage>
<ContentPage Title="Transport" Icon="transport.png" xf1:BottomBarPageExtensions.TabColor="Green" xf1:BottomBarPageExtensions.BadgeCount="10">
<Label VerticalOptions="Center" HorizontalTextAlignment="Center" Text="Transport" FontSize="Large"/>
</ContentPage>
<ContentPage Title="Communication" Icon="communication.png" xf1:BottomBarPageExtensions.TabColor="Blue" xf1:BottomBarPageExtensions.BadgeCount="3">
<Label VerticalOptions="Center" HorizontalTextAlignment="Center" Text="Communication" FontSize="Large"/>
</ContentPage>
<ContentPage Title="HSE" Icon="hse.png" xf1:BottomBarPageExtensions.TabColor="Red" xf1:BottomBarPageExtensions.BadgeCount="2">
<Label VerticalOptions="Center" HorizontalTextAlignment="Center" Text="HSE" FontSize="Large"/>
</ContentPage>
<ContentPage Title="Meeting" Icon="meeting.png" xf1:BottomBarPageExtensions.TabColor="DarkCyan" xf1:BottomBarPageExtensions.BadgeCount="5">
<Label VerticalOptions="Center" HorizontalTextAlignment="Center" Text="Meeting" FontSize="Large"/>
</ContentPage>
From homepage above I am calling my view <local:MailRoom/> which is calling another view MailRoomList. This is where I need your advice on how to call a content view from another content view.
ContentView is a View not a Page. Change your MainRoomList Xaml to 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"
x:Class="xx.xxxx.xx.Views.MailRoomList">
<StackLayout>
<Label Text="This is my MailRoom List" />
</StackLayout>
</ContentPage>
View's dont support navigation, they can only be navigated to if they belong to a Page which are the objects that contain the navigation infrastructure.
IF you want to mantain your MailRoomList as a ContentView, then you need to include her in some other page, and perform the navigation ( inside the tap method ) to that other page

Xamarin.Forms - How To Make Left Sidebar Swipe Out and Main Page Slide With It

I'm looking to create a specific animation where you start with a collapsed sidebar (still visible, but skinny) and main page content:
and when you pull out the left sidebar, the sidebar expands, and the main content moves with it (so that the right part of the main content slides out of view):
Also, note that the content in the sidebar doesn't move (though there is additional content that appears (button on the bottom)), but rather the width of the sidebar container just expands. Finally, I would like it to slide with my finger, not just be a static animation.
How do I accomplish this in Xamarin.Forms? (Is it possible?)
You can found it in Telerik Xamarin Forms sample (SlideDrawer -> Transitions/Location)
Sign in your account (telerik.com), I thinks it's free ..
Playing with the Xamarin Studio XAML Preview:
It is a matter of binding your expand event to WidthRequest in the first "column" to resize it and push the "right" side over. Depending upon the control settings in the first column, they will either expand to fill the new "column" width or stay a fixed size...
Note: Personally I would do this using ConstraintExpressions in order to make the design truly dynamic and adaptive to orientation changes, different screen sizes, etc...
<StackLayout RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.25}"
RelativeLayout.YConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.75}"
</StackLayout>
Example XAML from preview image above:
<?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="OpenDrawer.TestLayoutPreview">
<ContentPage.Content>
<StackLayout BackgroundColor="Blue" Orientation="Horizontal">
<StackLayout Orientation="Vertical">
<StackLayout Orientation="Vertical" BackgroundColor="Maroon" HorizontalOptions="Start" VerticalOptions="FillAndExpand" MinimumWidthRequest="100" WidthRequest="100">
<Button Text="Left 1" BackgroundColor="Aqua"></Button>
<Button Text="Left 2" BackgroundColor="Aqua"></Button>
<Button Text="Left 3" BackgroundColor="Aqua"></Button>
</StackLayout>
<StackLayout Orientation="Vertical" VerticalOptions="End">
<Button Text="Left Bottom" BackgroundColor="Lime"></Button>
</StackLayout>
</StackLayout>
<StackLayout Orientation="Vertical" BackgroundColor="Red" HorizontalOptions="FillAndExpand">
<Label Text="Right" BackgroundColor="Aqua"></Label>
<ScrollView>
<WebView Source="https://xamarin.com" WidthRequest="1000" HeightRequest="1000" ></WebView>
</ScrollView>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>

Center Icon and Text in a button Xamarin XAML

I don't how to center the icon inside the button and get it above the text, I didn't find information also about it, I'm asked to do a kind of "tabb" option menu, but below the screen, and I found that it was kind of "hard" because of the "design implications"etc, so I decided that with buttons would be easier, but the problem now is how to center the image and get the text right, If some one could help me, that would be great. This is my code so far:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
BackgroundColor="Silver"
x:Class="XamForm.View.MainPage">
<Label Text="{Binding MainText}" VerticalOptions="Center" HorizontalOptions="Center" />
<StackLayout Padding="30">
<Label x:Name="lblCuantos" Text="No #" TextColor="Gray" FontSize="20"/>
<Label x:Name="lblNombre" Text="" FontSize="20"/>
<Button x:Name="btn1" Text="Oprimir" Clicked="Accion"/>
<Button x:Name="btn2" BackgroundColor="White" Image="iconRes.png" HorizontalOptions="CenterAndExpand" Text="Gridd" TextColor="Gray" Clicked="Accion2"/>
<Button x:Name="btn3" BackgroundColor="White" Image="iconRes.png" HorizontalOptions="CenterAndExpand" TextColor="Gray" Clicked="Accion2"/>
</StackLayout>
</ContentPage>
This is the actual result of the button itself:
http://oi59.tinypic.com/11so9le.jpg
This is what the final result of the menu should look like kind off
http://oi62.tinypic.com/10pzw2f.jpg
Thank you!
You can use ContentLayout="Top,0" in button. For Example in your case use below code
<Button x:Name="btn2" ContentLayout="Top,0" BackgroundColor="White" Image="iconRes.png" HorizontalOptions="CenterAndExpand" Text="Gridd" TextColor="Gray" Clicked="Accion2" />
<Button x:Name="btn3" ContentLayout="Top,0" BackgroundColor="White" Image="iconRes.png" HorizontalOptions="CenterAndExpand" TextColor="Gray" Clicked="Accion2"/>
You could use a StackLayout with Orientation set to Vertical, and in it add Button and Label.
The Button.Image property is of type FileImageSource so any image that is 'local' can be used in a button. This means the following code will work:
someButton.Image = "imageName.png";
or you can write
someButton.Image = ImageSource.FromFile("imageName.png");
if imageName.png is located in each of the application projects (Resources folder in iOS, Resources/Drawable folder in Android, and application root in WinPhone; each with the appropriate build action set).
The Xaml equivalent is:
<Button Text="Has Image" Image="someImage.png" />
See the Working with Images doc for full details of what the build action should be for each platform.

Resources