Stretched width for rotated UILabel - c#

Sorry i'm really can't figure out how is native iOS design works (i'm usually do Xamarin Forms design).
I have UIStackView
UIStackView stackView = new UIStackView(new CGRect(0, 0, View.Frame.Width, View.Frame.Height));
then i create UILabel, set AdjustsFontSizeToFitWidth = true because i need auto adjusted font size
after that i apply some rotation to it targetLabel.Transform = CGAffineTransform.MakeRotation(new nfloat(Math.PI * 270 / 180.0)); because i need to make vertical text.
and then i add this label to the stack. Of course i have some other setups too but i think they are doesn't matter.
my final step is to set new Frame for UILabel with fixed width. I tried set width by getting stack's height, i tried even set it to constant, but it doesn't work. Width of the label always looks like auto.
this is what i want:
but in fact, the target label is very small.
Full code here: (Note this is TodayExtension)
[Register("CodeBasedViewController")]
public class CodeBasedViewController : SLComposeServiceViewController, INCWidgetProviding
{
UIImage image;
private UILabel otherLabel;
private UILabel targetLabel;
public CodeBasedViewController(IntPtr handle) : base(handle)
{
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
UIStackView stackView = new UIStackView(new CGRect(0, 0, View.Frame.Width, View.Frame.Height));
View.AddSubview(stackView);
stackView.Axis = UILayoutConstraintAxis.Horizontal;
image = new UIImage("picture.png");
UIImageView imageView = new UIImageView(image)
{
ContentMode = UIViewContentMode.ScaleAspectFit
};
otherLabel = new UILabel
{
TextColor = UIColor.White,
Text = "someTextA",
Font = UIFont.SystemFontOfSize(40)
};
targetLabel = new UILabel
{
TextColor = UIColor.Black,
Text ="4",
TextAlignment = UITextAlignment.Left,
Font = UIFont.SystemFontOfSize(30),
AdjustsFontSizeToFitWidth = true,
Lines = 1
};
targetLabel.Transform = CGAffineTransform.MakeRotation(new nfloat(Math.PI * 270 / 180.0));
stackView.AddArrangedSubview(imageView);
stackView.AddArrangedSubview(otherLabel);
stackView.AddArrangedSubview(targetLabel);
stackView.Frame = new CGRect(View.Frame.Width / 2, 0,
otherLabel .IntrinsicContentSize.Width +
targetLabel.IntrinsicContentSize.Width +
View.Frame.Height
, View.Frame.Height);
stackView.Center = View.Center;
targetLabel.Frame = new CGRect(targetLabel.Frame.X, targetLabel.Frame.Y, 150, 150); //test constants
}
public void WidgetPerformUpdate(Action<NCUpdateResult> completionHandler)
{
completionHandler(NCUpdateResult.NewData);
}
}

Firstly, set the property Distribution of StackView
stackView.Distribution = UIStackViewDistribution.Fill;
And don't forget to set the Font of label at the same time
targetLabel.Frame = new CGRect(targetLabel.Frame.X, targetLabel.Frame.Y, 150, 150);
targetLabel.Font = UIFont.SystemFontOfSize(80);
Following is the full code , I set the frame just for test and you can set the frame as you want(if you want to set the equals the size of screen , you should set the frame of label and imageView at same time).
UIStackView stackView = new UIStackView(new CGRect(100,200,300,150));
View.AddSubview(stackView);
stackView.Distribution = UIStackViewDistribution.Fill;
stackView.Spacing = 10;
stackView.BackgroundColor = UIColor.LightGray;
stackView.Axis = UILayoutConstraintAxis.Horizontal;
UIImageView imageView = new UIImageView()
{
ContentMode = UIViewContentMode.ScaleAspectFit,
BackgroundColor = UIColor.Red
};
otherLabel = new UILabel
{
TextColor = UIColor.Black,
Text = "someTextA",
Font = UIFont.SystemFontOfSize(40)
};
targetLabel = new UILabel
{
TextColor = UIColor.Black,
Text = "4",
TextAlignment = UITextAlignment.Left,
Font = UIFont.SystemFontOfSize(100),
AdjustsFontSizeToFitWidth = true,
Lines = 0
};
targetLabel.Transform = CGAffineTransform.MakeRotation(new nfloat(Math.PI * 270 / 180.0));
stackView.AddArrangedSubview(imageView);
stackView.AddArrangedSubview(otherLabel);
stackView.AddArrangedSubview(targetLabel);
stackView.Center = View.Center;
targetLabel.Frame = new CGRect(targetLabel.Frame.X, targetLabel.Frame.Y, 150, 150);

Related

TextBlock doesn't want to adjust grid columns

I'm preparing control to present some data. It is built in the following way:
-> ScrollViewer
--> StackPanel
---> Border
----> Grid
---> Border
----> Grid
...
---> Border
----> Grid
And there is my code for each item
public class PresenterItem : Border
{
// Variables
private Submission submission;
private int index;
private Grid grid = new Grid();
// Constructor
public PresenterItem(int i, Submission subm)
{
index = i;
submission = subm;
Child = grid;
Background = Global.GET_BRUSH("ItemBackground");
CornerRadius = new CornerRadius(5);
Margin = new Thickness(0, 0, 0, 10);
Padding = new Thickness(5);
grid.ShowGridLines = true;
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(40, GridUnitType.Pixel) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(2, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(2, GridUnitType.Star) });
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(40, GridUnitType.Pixel) });
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(30, GridUnitType.Pixel) });
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
InsertContent();
}
private Label CreateLabel(int row, int column, string content, int columnSpan = 1)
{
Label newLabel = new Label();
newLabel.Content = content;
Grid.SetRow(newLabel, row);
Grid.SetColumn(newLabel, column);
Grid.SetColumnSpan(newLabel, columnSpan);
grid.Children.Add(newLabel);
return newLabel;
}
private TextBlock CreateTextBlock(int row, int column, int columnSpan = 1)
{
TextBlock newTextBlock = new TextBlock();
newTextBlock.Foreground = Brushes.Silver;
Grid.SetRow(newTextBlock, row);
Grid.SetColumn(newTextBlock, column);
Grid.SetColumnSpan(newTextBlock, columnSpan);
grid.Children.Add(newTextBlock);
return newTextBlock;
}
private void InsertContent()
{
// Number
Label number = CreateLabel(0, 0, $"#{index + 1}");
number.HorizontalAlignment = HorizontalAlignment.Center;
number.VerticalAlignment = VerticalAlignment.Center;
number.FontSize = 17;
// Header
Label header = CreateLabel(0, 1, $"{submission.Name} ({submission.Rank})");
header.Foreground = Global.GET_BRUSH("HeaderForeground");
header.HorizontalAlignment = HorizontalAlignment.Left;
header.VerticalAlignment = VerticalAlignment.Center;
header.FontSize = 17;
// Timestamp
TextBlock timestamp = CreateTextBlock(0, 2);
timestamp.Inlines.Add(new Run("Timestamp"));
timestamp.Inlines.Add(new Run($"{submission.Timestamp}") { Foreground = Global.GET_BRUSH("HeaderForeground") });
timestamp.HorizontalAlignment = HorizontalAlignment.Right;
timestamp.VerticalAlignment = VerticalAlignment.Center;
timestamp.FontSize = 13.5;
// Range
TextBlock range = CreateTextBlock(1, 1);
range.Inlines.Add(new Run("Some text "));
range.Inlines.Add(new Run($"{submission.Range.ToStringWithDayNames()}") { Foreground = Global.GET_BRUSH("HeaderForeground") });
range.HorizontalAlignment = HorizontalAlignment.Left;
range.VerticalAlignment = VerticalAlignment.Center;
range.Margin = new Thickness(5, 0, 0, 0);
range.FontSize = 13.5;
// Conflict
Label conflict = CreateLabel(1, 2, "Nie wykryto konfliktu");
conflict.Foreground = Global.GET_BRUSH("GreenForeground");
conflict.HorizontalAlignment = HorizontalAlignment.Right;
conflict.VerticalAlignment = VerticalAlignment.Center;
conflict.FontSize = 13.5;
// Content
TextBlock content = CreateTextBlock(2, 1, 2);
content.Inlines.Add(new Run($"{submission.Content}"));
cotent.HorizontalAlignment = HorizontalAlignment.Left;
content.VerticalAlignment = VerticalAlignment.Top;
content.Margin = new Thickness(5, 0, 0, 0);
content.TextWrapping = TextWrapping.WrapWithOverflow;
content.FontSize = 13.5;
}
How it looks like
It perfectly works but when I added last TextBlock whole control is stretching to the right. In designer the same way of creating elements works, but in code no. What am I doing wrong?
I would like to achieve this effect with column 1 and 2 with the same width everywhere.
What I want
You have to set the dependency property Grid.IsSharedSizeScope to true in the StackPanel and then set the Property SharedSizeGroup for every ColumnDefinition to a string that definies the group with same size.
I dealt with this problem on my own. If someone will be having the same problem like me, I will write how to repair it.
In the place where my app initializes ScrollViewer I set property HorizontalScrollBarVisibility to Hidden. After setting this property to Disabled everything starts to work correctly.
There is something about this:
https://crmdev.wordpress.com/2010/01/16/how-to-deal-with-stubborn-silverlight-a-k-a-stubborn-me/

