Conditional Compilation seems to be not working in Xamarin Studio - xamarin

I created a Xamarin Forms app.
And inside a new page with a label named "MyLabel".
In the code behind for my page I have
private void SetUpUI()
{
#if __IOS__
this.MyLabel.BackgroundColor = Color.Navy;
#endif
}
In my iOS project options I can see symbol __IOS__ in the "Compiler" tab. (please see screenshot)
When I run in iOS it doesn't make the label blue:
But if I remove #if __IOS__ block it makes the label blue:
So it seems conditional compilation is not working.
I'm on a Mac. So couldn't test on Visual Studio.
Stuck with it for a long time but cannot figure out what I missed.

The answer of SushiHangover is correct: your PCL project won't have the compiler definitions for the platforms.
However, the solution he provides has become obsolete since Xamarin Forms 2.3.4 was released. Device.OnPlatform has been redesigned as discussed in this discussion and implemented in this Pull Request.
The correct way to do this in Xamarin Forms 2.3.4 and onwards is by using Device.RuntimePlatform. Use a switch or conditional to suit your needs like so:
if(Device.RuntimePlatform == Device.iOS)
{
// iOS
}
else if(Device.RuntimePlatform == Device.Android)
{
// Android
}
It would be possible to do it like you asked, if you were to use a shared project instead of a PCL. Because when you use a shared project, you have access to the compiler directives of your platform projects.

You are using the conditionals in your PCL project which would not contain those compiler defines, thus why your conditional code is greyed out.
In your PCL project you can use Device.OnPlatform to perform platform based processing:
Device.OnPlatform (iOS: () => this.MyLabel.BackgroundColor = Color.Navy; );
re: https://developer.xamarin.com/api/member/Xamarin.Forms.Device.OnPlatform/

Related

How to add trivial OpenGL functionality to Xamarin forms app

Can anyone please help with the following?
I have a trivial Xamarin forms app working and I want to add an OpenTK view.
The following works fine:
In my MainPage.xaml.cs I have the following event handler for a button which spawns an empty OpenTK view on each click:
private void OnXAMLButtonClicked(object sender, EventArgs e)
{
var view = new OpenGLView { HasRenderLoop = true };
view.HeightRequest = 300;
view.WidthRequest = 300;
view.OnDisplay = r =>
{
//GL.ClearColor(red, green, blue, 1.0f);
};
m_SL.Children.Add(view);
}
(where m_SL is the name of my StackLayout).
I get a new black window on each click. Great.
Now, see that commented-out line, that's because the value GL is undefined.
This code is from the simple example here:
https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.openglview?view=xamarin-forms
I see at the top of that example there is the following:
using OpenTK.Graphics.ES30;
But I cannot include this, OpenTK is not recognized as a namespace. I expected to have to add it as a reference, but how?
I can add a reference to it in my .Android project so that I can add the above using statement in my MainActivity.cs page but that is not where it belongs (although I see that I then have GL defined, so this proves that I need to add these using statements to my MainPage.xaml.cs in order to get GL defined), but like I say, how do I add the reference to OpenTK for the project that contains MainPage.xaml.cs.
Thanks for any help,
Mitch.
----- EDIT -----
Thanks to the poster for helping me so far, the new problem is a reference to System.Private.Core that cannot be resolved. Here's the my full workflow for creating this error:
1: Create a new project.
This gives me the three projects:
2: Change to .NET standard 2.1 in the OGLMobile project:
The .Android and .iOS projects don't have a .NET choice option.
3: Add reference to OpenTK to OGLMobile project:
4: OGLMobile project builds fine but .Android project gives:
If I remove reference to OpenTK everything builds again. Makes no difference if I add OpenTK Nuget package to .Android project, I still get the same error.
So close,
thanks for any advice.
You need to install Nuget Package OpenTK.Graphics, then can use that.
Now can refer it:
Note: 4.0.1 of OpenTK.Graphics need .NET Standard 2.1.

how to implement mapbox correctly in xamarin forms app

