I've created a working example for Android and UWP (not tested in iOS) from https://github.com/MitchMilam/Drawit.
I've looked over and over on stackoverflow, but whatever suggestions given, I cannot find the answer.
I'm creating a canvas and I want to show the image in the next screen.
My code for the mainscreen is:
using System;
using System.Collections.Generic;
using System.Linq;
using Xamarin.Forms;
namespace XamarinGame
{
class MainPage : ContentPage
{
private const int PalleteSpacing = 3;
public ImageWithTouch DrawingImage;
private Dictionary<string, Color> ColorPallete;
public MainPage()
{
NavigationPage.SetHasNavigationBar(this, false);
Content = BuildGrid();
// Accomodate iPhone status bar.
Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 10);
}
private Grid BuildGrid()
{
return new Grid
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
RowDefinitions = {
new RowDefinition {
Height = GridLength.Auto
},
new RowDefinition {
Height = new GridLength (1, GridUnitType.Star)
},
},
ColumnDefinitions = {
new ColumnDefinition {
Width = new GridLength (100, GridUnitType.Absolute)
},
new ColumnDefinition {
Width = new GridLength (1, GridUnitType.Star)
},
},
Children =
{
{new Label {
Text = "Draw It",
Font = Font.BoldSystemFontOfSize (50),
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
}, 0, 2, 0, 1},
{BuildPalletFrame(), 0, 1},
{new ContentView {
Content = BuildDrawingFrame(),
Padding = new Thickness(10, 0, 0, 0),
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
}, 1, 1}
}
};
}
private StackLayout CreatePalletStack()
{
BuildColorPallete();
var stack = new StackLayout
{
Spacing = PalleteSpacing,
Orientation = StackOrientation.Vertical,
VerticalOptions = LayoutOptions.FillAndExpand
};
stack.SizeChanged += OnStackSizeChanged;
foreach (var button in ColorPallete.Select(color => new Button
{
Text = color.Key,
TextColor = GetTextColor(color.Value),
BackgroundColor = color.Value,
Font = Font.BoldSystemFontOfSize(NamedSize.Medium),
}))
{
button.Clicked += OnButtonClicked;
stack.Children.Add(button);
}
var saveButton = new Button
{
Text = "Save",
};
saveButton.Clicked += OnSaveButtonClicked;
stack.Children.Add(saveButton);
return stack;
}
private void OnSaveButtonClicked(object sender, EventArgs e)
{
Navigation.PushModalAsync(new ShowImage(DrawingImage, "Test"));
}
// Formula for computing Luminance out of R G B, which is something close to luminance = (red * 0.3) + (green * 0.6) + (blue * 0.1).
// Original Source: http://stackoverflow.com/questions/20978198/how-to-match-uilabels-textcolor-to-its-background
private static Color GetTextColor(Color backgroundColor)
{
var backgroundColorDelta = ((backgroundColor.R * 0.3) + (backgroundColor.G * 0.6) + (backgroundColor.B * 0.1));
return (backgroundColorDelta > 0.4f) ? Color.Black : Color.White;
}
private Frame BuildPalletFrame()
{
var palleteFrame = new Frame
{
BackgroundColor = Color.White,
Padding = 5,
Content = CreatePalletStack()
};
return palleteFrame;
}
private Frame BuildDrawingFrame()
{
DrawingImage = new ImageWithTouch
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
BackgroundColor = Color.White,
CurrentLineColor = Color.Black
};
DrawingImage.SetBinding(ImageWithTouch.CurrentLineColorProperty, "CurrentLineColor");
var palleteFrame = new Frame
{
BackgroundColor = Color.White,
Padding = 5,
HasShadow = false,
OutlineColor = Color.Black,
Content = DrawingImage
};
return palleteFrame;
}
private void BuildColorPallete()
{
ColorPallete = new Dictionary<string, Color>
{
{ "White", Color.White },
{ "Silver", Color.Silver },
{ "Gray", Color.Gray },
{ "Yellow", Color.Yellow },
{ "Aqua", Color.Aqua },
{ "Blue", Color.Blue },
{ "Navy", Color.Navy },
{ "Lime", Color.Lime },
{ "Green", Color.Green },
{ "Teal", Color.Teal },
{ "Olive", Color.Olive },
{ "Fuschia", Color.Fuschia },
{ "Red", Color.Red },
{ "Purple", Color.Purple },
{ "Maroon", Color.Maroon },
{ "Black", Color.Black },
};
}
#region Event Handlers
private void OnButtonClicked(object sender, EventArgs e)
{
var button = (Button)sender;
DrawingImage.CurrentLineColor = button.BackgroundColor;
}
private void OnStackSizeChanged(object sender, EventArgs args)
{
var stackLayout = (StackLayout)sender;
var width = stackLayout.Width;
var height = stackLayout.Height;
if (width <= 0 || height <= 0)
{
return;
}
var stackChildSize = height / stackLayout.Children.Count;
var font = Font.BoldSystemFontOfSize(0.4 * stackChildSize);
foreach (var button in stackLayout.Children.Cast<Button>())
{
button.Font = font;
button.HeightRequest = stackChildSize - PalleteSpacing;
}
}
#endregion
}
}
My code for the next screen to load is:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ShowImage : ContentPage
{
public ShowImage (Image image, string message)
{
InitializeComponent ();
NewText.Text = "This is a long test " + message;
CreatedImage.Source = image.Source;
}
}
}
The source of the image in the ShowImage is always empty and it's not showing the drawn image. It shows the message I sent.
How can I show the image in the next screen?
Can I convert it to a bytearray or something? FYI: I would like to send it to a (C#) webservice next.
I've tested this on UWP and Android.
Related
I want to display text in a format in label, but it's displaying an incorrect value.
It's showing the correct value in debug mode. But its displayed wrong on the screen. Ideally, the screen should display total and subtotal as image one.
Code to format string
string paymentFormat = "{0,-25} {1,8}\n";
string paymentMode = "Total"; // Or Subtotal
string paymentAmount = "604.00";
string test = string.Format(paymentFormat, paymentMode, paymentAmount);
Update
public class AlertPopupViewItem : ContentView
{
Label HeaderLabel,MessageLabel;
public Button OKButton, CancelButton;
AbsoluteLayout _overlay;
LoggerService logservice;
public bool ButtonValue = false;
StackLayout CancelStackLayout, OKStackLayout;
string PageSource = string.Empty;
public AlertPopupViewItem()
{
logservice = new LoggerService();
logservice.WriteData(Constants.DEBUG_LOGGING, "Alert Message Popup ctor.. Start");
_overlay = new AbsoluteLayout
{
BackgroundColor = Color.Black.MultiplyAlpha(0.5),
HorizontalOptions = LayoutOptions.Fill,
VerticalOptions = LayoutOptions.Fill,
};
Grid mainGrid = new Grid
{
HeightRequest = 40,
BackgroundColor = Color.White,
Padding = 20,
RowDefinitions =
{
new RowDefinition { Height = new GridLength(15, GridUnitType.Star) },//0 Title
new RowDefinition { Height = new GridLength(3, GridUnitType.Star) },//1 Line
new RowDefinition { Height = new GridLength(80, GridUnitType.Star) },//2 Message
new RowDefinition { Height = new GridLength(12, GridUnitType.Star) },//3 OK-Cancel
}
};
HeaderLabel = new Label
{
FontAttributes = FontAttributes.Bold,
FontSize = 22,
TextColor = Color.Black,
HorizontalTextAlignment= TextAlignment.Center,
VerticalTextAlignment = TextAlignment.Center,
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions =LayoutOptions.CenterAndExpand
};
BoxView divider = new BoxView
{
HeightRequest = 1,
Color = Color.Gray,
VerticalOptions = LayoutOptions.End,
};
MessageLabel = new Label
{
FontAttributes = FontAttributes.None,
FontSize = 13,
HorizontalTextAlignment = TextAlignment.Start,
VerticalTextAlignment = TextAlignment.Center,
HorizontalOptions = LayoutOptions.StartAndExpand,
TextColor = Color.Black
};
ScrollView scroll = new ScrollView()
{
Orientation = ScrollOrientation.Vertical
};
scroll.Content = MessageLabel;
Grid ButtonGrid = new Grid
{
HeightRequest = 35,
ColumnDefinitions =
{
new ColumnDefinition {Width=new GridLength(58,GridUnitType.Star) },
new ColumnDefinition {Width=new GridLength(20,GridUnitType.Star) },
new ColumnDefinition {Width=new GridLength(2,GridUnitType.Star) },
new ColumnDefinition {Width=new GridLength(20,GridUnitType.Star) }
}
};
CancelStackLayout = new StackLayout
{
Padding = new Thickness(-6, -6, -6, -6),
//VerticalOptions = LayoutOptions.Center,
BackgroundColor = Color.FromHex("#ff9500")
};
CancelButton = new Button
{
TextColor = Color.White,
FontSize = 15,
BorderRadius = 0,
Text = Localizer.Localize("CancelSmall"),
BackgroundColor = Color.FromHex("#01458e"),
HorizontalOptions =LayoutOptions.FillAndExpand,
VerticalOptions=LayoutOptions.FillAndExpand,
BorderColor = Color.Transparent
};
CancelButton.Clicked += CancelButtonClicked;
CancelStackLayout.Children.Add(CancelButton);
ButtonGrid.Children.Add(CancelStackLayout, 1, 0);
OKStackLayout = new StackLayout
{
Padding = new Thickness(-6, -6, -6, -6),
BackgroundColor = Color.FromHex("#ff9500")
};
OKButton = new Button
{
TextColor = Color.White,
FontSize = 15,
BorderRadius = 0,
Text = Localizer.Localize("OK"),
BackgroundColor = Color.FromHex("#01458e"),
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
BorderColor = Color.Transparent
};
OKButton.Clicked += OKButtonClicked;
OKStackLayout.Children.Add(OKButton);
ButtonGrid.Children.Add(OKStackLayout, 3, 0);
mainGrid.Children.Add(HeaderLabel, 0, 0);
mainGrid.Children.Add(divider, 0, 1);
mainGrid.Children.Add(scroll, 0, 2);
mainGrid.Children.Add(ButtonGrid, 0, 3);
AbsoluteLayout.SetLayoutFlags(mainGrid, AbsoluteLayoutFlags.All);
AbsoluteLayout.SetLayoutBounds(mainGrid, Findlayoutbounds(new Rectangle(0.20, 0.25, 0.5, 0.50)));
_overlay.Children.Add(mainGrid);
Content = _overlay;
logservice.WriteData(Constants.DEBUG_LOGGING, "Alert Message Popup ctor.. End");
}
// ThreadHandle thread = new ThreadHandle();
private void CancelButtonClicked(object sender, EventArgs e)
{
ButtonValue = false;
this.IsVisible = false;
// thread.WorkMethod();
}
private void OKButtonClicked(object sender, EventArgs e)
{
ButtonValue = true;
if (PageSource == "StarterPage") ;
//MessagingCenter.Send(this, "ModifyValBooleanForAlert");
this.IsVisible = false;
// thread.WorkMethod();
}
Rectangle Findlayoutbounds(Rectangle fractionalRect)
{
if (fractionalRect.Width - 1 == 0)
fractionalRect.Width = 0.99;
if (fractionalRect.Height - 1 == 0)
fractionalRect.Height = 0.99;
Rectangle layoutbounds = new Rectangle
{
X = fractionalRect.X / (1 - fractionalRect.Width),
Y = fractionalRect.Y / (1 - fractionalRect.Height),
Width = fractionalRect.Width,
Height = fractionalRect.Height
};
return layoutbounds;
}
public void DisplayAlertPopup(string alertBoxTitle, string alertBoxContent,bool CancelDisplay)
{
HeaderLabel.IsVisible = false;
CancelStackLayout.IsVisible = CancelDisplay;
CancelButton.IsVisible = CancelDisplay;
HeaderLabel.Text = alertBoxTitle;
MessageLabel.Text = alertBoxContent;
OKButton.Text = Localizer.Localize("OK");
CancelButton.Text = Localizer.Localize("CancelSmall");
HeaderLabel.IsVisible = true;
}
public void DisplayAlertPopup(string alertBoxTitle, string alertBoxContent, string ButtonText)
{
CancelStackLayout.IsVisible = false;
CancelButton.IsVisible = false;
HeaderLabel.Text = alertBoxTitle;
MessageLabel.Text = alertBoxContent;
OKButton.Text = ButtonText;
}
public void DisplayAlertConditionalPopup(string alertBoxTitle, string alertBoxContent, bool CancelDisplay)
{
CancelStackLayout.IsVisible = CancelDisplay;
CancelButton.IsVisible = CancelDisplay;
HeaderLabel.Text = alertBoxTitle;
MessageLabel.Text = alertBoxContent;
this.IsVisible = true;
}
public void SetButtonText(string OKText, string CancelText)
{
if (OKText != null)
OKButton.Text = OKText;
if (CancelText != null)
CancelButton.Text = CancelText;
}
}
I get the formatted string from some other class and call the DisplayAlertPopup method. MessageLabel is the label for which I am setting this value.
Update2:
As suggested in answer, I have tried the below code to set the font for Android. But its also not displying the text in the required format.
MessageLabel = new Label
{
FontAttributes = FontAttributes.None,
FontSize = 13,
HorizontalTextAlignment = TextAlignment.Start,
VerticalTextAlignment = TextAlignment.Center,
HorizontalOptions = LayoutOptions.StartAndExpand,
TextColor = Color.Black,
FontFamily = "Droid Sans Mono"
};
You will need to use a fixed-width font. There is unfortunately none that is built-in across all platforms, but each platform has its own:
iOS - Courier New
Android - Droid Sans Mono
UWP - Consolas
If no built-in font suits you or you want to have the same experience on all platforms, you can also use custom fonts in Xamarin.Forms. This requires you to find a fixed-width font you like on a service like Google Fonts. Then you can follow the tutorial here on Xamarin Help, that describes how to include the TTF file in each platform and use it from XAML.
The short summary is:
Add the font to each platform project with appropriate build action (UWP - Content, iOS - Bundle Resource, Android - Android Asset)
Use the OnPlatform syntax to set the font (ideally creating a static resource so that it can be reused):
Resource:
<OnPlatform x:TypeArguments="x:String" x:Key="MyFontFamily">
<On Platform="Android" Value="MyFont.ttf#Open Sans" />
<On Platform="UWP" Value="/Assets/MyFont.ttf#Open Sans" />
<On Platform="iOS" Value="MyFont" />
</OnPlatform>
And use like this:
<Label FontFamily="{StaticResource MyFontFamily}" />
There is a label in the page Account which when tapped on will create a new ContentPage with a list of premise addresses. Tapping on any of the addresses should pop the ContentPage and send back a value to the Account page to set certain fields within the Account page. I tried to use Messaging center but it doesn't seem to be able to get the value. What am I missing?
This is the code that creates the ContentPage with the premise addresses:
private void ddlPremisesAddNavigation()
{
PremiseListPage = CreatePAContentPage();
var tgrddlPremiseAddress = new TapGestureRecognizer();
NavigationPage.SetHasNavigationBar(PremiseListPage, false);
tgrddlPremiseAddress.Tapped += (s, e) =>
{
Navigation.PushAsync(PremiseListPage);
};
// ddlPremiseAddresses.GestureRecognizers.Add(tgrddlPremiseAddress);
lblpremiseAddress.GestureRecognizers.Add(tgrddlPremiseAddress);
}
private ContentPage CreatePAContentPage()
{
#region Containers
ContentPage content = new ContentPage();
StackLayout pageContent = new StackLayout();
ScrollView addressesView = new ScrollView()
{
// BackgroundColor = Color.White,
Padding = new Thickness(20, 10, 20, 10)
};
StackLayout addressContainer = new StackLayout();
#endregion
#region Header
RowDefinitionCollection RowDefinitions = new RowDefinitionCollection();
ColumnDefinitionCollection ColumnDefinitions = new ColumnDefinitionCollection();
RowDefinitions.Add(new RowDefinition { Height = new GridLength(50, GridUnitType.Absolute) });
Grid header = new Grid()
{
RowDefinitions = RowDefinitions,
};
BoxView bg = new BoxView() { HeightRequest = 50, WidthRequest = 250, BackgroundColor = Color.White };
header.Children.Add(bg, 0, 0);
Grid.SetColumnSpan(bg, 5);
Label title = new Label()
{
Text = "Premise Address",
FontSize = 15,
FontAttributes = FontAttributes.Bold,
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand
};
header.Children.Add(title, 1, 0);
Grid.SetColumnSpan(title, 3);
Button back = new Button() { Image = "backArrow", BackgroundColor = Color.White };//
header.Children.Add(back, 0, 0);
Grid.SetColumnSpan(back, 1);
back.Clicked += back_Clicked;
#endregion
#region Address Frames
List<Frame> addrFrames = new List<Frame>();
if (premiseAddresses.Count <= 0)
{
foreach (PremisesModel premise in Premises)
{
premiseAddresses.Add(premise.PremiseId, premise.PremiseAddress);
}
}
foreach (KeyValuePair<int,string> item in premiseAddresses)
{
addrFrames.Add(CreatePAFrame(item));
}
#endregion
#region Add Content to Containers
foreach (Frame item in addrFrames)
{
addressContainer.Children.Add(item);
}
// < Button x: Name = "btnReqAmendment" Text = "Request amendment" Style = "{StaticResource buttonStyle}" Clicked = "btnReqAmendment_Clicked" />
Button addNew = new Button()
{
Text = "ADD NEW PREMISE ADDRESS",
Style = Application.Current.Resources["buttonStyle"] as Style,
HorizontalOptions = LayoutOptions.CenterAndExpand,
Margin = new Thickness(0, 20, 2, 15)
//FontSize = 12,
//WidthRequest = 220,
//HeightRequest = 40
};
addNew.Clicked += btnAddNewPremise_Clicked;
addressContainer.Children.Add(addNew);
addressesView.Content = addressContainer;
pageContent.Children.Add(header);
pageContent.Children.Add(addressesView);
content.Content = pageContent;
#endregion
return content;
}
private Frame CreatePAFrame(KeyValuePair<int, string> premiseAddress)
{
Frame frame = new Frame() { Padding = new Thickness(5, 5, 3, 5), HeightRequest = 60 };
StackLayout content = new StackLayout() { Padding = 0 };
content.Orientation = StackOrientation.Horizontal;
Label pAddress = new Label();
pAddress.Text = premiseAddress.Value;
pAddress.Style = Application.Current.Resources["LabelStart"] as Style;
pAddress.HeightRequest = 50;
pAddress.HorizontalOptions = LayoutOptions.StartAndExpand;
Image img = new Image()
{
Source = "rightArrow",
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.CenterAndExpand
};
content.Children.Add(pAddress);
content.Children.Add(img);
frame.Content = content;
var selectAddress = new TapGestureRecognizer();
selectAddress.Tapped += (s, e) =>
{
MessagingCenter.Send(this, "premiseId", premiseAddress.Key);
Navigation.PopAsync();
};
frame.GestureRecognizers.Add(selectAddress);
return frame;
}
And this is how it subscribes to Messaging center:
public Account()
{
MessagingCenter.Subscribe<ContentPage,int>(this, "premiseId", (sender,arg) =>
{
DisplayAlert("Premise Changed", "test", "OK");
selectedPremise = arg;
DisplaySelectedPremiseValues();
});
InitializeComponent();
}
One option could be using a global variable (e.g in App.cs) and setting this variable whenever a list item is tapped:
public static Address TappedAddress;
And before showing the listview reset that variable.
I am working on xamarin forms Cross platform.
I have a function createform in which i am calling the buildform function.My build form function is used to generate the UI.
I am callling my create form inside the constructor.
public FormsPage()
{
json = new JsonSerialize();
//Task.createForm("form5");
Task.Run(() => createForm("form5")).Wait();
}
public async void createForm(string path)
{
this.path = path;
definition =json.parseJson(path);
formdata = await json.parseJsonFormData(path);
//var x = (bool)formdata["Form"][1]["Section_OtherInfo"]["IsNop"];
// buildForm();
Device.BeginInvokeOnMainThread(buildForm);
}
If i am not using Device.BeginInvokeOnMainThread(buildForm) then it is throwing an exception for UWP.And If i am using Device.BeginInvokeOnMainThread(buildForm) then it is blocking the await operator.
The prototype of my BUildForm function is:
public void buildForm()
{
try
{
JToken y = formdata["Form"];
if (!(y.HasValues))
{
CreateJson();
}
data.Clear();
var section = new StackLayout
{
BackgroundColor = Color.White,
HorizontalOptions = LayoutOptions.FillAndExpand
};
var sectionLayout = new StackLayout
{
Padding = 10,
BackgroundColor = Color.White,
HorizontalOptions = LayoutOptions.FillAndExpand
};
var sectionheader = new StackLayout
{
BackgroundColor = Color.FromHex("#7635EB"),
HorizontalOptions = LayoutOptions.FillAndExpand
};
var mainLayout = new StackLayout
{
Padding = 10,
BackgroundColor = Color.FromHex("#DCDCDC")
};
var horizontalLayoutNaNop = new StackLayout
{
Orientation = StackOrientation.Horizontal,
BackgroundColor = Color.White
};
var horizontalLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
BackgroundColor = Color.White
};
this.Title = definition.Title;
//foreach (var sc in definition.Section)
for (var i = 0; i < definition.Section.Count; i++)
{
section = new StackLayout
{
BackgroundColor = Color.White,
HorizontalOptions = LayoutOptions.FillAndExpand
};
sectionheader = new StackLayout
{
BackgroundColor = Color.FromHex("#7635EB"),
HorizontalOptions = LayoutOptions.FillAndExpand
};
horizontalLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
BackgroundColor = Color.White
};
sectionLayout = new StackLayout
{
Padding = 10,
BackgroundColor = Color.White,
HorizontalOptions = LayoutOptions.FillAndExpand
};
if (definition.Section[i].SectionTitle != string.Empty)
{
var title = new Label
{
Text = definition.Section[i].SectionTitle,
HorizontalTextAlignment = TextAlignment.Start,
TextColor = Color.White,
FontSize = 20,
FontAttributes = FontAttributes.Bold,
Margin = new Thickness(10, 5, 5, 5)
};
sectionheader.Children.Add(title);
section.Children.Add(sectionheader);
}
if (definition.Section[i].IsNa || definition.Section[i].IsNop)
{
horizontalLayoutNaNop = new StackLayout
{
Orientation = StackOrientation.Horizontal,
BackgroundColor = Color.White
};
if (definition.Section[i].IsNa)
{
if ((string)formdata["Form"][i][definition.Section[i].SectionId]["IsNa"] == string.Empty)
{
formdata["Form"][i][definition.Section[i].SectionId]["IsNa"] = false;
}
var Na = new KanCheckBox("NA");
Na.StyleId = "IsNa";
Na.IsChecked = (bool)formdata["Form"][i][definition.Section[i].SectionId]["IsNa"];
data.Add("IsNa", (string)formdata["Form"][i][definition.Section[i].SectionId]["IsNa"]);
Na.OnCheckedChange += (object s, bool IsChecked) =>
{
data[Na.StyleId] = Convert.ToString(IsChecked);
};
horizontalLayoutNaNop.Children.Add(Na);
}
if (definition.Section[i].IsNop)
{
if ((string)formdata["Form"][i][definition.Section[i].SectionId]["IsNop"] == string.Empty)
{
formdata["Form"][i][definition.Section[i].SectionId]["IsNop"] = false;
}
var Nop = new KanCheckBox("No Problem Found");
Nop.StyleId = "IsNop";
Nop.IsChecked = (bool)formdata["Form"][i][definition.Section[i].SectionId]["IsNop"];
data.Add("IsNop", (string)formdata["Form"][i][definition.Section[i].SectionId]["IsNop"]);
Nop.OnCheckedChange += (object s, bool IsChecked) =>
{
data[Nop.StyleId] = Convert.ToString(IsChecked);
};
horizontalLayoutNaNop.Children.Add(Nop);
}
sectionLayout.Children.Add(horizontalLayoutNaNop);
sectionLayout.Children.Add(new BoxView
{
BackgroundColor = Color.FromHex("#ECECEC"),
HeightRequest = 1,
HorizontalOptions = LayoutOptions.FillAndExpand
});
}
if (definition.Section[i].subsection.Count != 0)
{
foreach (var sub in definition.Section[i].subsection)
{
if (sub.SubSectionTitle != string.Empty)
{
var subtitle = new Label
{
Text = sub.SubSectionTitle,
HorizontalTextAlignment = TextAlignment.Start,
FontSize = 15,
FontAttributes = FontAttributes.Bold,
TextColor = Color.FromHex("#7635EB")
};
sectionLayout.Children.Add(subtitle);
}
// (string)formdata["Form"][i][definition.Section[i].SectionId][el.Property]
foreach (var el in sub.elements)
{
var x = el.Type;
//AddElements(el, true, i, definition.Section[i].SectionId, sectionLayout, horizontalLayout);
int lvl = 0;
Dictionary<string, List<FormElement>> dt = new Dictionary<string, List<FormElement>>();
List<FormElement> lt = new List<FormElement>();
Stack<FormElement> stk = new Stack<FormElement>();
stk.Push(el);
while (stk.Count > 0)
{
var parent = stk.Pop();
if (parent.Elements.Count != 0)
{
AddElements(parent, true, i, definition.Section[i].SectionId, sectionLayout, horizontalLayout);
while (stk.Count != 0)
{
lt.Add(stk.Pop());
}
if (lt.Count != 0)
{
dt.Add("child" + lvl, lt);
lt = new List<FormElement>();
lvl++;
}
for (var j = 1; j <= parent.Elements.Count; j++)
{
stk.Push(parent.Elements[parent.Elements.Count - j]);
}
}
else
{
if (stk.Count > 0)
{
AddElements(parent, false, i, definition.Section[i].SectionId, sectionLayout, horizontalLayout);
}
else
{
AddElements(parent, false, i, definition.Section[i].SectionId, sectionLayout, horizontalLayout);
if (dt.Count > 0)
{
lt = dt["child" + lvl];
dt.Remove("child" + lvl);
for (var j = 1; j <= lt.Count; j++)
{
stk.Push(lt[lt.Count - j]);
lvl--;
}
}
}
}
}
if (horizontalLayout.Children.Count != 0)
{
sectionLayout.Children.Add(horizontalLayout);
horizontalLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
BackgroundColor = Color.White
};
}
}
}
}
section.Children.Add(sectionLayout);
mainLayout.Children.Add(section);
}
this.Content = new ScrollView
{
Content = mainLayout
};
}
catch(Exception ex)
{
}
}
Here i am trying to generate the form dynamically using BuildForm.
For the first time it is generating the ui without any problem.
And when the createform is called again then the await operator is blocked.
Is there any way to get to know that MainThread has stopped executing?
Or Any way to create the child thread as a main thread so that my await operator works.
I think you are a little confused with the concepts here. My Spidey Senses tells me the deadlock is because of an Unhandled Exception regardless of the UI
The first thing is the async void looks suspicious, secondly i think there is an Exception happening somewhere regardless (and you need to figure that out)
private void Start()
{
// invoke
Device.BeginInvokeOnMainThread(SomeMethod);
}
private async void SomeMethod()
{
try
{
// await method
await SomeAsyncMethod();
}
catch (Exception e) // handle whatever exceptions you expect
{
//Handle exceptions
}
}
private async Task SomeAsyncMethod()
{
// in this case lets push a new page
await Navigation.PushModalAsync(new ContentPage());
}
Although this is an example the take home here is, if there is a chance of not being on the UI thread, dispatch it on the main thread and if you are going down the road of fire-and-forget (suspicious) make sure you are handling your exceptions
Have you tryed calling the method asynchronoulsy?
private async Task ConectarWSAsync()
{
Device.BeginInvokeOnMainThread(
async () =>
{
lblStatus.Text = "Getting token WS...";
await ws.ConnectAsync();
lblStatus.Text = "WS connected";
}
);
}
When using ViewCell with TableView it shows a right arrow > (circled in red) and the whole cell can be touched - I suppose to select it and slide a new page from right to left to "drill into details".
Can someone advise on how to disable the display of > ?
Looks that ViewCell.IsEnabled = false turns off the touch action.
Here is some code in my class deriving from ContentPage that creates the table section:
public class SamplePage : ContentPage
{
public SamplePage()
{
var gridLengthStar = new GridLength(1, GridUnitType.Star);
// GRIDSAMPLE CODE
var gridSample = new Grid
{
RowDefinitions =
{
new RowDefinition {Height = GridLength.Auto},
new RowDefinition {Height = GridLength.Auto}
},
Padding = new Thickness(20, 20, 20, 20),
ColumnDefinitions =
{
new ColumnDefinition {Width = gridLengthStar},
new ColumnDefinition {Width = gridLengthStar}
},
};
gridSample.Children.Add ( new Label() { Text = "Data1" }, 0, 0);
gridSample.Children.Add ( new Label() { Text = "Data2" }, 1, 0);
gridSample.Children.Add ( new Label() { Text = "Data3" }, 0, 1);
gridSample.Children.Add ( new Label() { Text = "Data4" }, 1, 1);
var tableView = new TableView
{
HasUnevenRows = true,
Intent = TableIntent.Form,
};
tableView.Root = new TableRoot
{
new TableSection("SECTION TITLE")
{
(new ViewCell {View = gridSample, IsEnabled = false})
}
};
Content = new StackLayout()
{
Children = { tableView } ,
Orientation = StackOrientation.Vertical,
VerticalOptions = LayoutOptions.Start,
Spacing = 10
};
}
}
That arrow can be shown on iOS if you set
Accessory = UITableViewCellAccessory.DisclosureIndicator;
in your UITableViewCell.
Xamarin.Forms usually doesn't set this, so the arrow should not be shown. If it is there, then you have some renderer, Effect or other component which sets it in the iOS code.
I am having issues with getting a Toolbar displaying on my form. The form is ConfigurationPage.cs. I am including the pages that navigate to the ConfigurationPage and the page itself. Any idea why the Toolbar is not displaying?
App Section
public App()
{
// The root page of your application
MainPage = new NavigationPage(new MainPage());
}
Main Page
public class MainPage : ContentPage
{
public MainPage()
{
BackgroundColor = Color.White;
var setup = new Button
{
Text = "Lane Configuration",
TextColor = Color.Black
};
setup.Clicked += (sender, args) =>
{
Navigation.PushModalAsync(new ConfigurationPage());
};
var gateGridLayout = new Grid
{
Padding = new Thickness(5),
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
RowDefinitions = {new RowDefinition{ Height = new GridLength (1, GridUnitType.Auto) }},
ColumnDefinitions = {new ColumnDefinition{ Width = GridLength.Auto }}
};
gateGridLayout.Children.Add(setup, 0, 0);
Content = gateGridLayout;
}
}
Configuration Page - Toolbar not displaying here
public class ConfigurationPage : ContentPage
{
public event EventHandler SaveToDatabaseCompleted;
public ConfigurationPage()
{
BackgroundColor = Color.White;
var viewModel = new ConfigurationViewModel(this);
BindingContext = viewModel;
var lblIPAddress = new Label
{
Text = "IP Address",
TextColor = Color.Black
};
var IPAddress = new Entry
{
Text = string.Empty,
TextColor = Color.White,
BackgroundColor = Color.Blue,
HorizontalOptions = LayoutOptions.FillAndExpand
};
IPAddress.SetBinding(Entry.TextProperty, "IPAddress");
var lblUserName = new Label
{
Text = "UserName",
TextColor = Color.Black
};
var UserName = new Entry
{
Text = string.Empty,
TextColor = Color.White,
BackgroundColor = Color.Blue,
HorizontalOptions = LayoutOptions.FillAndExpand
};
UserName.SetBinding(Entry.TextProperty, "UserName");
var lblPassword = new Label
{
Text = "Password",
TextColor = Color.Black
};
var Password = new Entry
{
Text = string.Empty,
TextColor = Color.White,
BackgroundColor = Color.Blue,
HorizontalOptions = LayoutOptions.FillAndExpand
};
Password.SetBinding(Entry.TextProperty, "Password");
var lblXml = new Label
{
Text = "XML Page",
TextColor = Color.Black,
};
Picker picker = new Picker
{
Title = "XML Settings",
BackgroundColor = Color.Blue,
VerticalOptions = LayoutOptions.FillAndExpand
};
var options = new List<string> { "val1.xml", "val2.xml" };
foreach (string optionName in options)
{
picker.Items.Add(optionName);
}
string selected = string.Empty;
var lblXMLEntry = new Label
{
Text = "Selected XML Value",
TextColor = Color.Black
};
var XML = new Entry
{
IsEnabled = false,
Text = selected,
TextColor = Color.White,
BackgroundColor = Color.Blue,
HorizontalOptions = LayoutOptions.FillAndExpand
};
XML.SetBinding(Entry.TextProperty, "XML");
picker.SelectedIndexChanged += (sender, args) =>
{
if (picker.SelectedIndex == 0)
selected = picker.Items[0];
else if (picker.SelectedIndex == 1)
selected = picker.Items[1];
XML.Text = selected;
};
var IPAddressLblStack = new StackLayout
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
Orientation = StackOrientation.Horizontal,
Children = {
lblIPAddress
}
};
var UserNameLblStack = new StackLayout
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
Orientation = StackOrientation.Horizontal,
Children = {
lblUserName
}
};
var PasswordLblStack = new StackLayout
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
Orientation = StackOrientation.Horizontal,
Children = {
lblPassword
}
};
var XMLLblStack = new StackLayout
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
Orientation = StackOrientation.Horizontal,
Children = {
lblXml
}
};
var PickerStack = new StackLayout
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
Orientation = StackOrientation.Horizontal,
Children = {
picker
}
};
var XMLLblEntry = new StackLayout
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
Orientation = StackOrientation.Horizontal,
Children = {
lblXMLEntry
}
};
var gateGridLayout = new Grid
{
Padding = new Thickness(5),
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
RowDefinitions = {
new RowDefinition{ Height = new GridLength (1, GridUnitType.Auto) },
new RowDefinition{ Height = new GridLength (1, GridUnitType.Auto) },
new RowDefinition{ Height = new GridLength (1, GridUnitType.Auto) },
new RowDefinition{ Height = new GridLength (1, GridUnitType.Auto) },
new RowDefinition{ Height = new GridLength (1, GridUnitType.Auto) },
new RowDefinition{ Height = new GridLength (1, GridUnitType.Auto) },
new RowDefinition{ Height = new GridLength (1, GridUnitType.Auto) },
new RowDefinition{ Height = new GridLength (1, GridUnitType.Auto) },
new RowDefinition{ Height = new GridLength (1, GridUnitType.Auto) },
new RowDefinition{ Height = new GridLength (1, GridUnitType.Auto) }
},
ColumnDefinitions = {
new ColumnDefinition{ Width = GridLength.Auto }//,
}
};
gateGridLayout.Children.Add(IPAddressLblStack, 0, 1);
gateGridLayout.Children.Add(IPAddress, 0, 2);
gateGridLayout.Children.Add(UserNameLblStack, 0, 3);
gateGridLayout.Children.Add(UserName, 0, 4);
gateGridLayout.Children.Add(PasswordLblStack, 0, 5);
gateGridLayout.Children.Add(Password, 0, 6);
gateGridLayout.Children.Add(XMLLblStack, 0, 7);
gateGridLayout.Children.Add(PickerStack, 0, 8);
gateGridLayout.Children.Add(XMLLblEntry, 0, 9);
gateGridLayout.Children.Add(XML, 0, 10);
var saveButtonToolbar = new ToolbarItem();
saveButtonToolbar.Text = "Save";
saveButtonToolbar.SetBinding(ToolbarItem.CommandProperty, "SaveButtonTapped");
saveButtonToolbar.Priority = 0;
ToolbarItems.Add(saveButtonToolbar);
var cancelButtonToolbar = new ToolbarItem();
cancelButtonToolbar.Text = "Cancel";
cancelButtonToolbar.Command = new Command(async () => await PopModalAsync(true));
cancelButtonToolbar.Priority = 1;
ToolbarItems.Add(cancelButtonToolbar);
Content = gateGridLayout;
}
public void HandleSaveToDatabaseCompleted(object sender, EventArgs e)
{
if (SaveToDatabaseCompleted != null)
SaveToDatabaseCompleted(this, new EventArgs());
}
public async Task PopModalAsync(bool isAnimated)
{
await Navigation.PopModalAsync(true);
}
}
Figured it out. The MainPage setup.clicked event needs to be changed to the below code.
setup.Clicked += async (sender, args) =>
{
await Navigation.PushModalAsync(new NavigationPage(new ConfigurationPage()));
};