How to access components created in Xamarin.Forms C# code behind?

So, I'm doing an app in Xamarin.Forms that creates some components and layouts when a button is clicked.
My problem is that I need to access these components afterwards so I can change the text in some labels, get values from editors and remove them later if necessary...
This is the piece of code that creates the components:
private void newItem()
{
StackLayout add = new StackLayout { };
add.StyleId = "add_" + posicio;
elements.Children.Add(add);
StackLayout grupInical = new StackLayout
{
Orientation = StackOrientation.Horizontal
};
add.Children.Add(grupInical);
Label number = new Label
{
VerticalOptions = LayoutOptions.End,
HorizontalOptions = LayoutOptions.StartAndExpand,
Text = "Element" + posicio.ToString(),
FontAttributes = FontAttributes.Bold,
Margin = new Thickness(5, 0, 0, 0)
};
Button tancar = new Button
{
Padding = new Thickness(5),
Text = "✕",
HorizontalOptions = LayoutOptions.End,
BackgroundColor = Color.Transparent,
WidthRequest = 30,
HeightRequest = 30
};
number.StyleId = "number_" + posicio;
tancar.StyleId = "tancar_" + posicio;
tancar.Clicked += Eliminar_clicked;
grupInical.Children.Add(number_);
grupInical.Children.Add(tancar);
StackLayout values = new StackLayout
{
Orientation = StackOrientation.Horizontal
};
values.StyleId = "values" + posicio;
add.Children.Add(values);
Button elegir = new Button
{
Text = "Element"
};
Editor percentage = new Editor { MaxLength = 2, WidthRequest = 30 };
Label desc = new Label
{
VerticalOptions = LayoutOptions.Center,
FontSize = 20,
FontAttributes = FontAttributes.Bold,
Text = "%"
};
Picker picker = new Picker
{
IsVisible = false
};
elegir.Clicked += Elegir_Clicked;
elegir.StyleId = "elegir_"+posicio;
percentatge.StyleId = "percentatge_" + posicio;
desc.StyleId = "desc_" + posicio;
picker.StyleId = "picker_" + posicio;
values.Children.Add(elegir);
values.Children.Add(percentatge);
values.Children.Add(desc);
values.Children.Add(picker);
posicio += 1;
scroll.ScrollToAsync(0, elements.Height, true);
}
As you can see, I'm trying to access the components by assigning them a styleid value but I can't access the component.
Have you got any suggestions on how to identify the items so I can reference them later on?
Declare these components at the class level and then you can access them in the other place in your project.
public partial class MainPage : ContentPage
{
Label numberLabel;
StackLayout myAddStackLayout;
public MainPage()
{
InitializeComponent();
newItem()
numberLabel.Text = "updateValue";
myAddStackLayout.Children.Add(...);
}
public void test() {
numberLabel.Text = "updateValue";
myAddStackLayout.Children.Add(...);
}
private void newItem()
{
StackLayout add = new StackLayout { };
Label number = new Label ();
}
}

