Add multiple labels through code - c#

I am coding a social networking app using Xamarin in Visual Studio, its a portable project with an Android and iOS project.
When the MainPage class is navigated to it opens a URL and reads the page and saves it as a string. I need it to split at every "". I'm thinking I should use a for loop but I don't know what to do next. I would like each chunk to have its own layout box, I have yet to learn which layout to use and what each one is best for. In each box, it would have a label (content) and possibly an image (if the post comes with one, it would be a URL so it would open the URL and display that image)
Basically for each one I want to be able to edit the following
for(string chunk : data.split("<br/">){
<Layout?>
<label Text="*Content from the current chunk*"/>
if(*contains image*){
<image>*Open url and display the image*</image>
}
</Layout?>
}
This is also all inside of a scrollview so they all scroll together...

Parsing of chunk strings not shown.
MainPage.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:StackOverflow1"
x:Class="StackOverflow1.MainPage"
Appearing="ContentPage_Appearing">
<ScrollView>
<StackLayout x:Name="mainStackLayout" />
</ScrollView>
</ContentPage>
MainPage.xaml.cs:
// ...
public partial class MainPage : ContentPage
{
private List<Chunk> chunks = new List<Chunk>();
// ...
private void ContentPage_Appearing(object sender, EventArgs e)
{
StackLayout childLayout;
foreach (Chunk chunk in chunks)
{
childLayout = new StackLayout();
Image image = new Image() { Source = chunk.url, HorizontalOptions = LayoutOptions.Start };
Label label = new Label() { Text = chunk.text, HorizontalOptions = LayoutOptions.Start };
childLayout.Children.Add(image);
childLayout.Children.Add(label);
mainStackLayout.Children.Add(childLayout);
}
}
}
// ...

Related

Tab view not working right on UWP Windows UI Library

I am making an app for UWP on Visual Studio that uses the Windows UI Library for the tab view component. I was following the documentation and it gives the following code to use:
xaml:
<muxc:TabView AddTabButtonClick="TabView_AddTabButtonClick" TabCloseRequested="TabView_TabCloseRequested"/>
c#:
// Add a new Tab to the TabView
private void TabView_AddTabButtonClick(muxc.TabView sender, object args)
{
var newTab = new muxc.TabViewItem();
newTab.IconSource = new muxc.SymbolIconSource() { Symbol = Symbol.Document };
newTab.Header = "New Document";
// The Content of a TabViewItem is often a frame which hosts a page.
Frame frame = new Frame();
newTab.Content = frame;
frame.Navigate(typeof(Page1));
sender.TabItems.Add(newTab);
}
// Remove the requested tab from the TabView
private void TabView_TabCloseRequested(muxc.TabView sender, muxc.TabViewTabCloseRequestedEventArgs args)
{
sender.TabItems.Remove(args.Tab);
}
I added that code to my project and and at first glance it looks normal.
However when try to interact, there are problems. I can only create a new tab if I click at the very bottom edge of the " + " icon. I also cant exit any tabs or interact with them.Here's a gif of my problem:
https://im7.ezgif.com/tmp/ezgif-7-565b1f0b4531.gif
Does anybody have a fix for this?
Thanks for any help
You need to create a TabStripHeader and TabStripFooter.
TabStripHeader's children is Grid and set name it to ShellTitlebarInset,
TabStripFooter's children is Grid and set name it to CustomDragRegion
and set background to Transparent for both.
Use CustomDragRegion as Title Bar.
Like Example:-
<muxc:TabView>
<muxc:TabView.TabStripHeader>
<Grid x:Name="ShellTitlebarInset" Background="Transparent" />
</muxc:TabView.TabStripHeader>
<muxc:TabView.TabStripFooter>
<Grid Grid.Column="3" x:Name="CustomDragRegion" Background="Transparent" />
</muxc:TabView.TabStripFooter>
</muxc:TabView>
And C# Example:-
public MainPage()
{
this.InitializeComponent();
var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;
coreTitleBar.LayoutMetricsChanged += CoreTitleBar_LayoutMetricsChanged;
Window.Current.SetTitleBar(CustomDragRegion);
}
private void CoreTitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar sender, object args)
{
if (FlowDirection == FlowDirection.LeftToRight)
{
CustomDragRegion.MinWidth = sender.SystemOverlayRightInset;
ShellTitlebarInset.MinWidth = sender.SystemOverlayLeftInset;
}
else
{
CustomDragRegion.MinWidth = sender.SystemOverlayLeftInset;
ShellTitlebarInset.MinWidth = sender.SystemOverlayRightInset;
}
CustomDragRegion.Height = ShellTitlebarInset.Height = sender.Height;
}
Note: To ensure that the tabs in the title bar are not occluded by shell content, you must account for left and right overlays. In LTR layouts, the right inset includes the caption buttons and the drag region. The reverse is true in RTL. The SystemOverlayLeftInset and SystemOverlayRightInset values are in terms of physical left and right, so reverse these too when in RTL.
Click Here for More Information

