Wednesday, June 10, 2015

Add App.xaml in your Xamarin Forms project

In the current version of Xamarin tools, the default Xamarin Forms project templates in both Visual Studio and Xamarin Studio do not generate App.xaml along with the App class that derives from Application and provides an entry point where you can add initialization code. 

The support for App.xaml is briefly mentioned in Xamarin Forms documentation but without giving the exact steps.
These steps are:

1. Right click on the PCL project and choose to add a new file
2. In Visual Studio, choose the "Forms Xaml Page" item
    In Xamarin Studio, choose the "Forms ContentPage Xaml" item
3. Write "App" as name

You will get a App.xaml and App.xaml.cs created. You need to do some small modifications in each of these:

1. in App.xaml, replace the XAML with the following:
<Application
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="MyApp.App">
    <Application.Resources>
        <ResourceDictionary>
           
        </ResourceDictionary>
    </Application.Resources>
</Application>

Note the x:Class="MyApp.App" attribute. You should replace MyApp with the name of your Xamarin Forms project.

2. in App.xaml.cs, replace the base class ContentPage with Application
public partial class App : Application
{
    public App ()
    {
        InitializeComponent ();
        MainPage = YourContentPage(); // change as required
    }
}

You might also need to delete the old App.cs, you don't need it anymore.

Monday, June 08, 2015

IconView control for Xamarin Forms


Someone was asking on the forum how to draw a colored icon.
I created an IconView control which does this: https://github.com/andreinitescu/IconApp/

The control takes a local image and applies a color on it. This is useful when you want to color images on the fly, without the need to have multiple images for different colors.

At this moment the implementation is for Android and iOS. Contributions for Windows support are welcome!

Usage

An example of a Page using the IconView control:
<?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="IconApp.MyPage" xmlns:controls="clr-namespace:IconApp;assembly=IconApp"> <controls:IconView Source="monkey" Foreground="Red" WidthRequest="100" HeightRequest="100" HorizontalOptions="Center" VerticalOptions="Center" /> </ContentPage>
This draws the "monkey" image with red color in the center of the screen:



Add the control to your project


1. Add /IconApp/IconApp/IconView.cs to your Xamarin Forms PCL project
2. The control uses native renderes. You need to add the renderers to your Android and iOS project respectively:
/IconApp/IconApp.Droid/Renderers/IconViewRenderer.cs
IconApp/IconApp.iOS/Renderer/IconViewRenderer.cs

Note you might need to update some namespaces.

Tuesday, May 26, 2015

CallDataMethod trigger in Xamarin Forms