String.Format is not giving the correct string in Xamarin.Forms

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}" />

Entry control expands beyond StackLayout container

I'm using the following (test) code to dynamically create a Page Content. I'm expecting the Entry control to stay within the StackLayout bounds and clip its large Text value. Somehow this doesn't work like I want.
What am I doing wrong here?
public MyPage() {
InitializeComponent();
var stackMain = new StackLayout() {
Orientation = StackOrientation.Vertical,
Spacing = 2,
BackgroundColor = Color.Yellow
};
Content = stackMain;
Padding = new Thickness(15, Device.OnPlatform(25, 5, 5), 15, 10);
var label = new Label() {
Text = "Test:"
};
stackMain.Children.Add(label);
var stackEntry = new StackLayout() {
Orientation = StackOrientation.Horizontal
};
stackMain.Children.Add(stackEntry);
var entry = new Entry() {
Text = "Blaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
IsEnabled = false,
HorizontalOptions = LayoutOptions.FillAndExpand
};
stackEntry.Children.Add(entry);
var button = new Button() {
Text = "Click me"
};
stackEntry.Children.Add(button);
}
What you need is an editor, Entries are one line only, the code below is tested and it fixes the Height by the size of the text:
public class App : Application
{
public App()
{
// The root page of your application
var content = new ContentPage
{
Padding = new Thickness(15, Device.OnPlatform(25, 5, 5), 15, 10),
Title = "test",
Content = new StackLayout
{
Spacing = 2,
BackgroundColor = Color.Yellow,
Children = {
new Label {
Text = "Test:"
},
new Editor {
Text = "Blaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
IsEnabled = false,
HorizontalOptions = LayoutOptions.Fill,
VerticalOptions = LayoutOptions.Fill
},
}
}
};
MainPage = new NavigationPage(content);
}
}
Hope this helps.
I just solved the same problem on an editor control!
The problem is here Orientation = StackOrientation.Horizontal,
you need to set orientation as StackOrientation.Vertical and it will wrap properly.
Note that I'm using Editor instead of Entry.

