Xamarin.Forms XAML Previewer - Determine if in Design Mode in Code Behind and XAML similar to Blend

renzskarenzska John RennemeyerUS ✭✭

I'm using the Xamarin.Forms XAML Previewer and trying to use Design Time Data when in Design Mode and Real Data when running the actual application. Does it support functionality similar to Blend for WPF?:

Blend XAML:

xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
mc:Ignorable="d" 
d:DataContext="{d:DesignData Source=/SampleData/SomeSampleData.xaml}"
DataContext="{Binding RelativeSource={RelativeSource Self}}"

Blend Code Behind:

if (DesignMode.DesignModeEnabled)
{
  // This code runs in the visual designer and Blend
}

Right now I'm having to comment out "Init()" and "DesignInit()" methods and other code I've created depending on what I'm working on at the moment.

Thanks,

John

Tagged:

Answers

  • OddbjornBakkeOddbjornBakke Oddbjørn Bakke NO ✭✭

    I did not get IsInEditMode to work. But I guess Xamarin is working on getting it working.
    But checking if Application.Current is set to null seems to work OK.

    What I got to work, was something like this:

       public static class ViewModelLocator
        {
            public static SearchPageModel SearchPage = GetModel(new SearchPageModel
            {
    
            });
    
            private static T GetModel<T>(T obj)
                where T : class
            {
                return Xamarin.Forms.Application.Current == null ? obj : null;
            }
        }
    
    BindingContext="{Binding Source={x:Static a:ViewModelLocator.SearchPage}}"
    

    The problem is that the BindingContext is set to null before the ViewModel.
    (I am using FreshMvvm)

    I also testet with using something like this:

        <ContentPage.Triggers>
            <DataTrigger TargetType="ContentPage" Binding="{Binding Source={x:Static a:ViewModelLocator.IsPreview}}" Value="True" >
                <Setter Property="BindingContext" Value="{x:Static a:ViewModelLocator.SearchPage}" />
            </DataTrigger>
        </ContentPage.Triggers>
    

    Where IsPreview checks if Application.Current is set.

    However, I do belive that the tradeoff with the null kind is better.

  • renzskarenzska John Rennemeyer US ✭✭

    Nice find. I'll give it a try.

  • Gabor.SuranyiGabor.Suranyi Gábor Surányi US
    edited November 2016

    For me working this workaround:
    if(Application.Current==null) { //design mode } else { //runtime mode }

  • amay077amay077 amay 077 JP ✭✭

    We will not be able to use Application.Current==null as "IsPreview" in Xamarin Studio 6.2 and later.

    • Application.Current should be set now, which means controls which reference Application.Current will no longer null ref inside the previewer.
  • AlexanderShirshovAlexanderShirshov Alexander Shirshov RU

    I set a flag in OnStart:

    protected override void OnStart() { Design.Models.Disabled = true; // Real initialisation: MainPage = new LoginPage { BindingContext = new LoginPageModel { ... ...

    My view locator looks like this:

    namespace MyApp.Design
    {
        public class Models
        {
            public static bool Disabled;
            // Design time data:
            public static LoginPageModel LoginPageModel => Disabled ? null : new LoginPageModel {
               UserId = "u@a.b", Password = "11111"
            };
    ...
    

    Note that Xamarin Studio creates an instance of your Application class for the preview to work. Therefore if you set the Disabled = true flag in the app's constructor you'll see no data in the previewer. And if you set MainPage in the app constructor it'll use the design time model upon startup. To work around this I set it to a blank page in the constructor: MainPage = new ContentPage(); and then set the real startup page in the OnStart override as shown above.

  • JohnRennemeyer.6780JohnRennemeyer.6780 John Rennemeyer US

    Nice find! Crazy that they don't yet have a built-in property that we can use, but this will do for now. Thanks for sharing this.

Sign In or Register to comment.