Device.OS in Xaml in Xamarin.Forms - c#

How to write (Device.OS == TargetPlatform.Android) in xaml,
In My class file i created like this in c#, but i don't know how to write this in xaml,
if (Device.OS == TargetPlatform.Android)
{
var stack = new StackLayout()
{
HorizontalOptions = LayoutOptions.Center,
};
var label = new Label()
{
Content = "This design is for Android"
};
stack.Children.Add(label);
};
if (Device.OS == TargetPlatform.iOS)
{
var grid = new Grid()
{
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.CenterAndExpand
};
var label = new Label()
{
Content = "This design is for IOS"
};
grid.Children.Add(label);
}
Please help me how to write this two different design in android and IOS in xaml.

As far as I know, this is not possible in XAML, at least not like this. Two options come to mind:
Create two pages in XAML, one for Android and one for iOS and push the right page depending on the platform, basically with the if from your code.
Or, implement something like this in one page:
<StackLayout>
<StackLayout.IsVisible>
<OnPlatform x:TypeArguments="x:Boolean">
<OnPlatform.iOS>false</OnPlatform.iOS>
<OnPlatform.Android>true</OnPlatform.Android>
</OnPlatform>
</StackLayout.IsVisible>
</Stacklayout>
And for the grid the other way around. Note: the latter might negatively impact your layout cycle
PS. Device.OS is deprecated, you should use Device.RuntimePlatform now.

Related

Xamarin calculating a stack layout height at run time

I am trying to create a dynamic view, where I get the data from the backend and create views for it on my Xamarin App.
In the XAML view I have a simple stack layout
<StackLayout x:Name="Container">
</StackLayout>
and I am creating views as soon as the date is retrieved as so
Label label = new Label();
label.Text= Text;
label.LineHeight = 1.1;
Container.Children.Add(CreateLabel(label));
The problem is the view doesn't expand to fit all the elements added
calculating the height and setting it as the HeightRequest for stack layout didn't work
any idea or suggestion would be nice.
I made a demo for you by writing the MainPage.xaml.cs file.
public partial class MainPage : ContentPage
{
String Text1 = "This is a text. This is a text.This is a text.This is a text.";
Double LineHeight1 = 1.78;
public MainPage()
{
InitializeComponent();
var layout = new StackLayout { };
var label = new Label { Text = Text1, TextColor = Color.Black, FontSize = 20, LineHeight = LineHeight1, BackgroundColor = Color.Red, LineBreakMode = LineBreakMode.WordWrap };
layout.Children.Add(label);
this.Content = layout;
}
}
You can see that I create a StackLayout and a label and I bind the layout to the content. It works well and you can try it.

What is the best way to add buttons in Xamarin Forms?

