Xamarin Forms UWP specifying button width request with an effect - xamarin.forms

I would like to specify the width of a Xamarin.Forms.Button with an effect in UWP, something like:
protected override void OnAttached()
{
if (VisualElement is Xamarin.Forms.Button buttonControl)
{
buttonControl.WidthRequest = 40;
buttonControl.BorderWidth = 1;
}
}
VisualElement is an invalid type. What goes in its place? Thank you!

Xamarin Forms UWP specifying button width request with an effect
In Xamarin effect class, the attached control is referenced with Element property but not VisualElement, please edit your code like the following and you will get forms button on OnAttached method.
protected override void OnAttached()
{
if (Element is Xamarin.Forms.Button buttonControl)
{
buttonControl.WidthRequest = 40;
buttonControl.BorderWidth = 1;
}
}

Related

Adding children to StackLayout inside for loop causes this error "Layout cycle detected. Layout could not complete." in Xamarin Forms UWP

foreach (var equipment in EquipmentCollection)
{
var control = new EquipmentControl(equipment);
MyStackLayout.Children.Add(control);
}
I am getting this error only in UWP but not in Android. Even in UWP if the list size is small it is working fine.
I have tried few work arounds but still I couldn't able to make it work.
Since there is no UpdateLayout() method for xamarin-forms controls so I tried to use custom renderer for stacklayout and raised a child added event and called UpdateLayout() inside it but still got the crash.
[assembly: ExportRenderer(typeof(CustomStackLayout), typeof(CustomStackLayoutRenderer))]
namespace FO4.UWP.Controls
{
public class CustomStackLayoutRenderer : ViewRenderer<StackLayout, StackPanel>
{
StackPanel stkPanel;
protected override void OnElementChanged(ElementChangedEventArgs<StackLayout> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
CustomStackLayout stkLayout = (CustomStackLayout)e.NewElement;
stkLayout.ChildAdded += StkLayout_ChildAdded;
}
if (e.OldElement != null)
{
CustomStackLayout stkLayout = (CustomStackLayout)e.OldElement;
stkLayout.ChildAdded -= StkLayout_ChildAdded;
}
}
private void StkLayout_ChildAdded(object sender, ElementEventArgs e)
{
this.UpdateLayout();
}
}
}
I develop in Xamarin Forms but I don't target UWP.
Here some suggestions that will maybe help you:
For this kind of need, it is more frequent to use DataBinding through BindableLayout.ItemTemplate and Bindable.ItemsSource like described here: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/bindable-layouts#populate-a-bindable-layout-with-data.
If you don't want to use these mechanism, maybe you can try to use the BatchBegin() and BatchCompleted() method before and after your Loop https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.visualelement.batchbegin?view=xamarin-forms
The use of a renderer shoud not be required in my opinion...

How could I change the Navigastion's page arrow in Xamarin Forms?