xamarin forms: swipe to delete

How can I add Swipe to delete in my note list app.I am using xamarin forms. I have searched in xamarin forms samples but could not find it. I also tried the list view performance options with menuItem etc but I dont know how to adjust that in my code. Can anyone help me with this please?
My code is as follows:
public partial class MyPage
{
List<Note> notes;
string NotesFile {
get {
var documents = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
return System.IO.Path.Combine (documents, "notes.json");
}
}
public MyPage()
{
BuildContent();
LoadNotes ();
ReloadListContents ();
AddNoteButton.Clicked += (sender, args) => {
var note = new Note("typ...");
notes.Add(note);
EditNote(note);
};
NoteListView.ItemTapped += (sender, row) =>
{
NoteListView.SelectedItem = null;
Note note = (Note)row.Item;
EditNote(note);
};
buttonDelete.Clicked += (sender, args) =>{
notes.RemoveAt(0);
DisplayAlert("Delete", "Row deleted", "OK");
};
}
}
MyPage.cs
{
public ListView NoteListView = new ListView ();
public Button AddNoteButton;
public Button buttonDelete;
private void BuildContent()
{
AddNoteButton = new Button
{
Text = "Add New Note",
TextColor = Color.White,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
buttonDelete = new Button
{
Text = "Delete Note ",
TextColor = Color.White,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
Content = new StackLayout
{
BackgroundColor = Color.Black,
Children = {
new Label {
Text = "Note Taker",
TextColor = Color.White
},
NoteListView,
AddNoteButton,
buttonDelete
}
};
}
Im responding to this question in CS code rather than XAML (My Preferred) if anyone would like the Xaml response please drop a comment below and I'll write the XAML alongside the CS.
So to complete what you have asked in Xamarin.Forms on ListView elements you must first create the ViewCell that you would like to display the data in each cell in the ListView and give it context actions. Here is an example:
public class CustomViewCell : ViewCell
{
public CustomViewCell()
{
//instantiate each element we want to use.
var image = new CircleCachedImage
{
Margin = new Thickness(20, 10, 0, 10),
WidthRequest = App.ScreenWidth * 0.15,
HeightRequest = App.ScreenWidth * 0.15,
Aspect = Aspect.AspectFill,
BorderColor = Color.FromHex(App.PrimaryColor),
BorderThickness = 2,
HorizontalOptions = LayoutOptions.Center
};
var nameLabel = new Label
{
Margin = new Thickness(20, 15, 0, 0),
FontFamily = "Lato",
FontAttributes = FontAttributes.Bold,
FontSize = 17
};
var locationLabel = new Label
{
Margin = new Thickness(20, 0, 0, 5),
FontFamily = "Lato",
FontSize = 13
};
//Create layout
var verticaLayout = new StackLayout();
var horizontalLayout = new StackLayout() { BackgroundColor = Color.White };
//set bindings
nameLabel.SetBinding(Label.TextProperty, new Binding("Name"));
locationLabel.SetBinding(Label.TextProperty, new Binding("Location"));
image.SetBinding(CircleCachedImage.SourceProperty, new Binding("Image"));
//Set properties for desired design
horizontalLayout.Orientation = StackOrientation.Horizontal;
horizontalLayout.HorizontalOptions = LayoutOptions.Fill;
image.HorizontalOptions = LayoutOptions.End;
//add views to the view hierarchy
horizontalLayout.Children.Add(image);
verticaLayout.Children.Add(nameLabel);
verticaLayout.Children.Add(locationLabel);
horizontalLayout.Children.Add(verticaLayout);
//HERE IS THE MOST IMPORTANT PART
var deleteAction = new MenuItem { Text = "Delete", IsDestructive = true }; // red background
deleteAction.Clicked += async (sender, e) => {
//Here do your deleting / calling to WebAPIs
//Now remove the item from the list. You can do this by sending an event using messaging center looks like:
//MessagingCenter.Send<TSender,string>(TSender sender, string message, string indexOfItemInListview)
};
// add to the ViewCell's ContextActions property
ContextActions.Add(deleteAction);
// add to parent view
View = horizontalLayout;
}
}
Now you must do the following to your ListView:
listView = new ListView();
lstView.ItemTemplate = new DataTemplate(typeof(CustomViewCell));
In the same Content Page that you have the ListView you must also subscirbe to the MessagingCenter listening to the same parameters as set in the custom view cell as above. Please read the link provided if you have not used the MessagingCenter before. Inside of this method you must then remove the item from the listview with the index sent to this method.
If anyone needs any further explanations drop a comment below and Ill edit this post.

Categories