i just downloaded the naxam mapbox and am completely lost the github page isn't much of help and there seems to be nothing else can anyone give anything usefull on how to implement the map view in the xamarin.forms app and thanks.
Short Anwser:
The Naxam.Mapbox for Xamarin.Forms Nuget Package, and all the associated Forms ones, have not been update since Sep 12, 2018, and the Mapbox SDK's for Android/iOS have changed since then, i tried this package and it's a bit clunky, i have manage to display the map, but inserting Geojson Sources/ Markers is not a pleasant experience.
EDIT 2019/10/13
Last month, Naxam updated their nuggets to the latest Mapbox version for .Forms, Android and iOS
Long Anwser:
If you really want to use Mapbox in your Xamarin Projects, the Naxam Binding Libraries for Android and iOS are still working today (18/06/2019), So one way to have it working for a Xamarin Forms Project is to implement both sdk's in their respective project, and use them in a Custom View Renderer (and be carefull, because those projects still need other Nuget Packages to work, and they don't warn you when you install them, be sure see the dependecies in the links i gave above).
Other way to have a map in your project is by using MapsUi (Remember that MapsUi is TileBased and Mapbox is VectorBased, so you might see less fluidity while using MapsUi). i will leave here some relevant code for the custom render in iOS for the implementation of MapsUi to get started:
MapViewRenderer.cs
public class MapViewRenderer : ViewRenderer<MapsUIView, Mapsui.UI.iOS.MapControl>
{
Mapsui.UI.iOS.MapControl mapNativeControl;
MapsUIView mapViewControl;
protected override void OnElementChanged(ElementChangedEventArgs<MapsUIView> e)
{
base.OnElementChanged(e);
if (mapViewControl == null && e.NewElement != null)
mapViewControl = e.NewElement;
if (mapNativeControl == null && mapViewControl != null)
{
var rectangle = mapViewControl.Bounds;
var rect = new CGRect(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
mapNativeControl = new Mapsui.UI.iOS.MapControl(rect)
{
Map = mapViewControl.NativeMap,
Frame = rect
};
SetNativeControl(mapNativeControl);
}
}
}
This is the base on how to implement the MapView in a Custom View Render in iOS, similiar code is needed for Android, and of course, the Custom Renderer itself, wich there is tons of tutorials on how to do it, like this ones: Source 1 Source 2

xamarin android uitest theme style conflicts

Recently I asked a question over trying to get my theme recognized within the android test project: Unit testing a Xamarin Forms Android specific code project
I'm not running into a conflict that shows up within xunit / nunit as the testing strategy. I feel like it's because the FormsAppCompatActivity with an older activity type, but I'm new to Xamarin and am unsure on how to approach this.
I get a lot of these type of errors:
Attribute "layout_anchorGravity" already defined with incompatible format.
The full list of the similar Attribute errors is:
fabSize
tabMode
expandedTitleGravity
layout_scollFlags
layout_collapseMode
collapsedTitleGravity
tabGravity
showDividers
displayOptions
showAsActions
actionBarSize
finally I have the addition error:
Found tag styles where item is expected
//Within the Android Forms project, I have this inheritance:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity {
// typical code
}
//within the Android UITest project
public class MainActivity : Xunit.Runners.UI.RunnerActivity {
// tests can be inside the main assembly
AddTestAssembly(Assembly.GetExecutingAssembly());
AddExecutionAssembly(typeof(ExtensibilityPointFactory).Assembly);
// or in any reference assemblies
//AddTestAssembly(typeof(PortableTests).Assembly);
// or in any assembly that you load (since JIT is available)
#if false
// you can use the default or set your own custom writer (e.g. save to web site and tweet it ;-)
Writer = new TcpTextWriter ("10.0.1.2", 16384);
// start running the test suites as soon as the application is loaded
AutoStart = true;
// crash the application (to ensure it's ended) and return to springboard
TerminateAfterExecution = true;
#endif
// you cannot add more assemblies once calling base
base.OnCreate(bundle);
}

Changes in MvvmCross bindings

