How does this work? What exactly is happening? - c#

I am learning Xamarin and I know the basics of C#. One of the first codes I encounter is
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin.Forms;
namespace Hello
{
public class App : Application
{
public App()
{
// The root page of your application
MainPage = new ContentPage
{
Content = new StackLayout
{
VerticalOptions = LayoutOptions.Center,
Children = {
new Label {
HorizontalTextAlignment = TextAlignment.Center,
Text = "Welcome to Xamarin Forms!"
}
}
}
};
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
The part where I have a problem is
Children = {
new Label {
HorizontalTextAlignment = TextAlignment.Center,
Text = "Welcome to Xamarin Forms!"
}
I don't understand what's happening here. What is Children? What is it getting assigned to?

Children is not assigned to, but Children is initialized. It is more confusing as property `Children' is not browsable, so it does not appear in intellisense.
Children is IList<View>.
You can initialize collection like this...
List<string> list = new List<string>{
"s1",
"s2",
"s3"
};
which is equivalent to
List<string> list = new List<string>();
list.Add("s1");
list.Add("s2");
list.Add("s3");
Similarly
Children = {
new Label{
}
}
is equivalent to
Children.Add(new Label{ });
However, there is no official document about how to initialize collection property like this, but it seems compiler converts expression cleverly. I tried to compile and it seems it did work correctly.
You can see an example here, https://dotnetfiddle.net/8jln93

Related

Xamarian.Form default MasterDetail Project Application.Current.MainPage is null

I'm really trying to work my way through a Xamarian.Form app an I'm finding it difficult because the template out of the box doesn't seem to work.
Basically on the menu I'm trying to nav to the Browse or About page.
however MainPage RootPage { get => Application.Current.MainPage as MainPage; } is returning null.
I've made no changes to this template but I do understand C# so I roughly understand the issue but I'm not aware as to why this is returning null, certainly from the starting template.
MenuPage.xaml.xs
using ProspectGator.Models;
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace ProspectGator.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MenuPage : ContentPage
{
MainPage RootPage { get => Application.Current.MainPage as MainPage; }
List<HomeMenuItem> menuItems;
public MenuPage()
{
InitializeComponent();
menuItems = new List<HomeMenuItem>
{
new HomeMenuItem {Id = MenuItemType.Browse, Title="Browse" },
new HomeMenuItem {Id = MenuItemType.About, Title="About" }
};
ListViewMenu.ItemsSource = menuItems;
ListViewMenu.SelectedItem = menuItems[0];
ListViewMenu.ItemSelected += async (sender, e) =>
{
if (e.SelectedItem == null)
return;
var id = (int)((HomeMenuItem)e.SelectedItem).Id;
await RootPage.NavigateFromMenu(id);
};
}
}
}
App.xaml.cs
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using ProspectGator.Views;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace ProspectGator
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new NavigationPage( new MainPage());
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
Typically I would expect this property to be set or already set but I'm not sure. I do have a MainPage.xaml.

Why is this 'Label' a field?

Im currently working myself trough a Xamarin Book. There you can see this Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Xamarin.Forms;
namespace BookCode
{
public class Greetings : ContentPage
{
public Greetings()
{
Label label;
label = new Label
{
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
Content = label;
SizeChanged += OnPageSizeChanged;
void OnPageSizeChanged(object sender, EventArgs args)
{
label.Text = String.Format("{0} \u00D7 {1}", Width, Height);
}
}
}
}
And in an explanation of the code you can read this:
"Instead, the event handler accesses the Label element (conveniently saved as a field) to display the Width and Height properties of the page. The Unicode character in the String.Format call is a times (×) symbol."
My current knowledge of fields and properties is basically this:
public class ClassName
{
private string field;
public string property {get {return field;} set {field = value;} }
}
I dont understand why the Label element is saved as a field. Could it be saved as something else?
It is not a field. Fields are members on a class or struct. This label is just a local variable.
The book is wrong.
You can make it a field or property obviously by moving the definition of the label to the class level.

Xamarin forms PopModalAsync doesn't trigger

I'm building a Xamarin.Forms application with a facebook login using Xamarin.Auth.
Entry point (app.cs):
public App()
{
MainPage = new WelcomePage();
}
WelcomePage:
using System;
using Xamarin.Forms;
namespace Project
{
public class WelcomePage : ContentPage
{
public WelcomePage()
{
var login = new Button { Text = "Login" };
login.Clicked += (sender, e) =>
{
Navigation.PushModalAsync(new LoginPage());
};
Content = new StackLayout
{
BackgroundColor = Color.FromHex("F0C640"),
Padding = new Thickness(10, 40, 10, 10),
Children = {
new Label { Text = "Please login" },
login
}
};
}
}
}
LoginPage:
using Xamarin.Forms;
namespace Project
{
public class LoginPage : ContentPage
{
}
}
This is empty as I use Xamarin.Auth to authenticate with facebook so I created 2 different renderers on iOS and Android to display the facebook login page. After the login success I call an action which is located in my app.cs file:
public Action SuccessfulLoginAction
{
get
{
return new Action(() => goToMainPage());
}
}
public void goToMainPage()
{
MainPage.Navigation.PopModalAsync();
//MainPage.Navigation.PopToRootAsync();
MainPage.Navigation.PushAsync(new DetailPage());
}
At the end of the authentication the page is white but I believe it's a white page from Facebook after the authentication is done.
The SuccessfulLoginAction is well called so I go through the goToMainPage() function.
I put some breakpoints and PopModalAsync() doesn't do anything, same for PopToRootAsync() and PushAsync()...
The DetailPage is just a page with a Label. If I try to display it at the beginning of the process (app(){}) it display it well.
Thanks.

Xamarin remove TableSection top border

Is it possible to remove the top blue border(or atleast change its color) of xamarins TableSection:
I looked at Xamarin TableView documentation, but I found no help there:
https://developer.xamarin.com/guides/xamarin-forms/user-interface/tableview/
My code at the moment looks like this:
public class UserProfilePushNotification : TableView
{
public UserProfilePushNotification(string text) : base()
{
Intent = TableIntent.Data;
Root = new TableRoot
{
new TableSection
{
new SwitchCell
{
Text = text
},
new TextCell()
{
Text = string.Empty
},
new TextCell
{
Text = "Android Version: 1.2.1"
}
}
};
}
}
I was digging into this problem and I found that TableView is implemented (in the default renderer) as a ListView.
The TableSection is just a normal item in the Listview, the first one.
If you don't use the Title Property from the TableSection (in this case you aren't using it) you can hide it.
To do this I created a custom render for the TableView and hidden the first element of the ListView:
[assembly:ExportRenderer(typeof(Project.MenuTableView), typeof(Project.Droid.MenuTableViewRenderer))]
namespace Project.Droid
{
public class MenuTableViewRenderer : TableViewRenderer
{
private bool _firstElementAdded = false;
protected override void OnElementChanged (ElementChangedEventArgs<TableView> e)
{
base.OnElementChanged (e);
if (Control == null)
return;
var listView = Control as Android.Widget.ListView;
listView.ChildViewAdded += (sender, args) =>
{
if (!_firstElementAdded)
{
args.Child.Visibility = ViewStates.Gone;
_firstElementAdded = true;
}
};
// Uncomment this if you want to remove all the dividers from the table.
//listView.DividerHeight = 0;
}
}
}

Xamarin Forms webview not displaying on device

Ive developing a webview app in Xamarin.Forms over the last few days and ive been testing it on an android and iOS emulator and it seems to work just fine in the emulators but when i went and tried to test it on my own Android device, it just showed the xamarin splashscreen(im using the trial version at the moment) and then just transitioned to a blank white screen instead of the webview.
Does anyone have any ideas why it is doing this?
I will attach my code below:
App.cs
using Xamarin.Forms;
namespace WebViewApp
{
public class App() : Application
{
public App()
{
// The root page of your application
MainPage = new WebPage();
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
WebPage.cs
using Xamarin.Forms;
namespace WebViewApp
{
public class WebPage : ContentPage
{
private const string URL = "https://www.google.com";
private const int PADDING_WIDTH = 0;
private int paddingHeight;
private WebView webView;
public WebPage()
{
webView = new WebView
{
Source = URL,
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand
};
CheckDevice();
Content = new StackLayout
{
Padding = new Thickness(PADDING_WIDTH, GetPaddingHeight()),
Chrildren = { webView }
};
}
public int GetPaddingHeight()
{
return paddingHeight;
}
/// <summary>
/// This will set the padding height for the webview when displayed
/// <summary>
/// <param name="pHeight">Set integer value for the padding height.</param>
public void SetPaddingHeight(int pHeight)
{
paddingHeight = pHeight;
}
private void CheckDevice()
{
if(Device.OS == TargetPlatform.Android)
{
SetPaddingHeight(0);
}
else if(Device.OS == TargetPlatform.iOS)
{
SetPaddingHeight(20);
}
}
}
}
** UPDATE **
I am using a company website but I have been testing this app out with a number of different sites such as google, youtube, and amazon. It would seem that the only site that wont display on my device is my companies website(its a responsive website) but all of the others do.
Since version 9, iOS will only allow your application to communicate with servers that implement best-practice security by default. Values must be set in Info.plist to enable communication with insecure servers.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads </key>
<true/>
</dict>
You must set the two properties HeightRequest and WidthRequest.
WebView requires that HeightRequest and WidthRequest are specified
when contained in StackLayout or RelativeLayout. If you fail to
specify those properties, the WebView will not render.
Source: https://developer.xamarin.com/guides/xamarin-forms/user-interface/webview/
Here is my code to display a webview in a Xamarin.Forms App.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin;
using Xamarin.Forms;
namespace mynamespace
{
public class WebsitePage : ContentPage
{
public WebsitePage(string url)
{
Label lbl_header = new Label
{
Text = "WebView",
HorizontalOptions = LayoutOptions.Center
};
WebView webview = new WebView
{
Source = url,
VerticalOptions = LayoutOptions.FillAndExpand
};
this.Content = new StackLayout
{
Children = {
webview
}
};
}
}
}

Categories