I'm creating an app using xamarin Forms (multiplatform), I'm using a Navigation page, but I want to change the arrow ("<-") to text ("back")
Do you know how could i do it?
Thanks
(I'm going to use it in an Android App, but I'm creating the app using Xamarin forms)
You could use custom renderer to remove the navigation icon and set it with text. But, when you do that, you need to capture the click of the text and simulate the back event.
Create the interface:
public class CustomNavigationPage : NavigationPage
{
public CustomNavigationPage(Page startupPage) : base(startupPage)
{
}
}
The implementation of Android:
[assembly: ExportRenderer(typeof(CustomNavigationPage),
typeof(NavigationPageRenderer_Droid))]
namespace NavigationPageDemo.Droid
{
public class NavigationPageRenderer_Droid : NavigationPageRenderer
{
public Android.Support.V7.Widget.Toolbar toolbar;
public Activity context;
public NavigationPageRenderer_Droid(Context context) : base(context)
{
}
protected override Task<bool> OnPushAsync(Page view, bool animated)
{
var retVal = base.OnPushAsync(view, animated);
context = (Activity)Forms.Context;
toolbar = context.FindViewById<Android.Support.V7.Widget.Toolbar>(Droid.Resource.Id.toolbar);
if (toolbar != null)
{
//if (toolbar.NavigationIcon != null)
//{
//toolbar.NavigationIcon = Android.Support.V7.Content.Res.AppCompatResources.GetDrawable(context, Resource.Drawable.back);
//toolbar.NavigationIcon = null;
toolbar.NavigationIcon = null;
toolbar.Title = "back";
toolbar.SetOnClickListener(new OnClick());
//}
}
return retVal;
}
protected override Task<bool> OnPopViewAsync(Page page, bool animated)
{
return base.OnPopViewAsync(page, animated);
}
}
public class OnClick : Java.Lang.Object, IOnClickListener
{
void IOnClickListener.OnClick(Android.Views.View v)
{
App.Current.MainPage.Navigation.PopAsync();
}
}
In the custom renderer, use the OnClickListener to capture the click on text.
when you are working with xamarin forms it is suggested make use of common components and make least use of custom renderer.
Now for your requirement you want to create custom navigation bar
so here is how you can do it.
Create BaseContent Page
Create a Control Template inside your base page your can follow this link
Inside your control template using a grid view place your label with text binding (Back),also your can place a label in center to show title of page again u can make use of template binding which u would come to know when u go through the link
Now inherit your main page with your basecontentpage page
add your control template inside your main page
turn off your navigation bar of your main page
and you are done, this would give u more power to add more things like image or toolbar in your navbar
also to dynamically handle your back button u can check the count from navigationstack if its 0 u can show Humburger Icon or if its more than 0 u can show your label using IsVisible True/False

How to remove the border from a entry control with xamarin forms

How to remove the border from a entry box with xamarin control for the following control.
<Entry Text="" />
Currently I'm seeing a thin border against the textbox, where i'm not seeing any border property to remove.
Please let me know, how to disable this.
There some properties of controls that you cannot manipulate via Xamarin.Forms, you'll have to implement either an effect or a custom renderer. An effect might well do in your case, but since I'm more proficient with custom renderers, I'll show you how to achieve what you want with a custom renderer.
You'll have to create a class deriving from EntryRenderer that overrides OnElementChanged
public class CustomEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
this.Control.LeftView = new UIView(new CGRect(0, 0, 8, this.Control.Frame.Height));
this.Control.RightView = new UIView(new CGRect(0, 0, 8, this.Control.Frame.Height));
this.Control.LeftViewMode = UITextFieldViewMode.Always;
this.Control.RightViewMode = UITextFieldViewMode.Always;
this.Control.BorderStyle = UITextBorderStyle.None;
this.Element.HeightRequest = 30;
}
}
First there are some paddings added to the control (it looks quite ugly otherwise) by setting the LeftView and the RightView of the native control. Anyway, the more interesting part ist the BorderStyle by setting this property of the native control you can remove the border of the control.
Last thing you'll have to do is to say Xamarin.Forms to use that renderer. Use the following attribute in the global scope of your file (out of the namespace declaration):
[assembly: ExportRenderer(typeof(Entry), typeof(CustomEntryRenderer))]
If you don't want the style to be applied to all entries, you'll have to define a CustomEntry class that derives from Entry in your Xamarin.Forms project change the line presented above to
[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRenderer))]
Please note: This is the iOS implementation, but basically it's the same for Android.
Add this class to MainActivity.cs of Android project :
public class CustomEntryRenderer : EntryRenderer
{
public CustomEntryRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if(e.OldElement == null)
{
Control.Background = null;
var lp = new MarginLayoutParams(Control.LayoutParameters);
lp.SetMargins(0, 0, 0, 0);
LayoutParameters = lp;
Control.LayoutParameters = lp;
Control.SetPadding(0, 0, 0, 0);
SetPadding(0, 0, 0, 0);
}
}
}
and add this line before namespace:
[assembly: ExportRenderer(typeof(Entry), typeof(CustomEntryRenderer))]
then for iOS add this class to Main.cs :
public class CustomEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
Control.Layer.BorderWidth = 0;
Control.BorderStyle = UITextBorderStyle.None;
}
}
and :
[assembly: ExportRenderer(typeof(Entry), typeof(App1.iOS.CustomEntryRenderer))]
for set this change only for spicial class or custum Entry, just change typeof(Entry) to typeof(MyEntry).
Agree with the other responses that this is not possible with Entry unfortunately without using Effects or CustomRenderers.
My PCL-only approach was to use an Editor instead as this has a slightly richer set of styles and no annoying borders. The only extra code you need to write is a TextChanged event handler to catch the user pressing "enter" which just created a new line in an Editor. Eventhandling code as follows:
searchBox.Completed += (s, e) => {
DoSearch();
};
// Check for return pressed as well as we are now using an Editor
searchBox.TextChanged += (s, e) => {
if (e.NewTextValue.EndsWith("\n") == true) {
// trim the text
searchBox.Text = searchBox.Text.Trim();
// unfocus the box
searchBox.Unfocus();
// search
DoSearch();
}
};
Hope this helps - and for reference Xamarin, this has been annoying for years - please expose the borders of Entry field in a near future update!
There are no such property to remove border in entry. if you want to remove it you have to make renderer. Please Refer this Link