So I'm new to Xamarin Forms and I've found two ways of adding buttons:
1.Declaring the button in the .xaml file
<!-- <Button Text="Click Me!"
Clicked="OnButtonClicked" VerticalOptions="CenterAndExpand" />-->
and the .xaml.cs file
public void OnButtonClicked(object sender, EventArgs args)
{
count++;
label.Text =
String.Format("{0} click{1}!", count, count == 1 ? "" : "s");
declaring the button only in the .xaml.cs file
using System;
using Xamarin.Forms;
namespace FormsGallery
{
class ButtonDemoPage : ContentPage
{
Label label;
int clickTotal = 0;
public ButtonDemoPage()
{
Label header = new Label
{
Text = "Button",
Font = Font.BoldSystemFontOfSize(50),
HorizontalOptions = LayoutOptions.Center
};
Button button = new Button
{
Text = "Click Me!",
Font = Font.SystemFontOfSize(NamedSize.Large),
BorderWidth = 1,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.CenterAndExpand
};
button.Clicked += OnButtonClicked;
label = new Label
{
Text = "0 button clicks",
Font = Font.SystemFontOfSize(NamedSize.Large),
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.CenterAndExpand
};
// Accomodate iPhone status bar.
this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
// Build the page.
this.Content = new StackLayout
{
Children =
{
header,
button,
label
}
};
}
void OnButtonClicked(object sender, EventArgs e)
{
clickTotal += 1;
label.Text = String.Format("{0} button click{1}",
clickTotal, clickTotal == 1 ? "" : "s");
}
}
}
but the thing is: I want to know which way is better for adding a button and to not have any future code problems.
Thank you!
Actually they are same. It depends on one's choice.
I prefer XAML over Code because
XAML is cleaner and easy to understand.
XAML seems to be able to better respect the "separation of concerns" between UI and controller logic.
It has intellisense in Visual Studio
You can find your answer here in details
https://developer.xamarin.com/guides/xamarin-forms/creating-mobile-apps-xamarin-forms/summaries/chapter07/
They are functionally equivalent. Building your UI in XAML generally allows for a cleaner separation of concerns in your design, but one approach is not "better" than the other.
They are same. After building your UI with XAML, it's converted to their equivalent with C#, doing the same thing as writing with C# the view.
Code your UI as you like. For me the better approach is XAML as its more clean and easy to understand.
I agree with the above comments that using XAML or C# depends on your preferences. Additionally I would recommend to study bindings and MVVM quite quickly because they make the UI code much cleaner. In the case of buttons you can use commands to directly refer to ViewModel instead of having Click listener in your UI code.
Here is a place where you can get started with data bindings and MVVM: https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/

DataGrid binding crashes UWP app on Xamarin

I am creating an application with Xamarin using the shared definition, and my application should run on Android and as an UWP app. This App needs to show a DataGrid with bindable values and for this I am using the Xamarin.Forms.DataGrid. I had followed the sample showed in DataGrid's repository, and it works very well on Android, but I am having an issue when I try to run as a UWP app. The issue is that, when I run as a UWP app with a populated List and try to binding this list on the DataGrid, the app crashes, showing this Exception:
"System.Runtime.InteropServices.COMException: Error HRESULT E_FAIL has been returned from a call to a COM component.
at Windows.UI.Xaml.UIElement.Measure(Size availableSize)
at Xamarin.Forms.Platform.UWP.VisualElementRenderer`2.MeasureOverride(Size availableSize)
at Windows.UI.Xaml.UIElement.Measure(Size availableSize)
at Xamarin.Forms.Platform.UWP.VisualElementRenderer`2.MeasureOverride(Size availableSize)
at Windows.UI.Xaml.UIElement.Measure(Size availableSize)
at Xamarin.Forms.Plat"
As I had said this exception only occur on UWP, and only happens when this List is populate. The list is create in this way:
private List<TableValue> _tableValues;
public List<TableValue> TableValues
{
get { return _tableValues; }
set
{
TableValues= value;
OnPropertyChanged(nameof(TableValues));
}
}
private List<TableValue> CreateTableValues()
{
return new List<TableValue>{
new TableValue{Val1="", Val2="", Val3="", Val4="", Val5="", Val6="", Val7=""}
};
}
public async Task PopulateItems()
{
_tableValues = CreateTableValues();
UpdateProperty();
}
This list is create inside of the MVVM class of the View.
The DataGrid element is create in the View in that way:
private ScrollView CreateTable()
{
table = new DataGrid();
table.Columns.Clear();
table.Columns.AddRange(CreateColumns());
table.SelectionEnabled = true;
table.BackgroundColor = Color.White;
table.SetBinding(DataGrid.ItemsSourceProperty, new Binding("TableValues"));
table.HeaderBackground = Color.FromHex("#D4D0C8");
table.HeaderFontSize = 18;
table.HeaderTextColor = Color.FromHex("#08098F");
StackLayout tableStack = new StackLayout
{
BackgroundColor = Color.White,
HeightRequest = 850,
VerticalOptions = LayoutOptions.FillAndExpand
};
tableStack.Children.Add(table);
var scroll = new ScrollView
{
BackgroundColor = Color.White,
Margin = new Thickness(5, 5, 5, 5),
Content = tableStack,
Orientation = ScrollOrientation.Horizontal,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
return scroll;
}
I searched to find a possible solution for this problem, but I was not able to find any solution, since the questions using this DataGrid in Xamarin are few common.
In Xamarin.Forms.UWP nesting a ListView inside of a ScrollView is not supported. Thats the reason why you're crashing. See more on bugzilla.

visual studio xamarin forms mvvm

I'm starting a new project, and id like to use MVVM - I really like this pattern, and I have been using it in all my windows phone 8.1 apps. But moving to xamarin is a jungle! I usually use mvvm light, and I have a nice basic implementation I use every time a create a new project - but I can't find a really good sample that shows exactly what I need.
What I want to do is make a xamarin shared (or portable) project, that shares the views across all platforms. I want to write create the view using code-behind - so no xaml.
Does anyone have experience with this and can point me to a good sample?
I'm also wondering if I need to use a thirtyparty framework afterall, since navigating seems pretty easy.
There are many samples on to be found. My favorite site for Xamarin.Forms samples is Xamarin Forms in Anger.
Let's take a look at the Jobbberr sample:
using System;
using Xamarin.Forms;
namespace InAnger.Jobbberr
{
public class SettingsPage : ContentPage
{
public SettingsPage ()
{
Style = AppStyle.SettingsPageStyle;
var pageTitle = new Frame () {
Style = AppStyle.PageTitleLabelFrameStyle,
Padding = new Thickness(0,Device.OnPlatform(15,0,0),0,10),
Content = new Label {
Style = AppStyle.PageTitleLabelStyle,
Text = "Settings",
}
};
var signoutButton = new Button () {
VerticalOptions = LayoutOptions.EndAndExpand,
HorizontalOptions = LayoutOptions.Center,
Text = "Sign Out",
TextColor = AppStyle.DarkLabelColor,
};
Content = new StackLayout {
VerticalOptions = LayoutOptions.FillAndExpand,
Padding = new Thickness (20),
Children = {
pageTitle,
new BoxView() {
HeightRequest = 1,
BackgroundColor = AppStyle.DarkLabelColor,
},
new SettingsUserView(),
new SyncView (),
new SettingsSwitchView ("GPS"),
new SettingsSwitchView ("Jobs Alert"),
signoutButton,
new StatusBarView()
}
};
}
}
}
What do you see here?
The new class SettingsPage derives from ContentPage. The controls pageTitle and signoutButton are created in its constructor. In the end you see how a StackLayout is being created, filled with the controls and set as content of the page. That's how to create a Page in code.
How to apply MVVM?
Set BindingContext = ViewModel in the first row of the constructor (create a new view model or locate it by via a ViewModelLocator or anything).
Let's say for example you want to bind the Text and Command property of signoutButton to the view model's properties SignOutButtonText and SignoutCommand. You would change the creation of the button to this:
var signoutButton = new Button () {
VerticalOptions = LayoutOptions.EndAndExpand,
HorizontalOptions = LayoutOptions.Center,
TextColor = AppStyle.DarkLabelColor,
};
signoutButton.SetBinding(Button.TextProperty, "SignOutButtonText");
signoutButton.SetBinding(Button.CommandProperty, "SignoutCommand");

What approach should I take when implementing a horizontal GridView in Xamarin.Forms?

I need to implement the horizontal (magazine style) list. The apps that do this quite good (in my opinion) are Flipboard and Zite. I wondered if this is possible to implement into a Xamarin.Forms application with existing resources.
In Xamarin.Forms, you have an excellent View that is the ListView. This ListView has an ItemSource and an ItemTemplate property where you can bind your ViewModel to the ItemSource and you can bind your TextCell class to your ItemTemplate.
I'm searching for the exact same thing except that you can modify the ItemTemplate to a custom class I make myself. The reason I need this is that I need a more complex layout than TextCelland the ListView only scrolls vertically.
I like the MVVM pattern very much and I need something that exactly fits into this pattern. Now, I looked into some implementations:
https://github.com/XLabs/Xamarin-Forms-Labs
http://forums.xamarin.com/discussion/18627/gridview-with-itemssource
Option 1
In the Xamarin.Forms.Labs, there is a GridView, but this view doesn't expand to its parent in my implementation although I am setting the following:
var grid = GridView {
ItemWidth = 50,
ItemHeight = 50,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
My ItemSource is tied to my ViewModel (which I am 100% sure of it is providing items. I know that because if I swap this GridView for a ListView, there are items.):
grid.ItemSource = ViewModel.Items;
And my ItemTemplate:
var cell = new DataTemplate(typeof(TextCell));
cell.SetBinding(TextCell.TextProperty, "Title");
cell.SetBinding(TextCell.TextProperty, "Description");
gridView.ItemTemplate = cell;
Now, I know there are some problems with the GridView and that the implementation is only for iOS right now according to this.
Option 2
In the second post they mention a WrapLayout. Although it shows some items being added via its Children property, it doesn't show any implementation with MVVM. Besides that, the implementation is nowhere near finished.
I can take this project as a base and expand it to my needs. But I feel there has to be a lot of work done for this to work in my scenario.
Does anybody know any other resources that better fit my needs than these two? For which option should I go if there aren't any resources available (I know there must be something available since Zite and Flipboard already done it)?
I dont know flipboard or zite but you try could something like this.
var grid = new Grid()
{
VerticalOptions = LayoutOptions.FillAndExpand,
ColumnDefinitions = new ColumnDefinitionCollection()
{
new ColumnDefinition(){ Width = new GridLength(250, GridUnitType.Absolute) },
new ColumnDefinition(){ Width = new GridLength(250, GridUnitType.Absolute) },
new ColumnDefinition(){ Width = new GridLength(250, GridUnitType.Absolute) },
new ColumnDefinition(){ Width = new GridLength(250, GridUnitType.Absolute) },
new ColumnDefinition(){ Width = new GridLength(250, GridUnitType.Absolute) },
new ColumnDefinition(){ Width = new GridLength(250, GridUnitType.Absolute) }
},
RowDefinitions = new RowDefinitionCollection()
{
new RowDefinition(){ Height = new GridLength(1,GridUnitType.Star) },
new RowDefinition(){ Height = new GridLength(1,GridUnitType.Star) },
new RowDefinition(){ Height = new GridLength(1,GridUnitType.Star) }
}
};
var scrollview = new ScrollView() { Orientation = ScrollOrientation.Horizontal };
scrollview.Content = grid;

Categories

Resources