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

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/

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.

Device.OS in Xaml in Xamarin.Forms

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.

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");

creating dynamic textbox in wpf according to location

I'm trying to create dynamically text box in WPF. It is very essential that I will have the flexibility to determine where the text box will be - in pixel level.
I have found many answers which use stackpanel to create "run-time" text box - but couldn't find how to construct it according to specified location.
the textbox has to be "word wrap" and I'm using a button click event to create the text box
this is the code for now, I really don't know which methods or properties will be helpful.
thanks :)
private void button1_Click(object sender, RoutedEventArgs e)
{
TextBox x = new TextBox();
x.Name = "new_textbox";
x.TextWrapping= TextWrapping.Wrap;
x.VerticalScrollBarVisibility=ScrollBarVisibility.Visible;
x.AcceptsReturn = true;
x.Margin = new Thickness(5, 10, 0, 0);
}
TextBox x = new TextBox();
x.Name = "new_textbox";
x.TextWrapping= TextWrapping.Wrap;
x.VerticalScrollBarVisibility=ScrollBarVisibility.Visible;
x.AcceptsReturn = true;
x.Margin = new Thickness(5, 10, 0, 0);
HouseCanvas.Children.Add(x);
Canvas.SetLeft(x, 20);
Canvas.SetTop(x, 20);
You probably want to place it in a Canvas, if you care about pixel placement of the textbox itself. You'll need to use x.SetValue(Canvas.LeftProperty, pixelX) [and .RightProperty, etc...] to get the position exactly right. Having not done this myself, I'd guess that you need to put the canvas in the right Z-order (on top), and make it transparent. There may also be issues with events, depending on the z-order. Good luck!
-Kev

FindName returning null

I'm writing a simple tic tac toe game for school. The assignment is in C++, but the teacher has given me permission to use C# and WPF as a challenge. I've gotten all the game logic finished and the form mostly complete, but I've run into a wall. I'm currently using a Label to indicate who's turn it is, and I want to change it when a player makes a valid move. According to Applications = Code + Markup, I should be able to use the FindName method of the Window class. However, it keeps returning null. Here's the code:
public TicTacToeGame()
{
Title = "TicTacToe";
SizeToContent = SizeToContent.WidthAndHeight;
ResizeMode = ResizeMode.NoResize;
UniformGrid playingField = new UniformGrid();
playingField.Width = 300;
playingField.Height = 300;
playingField.Margin = new Thickness(20);
Label statusDisplay = new Label();
statusDisplay.Content = "X goes first";
statusDisplay.FontSize = 24;
statusDisplay.Name = "StatusDisplay"; // This is the name of the control
statusDisplay.HorizontalAlignment = HorizontalAlignment.Center;
statusDisplay.Margin = new Thickness(20);
StackPanel layout = new StackPanel();
layout.Children.Add(playingField);
layout.Children.Add(statusDisplay);
Content = layout;
for (int i = 0; i < 9; i++)
{
Button currentButton = new Button();
currentButton.Name = "Space" + i.ToString();
currentButton.FontSize = 32;
currentButton.Click += OnPlayLocationClick;
playingField.Children.Add(currentButton);
}
game = new TicTacToe.GameCore();
}
void OnPlayLocationClick(object sender, RoutedEventArgs args)
{
Button clickedButton = args.Source as Button;
int iButtonNumber = Int32.Parse(clickedButton.Name.Substring(5,1));
int iXPosition = iButtonNumber % 3,
iYPosition = iButtonNumber / 3;
if (game.MoveIsValid(iXPosition, iYPosition) &&
game.Status() == TicTacToe.GameCore.GameStatus.StillGoing)
{
clickedButton.Content =
game.getCurrentPlayer() == TicTacToe.GameCore.Player.X ? "X" : "O";
game.MakeMoveAndChangeTurns(iXPosition, iYPosition);
// And this is where I'm getting it so I can use it.
Label statusDisplay = FindName("StatusDisplay") as Label;
statusDisplay.Content = "It is " +
(game.getCurrentPlayer() == TicTacToe.GameCore.Player.X ? "X" : "O") +
"'s turn";
}
}
What's going on here? I'm using the same name in both places, but FindName can't find it. I've tried using Snoop to see the hierarchy, but the form doesn't show up in the list of applications to choose from. I searched on StackOverflow and found I should be able to use VisualTreeHelper class, but I don't understand how to use it.
Any ideas?
FindName operates on the XAML namescope of the calling control. In your case, since the control is created entirely within code, that XAML namescope is empty -- and that's why FindName fails. See this page:
Any additions to the element tree after initial loading and processing must call the appropriate implementation of RegisterName for the class that defines the XAML namescope. Otherwise, the added object cannot be referenced by name through methods such as FindName. Merely setting a Name property (or x:Name Attribute) does not register that name into any XAML namescope.
The easiest way to fix your problem is to store a reference to your StatusDisplay label in the class as a private member. Or, if you want to learn how to use the VisualTreeHelper class, there's a code snippet at the bottom of this page that walks the visual tree to find the matching element.
(Edited: Of course, it's less work to call RegisterName than to use the VisualTreeHelper, if you don't want to store a reference to the label.)
I'd recommend reading the first link in its entirety if you plan on using WPF/Silverlight in any depth. Useful information to have.
You have to create a new NameScope for your window:
NameScope.SetNameScope(this, new NameScope());
Then you register name of your label with the window:
RegisterName(statusDisplay.Name, statusDisplay);
So this seems to be all you need to do to make FindName() work.

Categories

Resources