Caliburn.Micro
Caliburn.Micro copied to clipboard
Error with global styles (Xamarin.Forms)
Hi, I'm new with Caliburn with Xamarin.forms, i'm sorry if the issue is inappropriate.
When I try to set global styles in the App.XAML file, if I use the style in HomeView page or another view, I receive the following error: System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'
Where? in Application.cs (Droid):
protected override object GetInstance(Type service, string key) { return container.GetInstance(service, key); }
Thank you.
If i try it with CSS styleSheet, i have the same error.
Can we see some code how you placed the styles linked into the app.xaml or if you show a GitHub repository we be better.
Here is my example code.
First way (using CSS):
My ContentPage:
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="GIPMobile.Views.HomeView">
<ContentPage.Resources>
<StyleSheet Source="../Estilos/gipstyles.css" />
</ContentPage.Resources>
<ContentPage.Content>
<ScrollView>
<StackLayout Orientation="Vertical" VerticalOptions="Start" Margin="5,20,5,5" Visual="Material" >
<Label Text="Estamos probando una APP con Caliburn.Micro"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
FontSize="25"
HorizontalTextAlignment="Center"/>
<Grid Visual="Material">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Entry Text="{Binding Nombre}"
Placeholder="Nombre en un grid" Margin="10"
MaxLength="15"
Grid.Column="0"
/>
<Label Grid.Column="1" VerticalOptions="Center">Aqui está la columna 2</Label>
</Grid>
<Entry Text="{Binding Nombre}"
Placeholder="Nombre" Margin="10"
MaxLength="15"
x:Name="GlobalCajas"/>
<Entry Text="{Binding Apellidos}"
Placeholder="Apellidos" Margin="10"
/>
<Entry Text="{Binding Direccion}"
Placeholder="Dirección" Margin="10"
/>
<StackLayout BackgroundColor="Beige">
<Label Text="{Binding Nombre}" Margin="10,30,10,10" TextColor="Black"/>
<Label Text="{Binding Apellidos}" Margin="10,10,10,10" TextColor="Black"/>
<Label Text="{Binding Direccion}" Margin="10,10,10,10" TextColor="Black"/>
</StackLayout>
<Label Text="Uso de stringformat..." Margin="10,10,10,10"/>
<Label Text="{Binding Nombre,StringFormat='Nombre {0}'}"/>
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
Here is my BootApp file:
using Caliburn.Micro;
using Caliburn.Micro.Xamarin.Forms;
using GIPMobile.ViewModels;
using GIPMobile.Views;
using Xamarin.Forms;
using INavigationService=Caliburn.Micro.Xamarin.Forms.INavigationService;
namespace GIPMobile
{
public class BootApp: FormsApplication
{
private readonly SimpleContainer container;
public BootApp(SimpleContainer container)
{
Initialize();
container.PerRequest<HomeViewModel>();
DisplayRootView<HomeView>(); //view first
//DisplayRootViewFor <HomeViewModel>(); // ViewModel first
}
protected override void PrepareViewFirst(NavigationPage navigationPage)
{
container.Instance<INavigationService>(new NavigationPageAdapter(navigationPage));
}
}
}
Here Application.cs (droid app):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Caliburn.Micro;
using GIPMobile.ViewModels;
namespace GIPMobile.Droid
{
[Application]
public class Application : CaliburnApplication
{
private SimpleContainer container;
public Application(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
public override void OnCreate()
{
base.OnCreate();
Initialize();
}
protected override void Configure()
{
container = new SimpleContainer();
container.Instance(container);
container.Singleton<BootApp>();
}
protected override IEnumerable<Assembly> SelectAssemblies()
{
return new[]
{
GetType().Assembly,
typeof (HomeViewModel).Assembly
};
}
protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}
protected override object GetInstance(Type service, string key)
{
return container.GetInstance(service, key);
}
}
}
Here MainActivity.cs (droid app):
using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Caliburn.Micro;
namespace GIPMobile.Droid
{
[Activity(Label = "GIPMobile", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(IoC.Get<BootApp>());
}
}
}
And the last one, stylesheet:
^ContentPage
{
background-color:silver;
}
^Entry
{
background-color:aqua;
font-size:large;
}
#GlobalCajas
{
background-color:orange;
}
And second way, using app.xaml (i dont know if it'd be a correct way) writing here the Application resources.
App.xaml
<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="GIPMobile.App">
<Application.Resources>
<ResourceDictionary>
<Style TargetType="ContentPage">
<Setter Property="BackgroundColor" Value="Silver"></Setter>
</Style>
<Style TargetType="Entry">
<Setter Property="BackgroundColor" Value="Aqua"></Setter>
</Style>
<Style x:Key="GlobalCajas" TargetType="Entry">
<Setter Property="BackgroundColor" Value="Orange"></Setter>
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
Here homeview.xaml:
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="GIPMobile.Views.HomeView">
<ContentPage.Content>
<ScrollView>
<StackLayout Orientation="Vertical" VerticalOptions="Start" Margin="5,20,5,5" Visual="Material" >
<Label Text="Estamos probando una APP con Caliburn.Micro"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
FontSize="25"
HorizontalTextAlignment="Center"/>
<Grid Visual="Material">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Entry Text="{Binding Nombre, Mode=TwoWay, UpdateSourceEventName=PropertyChanged}"
Placeholder="Nombre en un grid" Margin="10"
MaxLength="15"
Grid.Column="0"
/>
<Label Grid.Column="1" VerticalOptions="Center">Aqui está la columna 2</Label>
</Grid>
<Entry Text="{Binding Nombre, Mode=TwoWay, UpdateSourceEventName=PropertyChanged}"
Placeholder="Nombre" Margin="10"
MaxLength="15"
Style="{StaticResource GlobalCajas}"/>
<Entry Text="{Binding Apellidos, Mode=TwoWay}"
Placeholder="Apellidos" Margin="10"
/>
<Entry Text="{Binding Direccion}"
Placeholder="Dirección" Margin="10"
/>
<StackLayout BackgroundColor="Beige">
<Label Text="{Binding Nombre}" Margin="10,30,10,10" TextColor="Black"/>
<Label Text="{Binding Apellidos}" Margin="10,10,10,10" TextColor="Black"/>
<Label Text="{Binding Direccion}" Margin="10,10,10,10" TextColor="Black"/>
</StackLayout>
<Label Text="Uso de stringformat..." Margin="10,10,10,10"/>
<Label Text="{Binding Nombre,StringFormat='Nombre {0}'}"/>
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
And my HomeViewModel:
using Caliburn.Micro;
using System;
using System.Collections.Generic;
using System.Text;
namespace GIPMobile.ViewModels
{
public class HomeViewModel :Screen
{
private string _nombre;
public string Nombre
{
get { return _nombre; }
set
{
_nombre = value;
NotifyOfPropertyChange(() => Nombre);
}
}
private string _apellidos;
public string Apellidos
{
get { return _apellidos; }
set
{
_apellidos = value;
NotifyOfPropertyChange(() => Apellidos);
}
}
private string _direccion;
public string Direccion
{
get { return _direccion; }
set
{
_direccion = value;
NotifyOfPropertyChange(() => Direccion);
}
}
}
}
I havo to say, while i am at design time, i can see the styles changes in designer window.
Thank you.
couple of things... Reference code comments inline with the source snipped from your source.
namespace GIPMobile
{
public class BootApp: FormsApplication
{
private readonly SimpleContainer container;
public BootApp(SimpleContainer container)
{
Initialize();
this.container = container; // necessary to initialize it.
container.PerRequest<HomeViewModel>();
DisplayRootView<HomeView>(); //view first
//DisplayRootViewFor <HomeViewModel>(); // ViewModel first
}
protected override void PrepareViewFirst(NavigationPage navigationPage)
{
container.Instance<INavigationService>(new NavigationPageAdapter(navigationPage));
}
}
}
protected override void Configure()
{
container = new SimpleContainer();
/// container.Instance(container); //DON"T DO THIS...
container.Singleton<BootApp>();
}
This was the ultimate reason for it not to work in the droid flavor. the container already knows about itself it doesn't need to be inserted back into the container.
<Application.Resources>
<ResourceDictionary.MergeDictionaries>
<ResourceDictionary>
<Style TargetType="ContentPage">
<Setter Property="BackgroundColor" Value="Silver"></Setter>
</Style>
<Style TargetType="Entry">
<Setter Property="BackgroundColor" Value="Aqua"></Setter>
</Style>
<Style x:Key="GlobalCajas" TargetType="Entry">
<Setter Property="BackgroundColor" Value="Orange"></Setter>
</Style>
</ResourceDictionary>
<ResourceDictionary.MergeDictionaries>
</Application.Resources>
To be honest it had nothing to do with the Styles in my opinion. IT had everything to do with the container not being this.container = container
in one location and then you trying to insert the container into its self.
Hi, thank you.
I agree, writing this.conainer = conainter
it works.
But it is working with CSS stylesheet, but not with App.xaml and application.resources. It´s like caliburn didnt found app.xaml.
How can i register it in caliburn´s container?
To clarify, when i try work with xaml styles, i don´t use CSS. I don´t mix them.
Does this work in a project without Caliburn.Micro at all?
Yes, it does.
I'm having the exact same issue with 'V4.0.113'
The resources from my app.xaml aren't used/found.
All other things are almost identicall to Wilsmor.
Update:
After changing back the 'Application' back to the 'FormsApplication' and not use 'BootApp.cs' seperatly (and of course load the app class instead of bootapp class). This worked again!
Don't forget to set: 'InitializeComponent()' in the Constructor of the app, because otherwise it won't work (without any errors)