How to fix "The property Content is set more than once" error in XAML when overriding the ContentProperty of ContentPage

Here is the code I have:
<?xml version="1.0" encoding="UTF-8" ?>
<pages:PopupPage
x:Class="Memorise.DecksTab.CopyDeckPopup"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup">
<Label />
<Label />
</pages:PopupPage>
With backing code:
csharp
[ContentProperty("Contents")]
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CopyDeckPopup : Rg.Plugins.Popup.Pages.PopupPage
{
StackLayout contentStack { get; } = new StackLayout()
{
Spacing = 0,
Padding = new Thickness(0),
Orientation = StackOrientation.Vertical
};
public IList<View> Contents { get => contentStack.Children; }
public CopyDeckPopup(string clickedDeckName, string clickedDeckDescription)
{
BindingContext = new CopyDeckPopupViewModel(clickedDeckName, clickedDeckDescription);
InitializeComponent();
Content = contentStack;
}
In the first XAML I am getting an error on the 2nd Label saying
The property "Content" is set more than once
I can reproduce the behavior.
Nevertheless, on my side even though VS displays that warning/error if i run the project it deploys correctly and both labels are displayed.
It seems that VS does not recognize that the ContentProperty is being overriden, and supposes instead that you are trying to add both Labels to Content, which is wrong since you are adding them to your custom ContentProperty Contents!
Please run the project and let me know if the deploy fails...
UPDATE
The whole issue looks to me like a limitation of VS. At the end it is just a warning, and you should be able to ignore it without any danger.
If on the other hand you opt to set the labels on code you could write
public CopyDeckPopup(string clickedDeckName, string clickedDeckDescription)
{
BindingContext = new CopyDeckPopupViewModel(clickedDeckName, clickedDeckDescription);
InitializeComponent();
Content = contentStack;
Contents.Add(new Label() { Text = "ABC" });
Contents.Add(new Label() { Text = "DEF" });
}
But now this looks redundant since as i understand ContentProperty's is an attribute that the
XAML processor uses to determine the content property.
Decorating types with ContentPropertyAttribute allows shorter XAML syntax.
If you code everything on C# just use the good old Stacklayout and write your code like
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CopyDeckPopup : Rg.Plugins.Popup.Pages.PopupPage
{
public CopyDeckPopup(string clickedDeckName, string clickedDeckDescription)
{
BindingContext = new CopyDeckPopupViewModel(clickedDeckName, clickedDeckDescription);
InitializeComponent();
StackLayout contentStack = new StackLayout()
{
Spacing = 0,
Padding = new Thickness(0),
Orientation = StackOrientation.Vertical,
Children =
{
new Label() { Text = "ABC" },
new Label() { Text = "ABC" }
}
};
Content = contentStack;
}

How to Display Pop Up when the Polygon is clicked in Xamarin Forms

I'm using WEB API to retrieve coordinates and display them as polygons on my Map.
Now I want to make those Polygons when they clicked to display a pop with more information from the API.
My Xaml:
<maps:Map x:Name="map">
<x:Arguments>
<maps:MapSpan>
<x:Arguments>
<maps:Position>
<x:Arguments>
<x:Double>-30.241943</x:Double>
<x:Double>25.771944</x:Double>
</x:Arguments>
</maps:Position>
<x:Double>
20
</x:Double>
<x:Double>
20
</x:Double>
</x:Arguments>
</maps:MapSpan>
</x:Arguments>
<maps:Map.MapElements>
</maps:Map.MapElements>
</maps:Map>
</StackLayout>
then my C# code for adding Polygons:
foreach (var tempList in AlertsList)
{
string alertType = tempList.AlertType;
if (alertType == "Advisory")
{
polygon = new Polygon();
polygon.StrokeColor = Color.FromHex("ffff00");
polygon.FillColor = Color.FromHex("ffff00");
polygon.StrokeWidth = 5f;
foreach (var Poly in tempList.Polygon)
{
float Lat = float.Parse(Poly[0]);
float Long = float.Parse(Poly[1]);
polygon.Geopath.Add(new Position(Lat, Long));
}
// add to map
map.MapElements.Add(polygon);
}
}
Add Gesture recognizer to your view and display the popup based on your requirement. You can add Gestures to any view in Xamarin Forms.
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += (s, e) => {
// handle the tap to display the popup here
};
[YourView].GestureRecognizers.Add(tapGestureRecognizer);
If you want to display a simple alert dialog then you can use the DisplayAlert in Xamarin forms to achieve the result. Refer the documentation here for more details.
If you wish to display customized popup based on your UI requirements, then there is an excellent open source plugin (Rg.Plugins.Popup) available for it. You can download the NuGet here. It has various examples as well for you to achieve what you want.
I hope that helps you.

Xamarin Forms Picker control opens when entering input in Entry control

For reproducing the problem, I have added 2 controls to a content page: Picker and Entry. The container is a TableView section.
If I click on the Entry control, causing the keyboard to open, or enter characters in it, the Picker selection is opening. It's opening every time I enter a character or removing one (so when the value is changing).
I don't have this problem if the main container isn't a TableView, but for example a StackLayout.
I have this problem since Xamarin Forms v3.3. In previous versions, like 3.2, this problem didn't exist. The problem also exists in the 3.4 beta.
Also: the problem only occurs in Android (version 4 - 9). Not in iOS.
Below you'll find my 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:PickerBugXF33"
x:Class="PickerBugXF33.MainPage">
<StackLayout>
<TableView x:Name="testTableView" Intent="Form" HasUnevenRows="true" />
</StackLayout>
</ContentPage>
Code behind:
using Xamarin.Forms;
namespace PickerBugXF33
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
testTableView.Root = new TableRoot();
var section = new TableSection("Test section");
testTableView.Root.Add(section);
var viewCell = new ViewCell();
section.Add(viewCell);
var stack = new StackLayout() { Orientation = StackOrientation.Vertical };
viewCell.View = stack;
var picker = new Picker();
picker.Items.Add("Test item in picker");
stack.Children.Add(picker);
var entry = new Entry();
stack.Children.Add(entry);
}
}
}
NB: This is a test project. The real live project is much larger in which the page has to be created via code.
Update 1, 11/9/2018: Might be solved by commit: https://github.com/xamarin/Xamarin.Forms/pull/4344/commits/8401d81745ad248b5b70aa669863c8b8c8753e66