Hi Xamarin/MvvmCross devs,
This is just a question out of curiosity. In one of the apps I'm developing some behaviour changed. Specifically on iOS when binding the UISwitch "On" value to a boolean in the ViewModel. The getter on the property fires when the binding is applied as well as the setter when the switch is flipped, but the UI does not reflect it. Forcing me to go from just
var set = this.CreateBindingSet<SettingsView, SettingsViewModel>();
set.Bind(PushNotificationSwitch).For(s => s.On)
.To(vm => vm.ReceivePushNotifications);
set.Apply();
To having to also add the following below that (to get the UI of the switch to reflect the value)
var settingsViewModel = ((SettingsViewModel)ViewModel);
PushNotificationSwitch.On = settingsViewModel.ReceivePushNotifications;
I left the binding, as well as the new code to reflect UI state, because in addition to the UI just reflecting the correct state, I also want it to change the state in my settingsService when the user changes it.
I recently upgraded through Xamarin Studio on Mac and my iOS Xam version is Version: 10.0.0.6. Unfortunately I didn't check what version I upgraded from, but I always upgrade as soon as I see there's one available, so it should be the previous stable version.
My questions are:
Has any of you experienced similar issues where bindings changed in this way?
Since the Android binding still works fine, do you think it's an issue in MvvmCross, or iOS Xamarin Changes
Any speculations as to what could be causing this? And other parts that you think this might affect, so I won't have to go scour for bugs if none exists. Commands, text and custom control bindings are working fine (as far as I've tested)
If this question would be better suited somewhere else please let me know, I'm just curious about this behaviour.
Thanks
As we worked out in the comments of the OP the event of the switch was linked out. Hence, the binding did nothing.
Easiest way to remedy this is to add the following code to your LinkerPleaseInclude.cs file, which MvvmCross provides in the Startup NuGet and through the templates available for Visual Studio and Xamarin Studio:
public void Include(UISwitch sw)
{
sw.On = !sw.On;
sw.ValueChanged += (sender, args) =>
{
sw.On = false;
};
}
This will tell the Linker that there is a direct usage of both the ValueChanged event and the On property, since the LinkerPleaseInclude class uses the Preserve attribute.

MvvmCross, Xamarin Studio and ICommands

My issue was born in Does MvvmCross work in Xamarin Studio?. MvvmCross works fine in Visual Studio. However, I've been mandated to deploy this corporately using Xamarin Studio which is what their build server uses. I ran into the issue with System.Windows.Input.ICommand not being found by the compiler during my Xamarin Studio build. ICommands appear to be used quite extensively throughout MvvmCross for user commands (MvxCommand, which implements System.Windows.Input.ICommand). I've tried creating my own version of ICommand via the following code:
using System;
namespace Something.Common
{
public interface ICommand
{
event EventHandler CanExecuteChanged;
bool CanExecute(object parameter);
void Execute(object parameter);
}
}
All good, but still doesn't fix MvxCommand, because it implements the interface System.Windows.Input.ICommand. So I created my own version, MvxCommandEx, which is basically copied from Stuart's MvxCommand and implements my own ICommand (Something.Common.ICommand).
Lo and behold, it builds. It deploys. It got me all excited. But.... it didn't work. Any place I've bound a UI element to my custom ICommand just doesn't do anything. It's as if the binding from the Click event of the control to the view model's command is just not there anymore, whether I bind it in the .axml layout file... or use the CreateBindingSet method built-in to the view.
Now... I can get around this for some things... for instance, if I use a standard android Button, and invoke the view model's command manually from the built-in Click event, like:
btnAddScope.Click += (o, i) => { _ViewModel.RequestAddScope.Execute(null); };
it works, and I'm okay doing it this way in the interim until Xamarin releases their PCL support. But I'm using an MvxListView in another section of the app that was bound the old way using a syntax like:
lst.ItemClick = _ViewModel.RequestViewScope;
where lst is a MvxListView.
This won't work, however, because lst.ItemClick expects a System.Windows.Input.ICommand, and my ICommand isn't in that namespace.
Stuart provided explanations for this that supposedly are supposed to work. However, I'm feeling stupid for not being able to implement the ICommand in a way that actually works, when it feels like it should work... so before I go down a different avenue to address this, I wanted to see if anyone could shed light on what I'm doing wrong.
The easy solutions are:
either to provide your own implementation for the Xamarin version of System.Windows.Input.ICommand and to use this implementation
or to use the mvvmcross binaries which are built on the mac.
I'd recommend the first.
If you delete your Something.Common.ICommand code abd then put your MyCommand class implementation in the same project/assembly as your viewmodels, then they should build and run fine on both windows and on mac.

Resources