Here’s a very simple implementation of a CallDataMethod trigger in Xamarin Forms:
public class CallDataMethod: TriggerAction<VisualElement> { public string Method { get; set; } #region implemented abstract members of TriggerAction protected override void Invoke (VisualElement sender) { MethodInfo method = sender.GetType ().GetRuntimeMethod (Method, new Type[0]); if (method != null) { ParameterInfo[] parameters = method.GetParameters (); if (parameters.Length == 0) method.Invoke (sender, null); } } #endregion }

For a demo, let’s say we have two text-boxes (Entry control in Xamarin Forms) and you want to enable the second one when the first has ten characters:

<?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:controls="clr-namespace:Xamore.Controls;assembly=Xamore.Controls" x:Class="Xamore.Controls.TestApp.Views.CallDataMethodPage"> <StackLayout> <Entry x:Name="FirstEntry" WidthRequest="100" /> <Entry IsEnabled="false" WidthRequest="100"> <Entry.Triggers> <DataTrigger TargetType="Entry" Binding="{Binding Source={x:Reference FirstEntry}, Path=Text.Length}" Value="10"> <Setter Property="IsEnabled" Value="True" /> <Trigger.EnterActions> <controls:CallDataMethod Method="Focus" /> </Trigger.EnterActions> </DataTrigger> </Entry.Triggers> </Entry> </StackLayout> </ContentPage>

Wednesday, May 20, 2015

Manually install Xamarin Studio addins

Just copy the .dll file to (note the Xamarin Studio version, it might be different today):

on Windows:
%LocalAppData%\XamarinStudio-5.0\LocalInstall\Addins

on Mac:
/Users/[YourUser]/Library/Application Support/XamarinStudio-5.0/LocalInstall/Addins

Source:
http://forums.xamarin.com/discussion/comment/6356/#Comment_6356


Monday, May 18, 2015

Add ImageFailed and ImageOpened to the Xamarin Forms Image control

Currently the Image control in Xamarin Forms does not have an event to handle when image could or couldn't open.
I created a way to do this by extending the implementation for the Image control and ImageSource.
Check out the source code and a demo app on my GitHub: https://github.com/nitescua/ImageExtensionsApp
I implemented two ways to handle image loaded status. You could either: 
1. Use the Image derived class ImageEx which exposes ImageOpened and ImageFailed events:
<controls:ImageEx Source="http://dummyimage.com/100x100/000/fff" ImageFailed="Image_ImageFailed" ImageOpened="Image_ImageOpened"/>


2. Handle the status change right on the ImageSource instance:
ImageSourceExtensions.SetStatusChangedHandler (MyImage.Source, (sender, status) => { Debug.WriteLine("Image status: {0}", status); });
where MyImage is an Image control in your Page

To add the implementation in your apps, you need to:

1. Add ImageSourceExtensions.cs and ImageEx.cs to your shared Xamarin Forms project
https://github.com/andreinitescu/ImageExtensionsApp/blob/master/ImageExtensionsApp/ImageExtensionsApp/Helpers/ImageSourceExtensions.cs
https://github.com/andreinitescu/ImageExtensionsApp/blob/master/ImageExtensionsApp/ImageExtensionsApp/Controls/ImageEx.cs

2. Add the ImageLoaderSourceHandlerEx.cs in your platform specific code

Android: https://github.com/andreinitescu/ImageExtensionsApp/blob/master/ImageExtensionsApp/ImageExtensionsApp.Droid/Renderers/ImageLoaderSourceHandlerEx.cs

iOS: https://github.com/andreinitescu/ImageExtensionsApp/blob/master/ImageExtensionsApp/ImageExtensionsApp.iOS/Renderers/ImageLoaderSourceHandlerEx.cs

WindowsPhone: https://github.com/andreinitescu/ImageExtensionsApp/blob/master/ImageExtensionsApp/ImageExtensionsApp.WinPhone/Renderers/ImageLoaderSourceHandlerEx.cs

Few things you should be aware of:

- the events are called when Uri is valid. So for example, it will work when uri is “http://xxxxx’ but not for ‘xxxxx’
- when using the ImageSource.StatusChangedHandler note that the event is called only if you set the ImageSource to an Image. It doesn’t work if you just create an ImageSource using ImageSource.FromXXX methods. You must set the ImageSource to an Image.

Wednesday, May 06, 2015

Cross platform splash screen in Xamarin Forms


EDIT: I do not recommend this approach. Instead, use native approach to create splash screen because it shows much faster.


If the splash screen is more than just an image, you can treat the splash screen as a Xamarin Page.
To make this there are some steps:

Step 1. set the App’s MainPage to the splash screen page:
public partial class App : Application { public App() { InitializeComponent(); Setup.Init(); // with XLabs, you would do (Page)ViewFactory.CreatePage<SplashViewModel>(); MainPage = new SplashPage(); }


Step 2.  In SplashPage, after some logic is done, you will need to “navigate” to your first app’s page. This means you just need to set again the App’s MainPage, i.e”:
void ShowMainPage() { MainPage = new SplashPage(); }
The issue is how do you call this.
If you are not doing any logic in the splash screen, you can just do something like this:
public class SplashPage : Page { async protected override void OnAppearing() { base.OnAppearing(); await Task.Delay(TimeSpan.FromSeconds(2)); // again, here you might want to use instead XLab's ViewFactory.Create<FirstPageViewModel>() App.Current.MainPage = new FirstPage(); } }
If you are doing some logic in the view-model and you want to navigate to FirstPage, you don’t want to call this in the view-model.
There are few ways to change the App’s MainPage without calling it from the view-model.

You could use a messaging mechanism to send a custom message from the view-model to the view. Look to the Xamarin Form’s MessagingCenter: http://developer.xamarin.com/guides/cross-platform/xamarin-forms/messaging-center/.

Another way is, you probably are already using some navigation service to navigate between view-models, so what you need to do is have a custom navigation behavior in the way you navigate to the first page. With XLabs for example, you can define your own CustomNavigationService : XLabs.Platform.Services.INavigationService, override NavigateTo( ), then check for the page to which you navigate to, and if it’s FirstPage then create the NavigationPage and push the first page to it:

public class CustomNavigationService : INavigationService { NavigationService navigationSvc; public CustomNavigationService() { navigationSvc = new NavigationService(); } public void GoBack() { navigationSvc.GoBack(); } public void GoForward() { throw new NotImplementedException(); } public void NavigateTo<T>(object parameter = null, bool animated = true) where T : class { NavigateTo(typeof(T), parameter, animated); } public void NavigateTo(string pageKey, object parameter = null, bool animated = true) { throw new NotImplementedException(); } public void NavigateTo(Type pageType, object parameter = null, bool animated = true) { if (pageType == typeof(MainViewModel)) { var page = (Page)ViewFactory.CreatePage(pageType); App.Current.MainPage = new NavigationPage (page); navigationSvc = new NavigationService(App.Current.MainPage.Navigation); } else { navigationSvc.NavigateTo(pageType, parameter, animated); } } public void RegisterPage(string pageKey, Type pageType) { navigationSvc.RegisterPage(pageKey, pageType); } }
Step 3. In Android, you need to configure few things:

         a. Define a startup theme and an app theme in your Resources\values\themes.axml:
<?xml version="1.0" encoding="utf-8" ?> <resources> <color name="splashscreencolor">#232323</color> <style name="StartUpAppTheme" parent="android:Theme.Holo.Light"> <item name="android:windowNoTitle">true</item> <item name="android:windowBackground">@color/splashscreencolor</item> </style> <style name="AppTheme" parent="android:Theme.Holo.Light"> </style> </resources>

b. In the native MainActivity, have the activity start with the Theme.Splash and then have it running with the AppTheme:

[Activity(Theme = "@style/Theme.Splash"", MainLauncher = true, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize)] public class MainActivity : FormsApplicationActivity { protected override void OnApplyThemeResource(global::Android.Content.Res.Resources.Theme theme, int resid, bool first) { base.OnApplyThemeResource(theme, Resource.Style.AppTheme, first); } ... }

Friday, October 03, 2014

Configure app which requires admin rights to run at startup with task scheduler

 

App which requires elevated admin rights can’t just be set to run at startup by adding it to the registry key (HKLM\Software\Microsoft\Windows\CurrentVersion\Run) because it mail fail to start since it requires the UAC prompt. Windows will silently fail to display the UAC prompt.

One solution is to make the app a Windows Service, but depending on the technology used, this might not be possible. For example, a .NET Windows Service which is using .NET API printing (System.Printing) is not recommended (see http://blogs.msdn.com/b/dsui_team/archive/2013/06/24/printing-from-a-windows-service.aspx or see ‘Caution’ in http://msdn.microsoft.com/en-us/library/system.drawing.aspx).

So another solution is to use task scheduler.

When configuring the scheduled task, you need to make sure:

1. In the task properties popup, "Run with highest privileges" option is checked.

2. In the "Edit Action" popup, "Start in" is filled with the directory path (Do not include quotation marks or a trailing slash)

http://social.technet.microsoft.com/Forums/windows/en-US/7167bb31-f375-4f77-b430-0339092e16b9/how-does-run-with-the-highest-privileges-really-work-in-task-scheduler-?forum=w7itprogeneral