Xamarin Forms Orientation on iPad

I have a Universal Xamarin Forms App with a single page wrapped in a NavigationPage:
Current.MainPage = new NavigationPage(new RootPage()
{
BackgroundColor = (Color)Application.Current.Resources["BackgroundColour"]
})
{
BackgroundColor = (Color)Application.Current.Resources["BackgroundColour"],
BarBackgroundColor = (Color)Application.Current.Resources["BackgroundColour"],
Padding = NavigationPaddingForPlatfrom()
};
I've also overridden GetSupportedInterfaceOrientations in AppDelegate and set a break point - however the break point is never hit. When I rotate in the simulator or device, the break point isn't hit. I've also set the Device Orientation in info.plist to Portrait only, however the App still rotates.
Am I missing some configuration point that's needed to control orientation?
I'm using Xamarin Forms 2.4.0.38779.
The end goal is to force a MasterDetail Page into landscape only.
For forcing exact mode this code worked for me:
public MainPage()
{
InitializeComponent();
OnOrientationChanged += OnOrientationChange;
OnOrientationChange(this, new OrientationChangedEventArgs(DeviceOrientation.Landscape));
}
private void OnOrientationChange(object sender, OrientationChangedEventArgs e)
{
IOrientationService orientationService = DependencyService.Get<IOrientationService>();
DeviceOrientation currentOrientation = orientationService.GetCurrentOrientation();
if (currentOrientation != DeviceOrientation.Landscape)
{
orientationService.SetCurrentOrientation(DeviceOrientation.Landscape);
}
}
Have you tried this.
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
if (width != this.width || height != this.height)
{
this.width = width;
this.height = height;
if (Width > Height)
{
//your grid
}
else
{
//your grid
}
}
}
After reading a lot of article and forum posts, I came across this:
https://forums.xamarin.com/discussion/79389/how-to-lock-orientation-in-landscape-for-an-ipad-only-app
The last post by JoeRaco references this SO post:
Xcode 7 ERROR ITMS-90474: "Invalid Bundle", can't submit to Apple
Without 'Requires full screen' set to true, GetSupportedInterfaceOrientations was not being called in AppDelegate. Therefore adding the following to the info.plist solved my problem:
<key>UIRequiresFullScreen</key>
<true/>

Xamarin Form: Button inside Grid have a margin. How to remove that margin

I have a grid contains a set of button. I have set the columnSpacing of the grid to 0 but still have the margin between buttons. I assumed its the button control. Even if I put the margin on button to 0, the result is the same.
I can't use boxView, i need a text and clickable on it.
Old thread, but I was getting this on my Android platform. Upgrading Xamarin.Forms from 2.5 to recently released 3.1 seems to have resolved it.
The problem is, android button has default background drawable that has margin. You can remove it using custom renderer. Xamarin.Forms custom renderer
Example:
using System;
using test.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(Button), typeof(DefaultButtonRenderer))]
namespace test.Droid
{
public class DefaultButtonRenderer: ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
// Control is Android.Widget.Button, Element is Xamarin.Forms.Button
if (Control != null && Element != null)
{
// remove default background image
Control.Background = null;
// set background color
Control.SetBackgroundColor(Element.BackgroundColor.ToAndroid());
}
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "BackgroundColor")
{
// You have to set background color here again, because the background color can be changed later.
Control.SetBackgroundColor(Element.BackgroundColor.ToAndroid());
}
}
}
}
This code will remove button click effect. If you want to remain the effect, you have to set Control.Background to proper resource. (ex: Android.Resource.Attribute.SelectableItemBackground)
Alternatively, you can use label with TapGestureRecognizer. You can add TapGestureRecognizer to any view.

Resources