Opening platform specific screens after login screen in cross platform shared code Xamarin?

I want to open an Android activity for Android devices and iOS screen for iOS devices from login screen. The code of the login screen, I have written is in shared portable code Area. I have used interface and #if ANDROID #endif, but it is also not working.
Android screen will only contain a textview and an iOS screen will contain a Image. This is my Login Page in portable folder
namespace DemoApp
{
public class HomePage : ContentPage
{
public HomePage()
{
var title = new Label
{
Text = "Welcome to CloudCakes",
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
var email = new Entry
{
Placeholder = "E-Mail",
};
var password = new Entry
{
Placeholder = "Password",
IsPassword = true
};
var login = new Button
{
Text = "Login"
};
// With the `PushModalAsync` method we navigate the user
// the the orders page and do not give them an option to
// navigate back to the Homepage by clicking the back button
login.Clicked += (sender, e) =>
{
App.UserPreferences.Open();
// await Navigation.PushModalAsync(new MainPage());
};
Content = new StackLayout
{
Padding = 30,
Spacing = 10,
Children = { title, email, password, login}
};
}
}
}
And, this is the page in Droid folder where I want to navigate on clicking login button
name space
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Page1 : IUserPreferences
{
public Page1()
{
InitializeComponent();
}
public void Open()
{
var title = new Label
{
Text = "Welcome to Xamarin Forms IOS Screen!!",
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
Content = new StackLayout
{
Padding = 30,
Spacing = 10,
Children = { title }
};
}
}
}
Open is a method of interface which is present in the portable folder.
I assume that you're using Xamarin.Forms, so what you need to do is actually quite easy to achieve.
Instead of having a separate page for each platform, create one new XAML page with the following code:
MainPage.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"
x:Class="YourApp.Views.MainPage">
<ContentView>
<OnPlatform x:TypeArguments="View">
<OnPlatform.iOS>
<Image Source="something.png" />
</OnPlatform.iOS>
<OnPlatform.Android>
<Label Text="Android" />
</OnPlatform.Android>
</OnPlatform>
</ContentView>
</ContentPage>
This way you can control what to have on the page for each platform.
To navigate to MainPage from your LoginPage, you need to implement the Clicked event (or preferrably use Commands) in the code behind (MainPage.xaml.cs) and do the navigation there:
private void SomeButton_Clicked(object sender, System.EventArgs e)
{
await this.Navigation.PushAsync(new MainPage());
}
In the long run, you should look into doing all this outside the code behind with ViewModel's and Commands.
Edit: Since the first solution didn't work for you, here's what to do:
1) Subclass ContentPage in your core project.
public class MainPage : ContentPage { }
2) Implement a PageRenderer for each platform separately. You'll be able to use native layout definition for your pages as you mentioned.
There's a great article on the Xamarin blog on how to achieve this. You can also find the source code on GitHub.

Categories