How to implement Styles into Xamarin.Forms well? - xamarin

With control level styling I do not need to worry about adding a line of code for every control on every page.
Style Class
public static class Styles
{
#region "Entry"
public static readonly Style Entry_Standard = new Style(typeof(Entry))
{
new Setter {Property = Xamarin.Forms.Entry.BackgroundColorProperty, Value = Color.Red }
};
#endregion
}
Custom Control
public class Custom_Entry : Entry
{
public Custom_Entry()
{
this.Style = Styles.Entry_Standard;
}
}
All of the example documentation from Xamarin though appears to favor setting styles as a property at the page level after object creation either through a page resource or static class reference.
Is there a valid reason for this or is it just that the short examples do not bother to abstract away control styles?

Related

What would be a good way to replace a static class used to hold Application settings?

I have an application that uses a static class to store settings:
namespace ABC
{
public static class MS
{
public static bool abc;
public static bool def;
...
}
}
When the app starts up it goes to the database and updates some of these settings.
I have been told that holding them in a static class is not ideal for when I am doing bindings and adding notification so I'm thinking I should new a class and the hold them in an instance. If that's the case can someone give me some advice. Should I do that when the application starts up and should it be in the constructor of the App() if that is the best way to do it then how can I do this. Any small 4-5 line example would be a big help
public partial class App : Application
{
public static xxx
public App()
{
AS.appUpdated = "Feb 1, 2017";
AS.appVersion = "0.1";
InitializeComponent();
MainPage = new MS.MainPage();
}
}
Have a look at James Montemagno's settings plugin.
https://github.com/jamesmontemagno/SettingsPlugin
This abstracts away a lot of the plumbing around settings and persisting them locally. Calling one of your settings from anywhere in your application then becomes as simple as calling Settings.MySettingName.
When it comes to binding these values to a view I would always create a property for them in your view model that simply returns the value from the settings. If need be you can put them in a base viewmodel and go from there.
public class MyViewModel : BaseViewModel
{
}
public class BaseViewModel
{
public bool SettingA => Settings.SettingA;
public bool SettingB => Settings.SettingB;
}

Windows Phone - Using generic class for PhoneApplicationPage

I have a Page which consist of AddPage.xaml and AddPage.xaml.cs. I want to create a generic class AddPage which extends from PhoneApplicationPage to outsource some repetitive code like Save or Cancel.
If I change the base class from PhoneApplicationPage to my new generic class, I get this error: Partial declarations of 'AddPage' must not specify different base classes.
To accomplish this you need to do the following.
First, create your base class
public class SaveCancelPhoneApplicationPage : PhoneApplicationPage
{
protected void Save() { ... }
protected void Cancel() { ... }
}
Then, your AddPage needs to be modified to inherit from the base class. The main places this is needed is within the code (AddPage.xaml.cs) AND within the xaml
Code:
public partial class AddPage : SaveCancelPhoneApplicationPage { ... }
Xaml:
<local:SaveCancelPhoneApplicationPage
x:Class="MyPhone.Namespace.AddPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyPhone.Namespace"
<!-- other xaml elements -->
</local:SaveCancelPhoneApplicationPage>
UPDATE: Info added based on comments
If you need to have generic like functionality and you must use the Page to do this (rather than a ViewModel) then you can still do this using generic methods
public abstract class SaveCancelPhoneApplicationPage : PhoneApplicationPage
{
protected override void OnNavigatedTo(blaa,blaa)
{
var obj = CreateMyObject();
obj.DoStuff();
}
// You should know what your objects are,
// don't make it usable by every phone dev out there
protected MyBaseObject MyObject { get; set; }
protected T GetMyObject<T>() where T : MyBaseObject
{
return MyObject as T;
}
}
public class AddPage : SaveCancelPhoneApplicationPage
{
public AddPage()
{
MyObject = new MyAddObject();
}
}
In order to outsource some functions you just declare some add class which does the common work. Having another page doesn't do that work.
public class Add
{
public bool SaveContent(string filename, string content)
{
....//some content
return true;
}
public string ViewContent(string filename)
{
string content="";
.....
return content;
}
}
Add this part of code where you thought it is redundant.
Add obj=new Add();
obj.SaveContent("myfile.txt","Hello.This is my content.");
string content("myfile.txt");
Tell me if this is what you intend or not.

How to apply style to application bar globally?

I checked the Application bar but no style attribute is shown. I have about 10 pages that use an app bar so it would be ideal to set a style in the Application.Resources. Is it possible to apply a style to all application bars in my application?
You can pretty much do this with a abstract class which your pages inherit from.
public abstract class BasePage : PhoneApplicationPage
{
public abstract bool UsingApplicationBar { get; }
public Color ApplicationBarColor= Colors.Gray;
public BasePage()
{
Loaded += BasePageLoaded;
}
private void BasePageLoaded(object sender, RoutedEventArgs e)
{
if (UsingApplicationBar)
{
ApplicationBar.BackgroundColor = ApplicationBarColor;
}
}
}
As far as I understand your question, you have different application bars on different pages and you want to have a style which can be applied to all. Unfortunately, binding does not work with application bars. You may have to style all of them one by one. For more information:
Windows Phone ApplicationBar BackgroundColor property style XamlParseException

Need help converting PRISM Unity Module Init to PRISM MEF Module Init

I need help converting the following class for use in a program that I am developing. The original was a demo program from IdeaBlade called "PRISM EXPLORER" based on Unity. I need help converting one part from UNITY to MEF. I handled everything else. Just stuck on this one. I already marked my classes with the MEF "[EXPORT(typeof(XXX))]" and I think I need to use the "ComposeExportedValue" somehow. The confusing part is finding the equivelant for this line:
var provider =
(IEntityManagerProvider) _container.Resolve<IPersistenceGateway>();
_container.RegisterInstance<IEntityManagerProvider>(provider);
THANKS!
The following is the entire class I need to convert. You can find the original here: Ideablade PRISM Page
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Composite.Regions;
using Microsoft.Practices.Unity;
using PrismExplorer.Infrastructure;
namespace ModelExplorer.Explorer {
public class ExplorerModule : IModule {
private readonly IUnityContainer _container;
public ExplorerModule(IUnityContainer container) {
_container = container;
}
public void Initialize() {
InitializeContainer();
SetViews();
}
// ToDo: Consider getting from configuration
private void InitializeContainer() {
RegisterGatewayAndEntityManagerProvider();
_container.RegisterType<IQueryRepository, QueryRepository>(
new ContainerControlledLifetimeManager()); // singleton
}
private void RegisterGatewayAndEntityManagerProvider() {
_container.RegisterType<IPersistenceGateway, PrismExplorerPersistenceGateway>(
new ContainerControlledLifetimeManager()); // singleton
var provider =
(IEntityManagerProvider) _container.Resolve<IPersistenceGateway>();
_container.RegisterInstance<IEntityManagerProvider>(provider);
}
private void SetViews() {
var regionManager = _container.Resolve<IRegionManager>();
var view = _container.Resolve<ExplorerView>();
regionManager.AddToRegion(RegionNames.MainRegion, view);
regionManager.RegisterViewWithRegion(RegionNames.MainRegion, typeof(ExplorerView));
}
// Destructor strictly to demonstrate when module is GC'd
//~MevModule() {
// System.Console.WriteLine("Goodbye, MevModule");
//}
}
}
The two corresponding methods on a CompositionContainer are ComposeExportedValue<T>(...), which allows you to add a specific instance to the container, and GetExportedValue<T>(...) which gets an instance of T from the container.
If you can design your types in a way to reduce this use of service location and try and prefer constructor injection, it will make your code much easier to maintain and test. E.g., could your code be transformed into:
[Export(typeof(IModule))]
public class ExplorerModule : IModule
{
[ImportingConstructor]
public ExplorerModule(IPersistenceGateway gateway)
{
}
}

Accessing ninject kernel in Application_Start

I am using Ninject and the MVC3 extension installed with nuget. My kernel setup code is in the App_Start/NinjectMVC3.cs file. Everything works great in controllers, but I can't figure out how to (properly) bind interfaces in the Global.asax.cs MvcApplication code.
I ended up using a hack (creating a public NinjectMVC3.GetKernel() method that returns bootstrap.kernel). However, that will be deprecated, and there must be a proper way to do this that I am not seeing.
Here is my code:
public class LogFilterAttribute : ActionFilterAttribute
{
private IReportingService ReportingService { get; set; }
public LogFilterAttribute( IReportingService reportingService )
{
this.ReportingService = reportingService;
}
...
}
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters( GlobalFilterCollection filters )
{
filters.Add( new HandleErrorAttribute() );
filters.Add( new LogFilterAttribute() );
}
...
protected void Application_Start()
{
...
RegisterGlobalFilters( GlobalFilters.Filters );
// NOTE hack:
var kernel = NinjectMVC3.GetKernel();
var logger = kernel.Get<ILogger>();
var bw = new BackgroundWork(logger);
Application["BackgroundWork"] = bw;
bw.Start();
}
}
There are two interfaces I am interested in. The first is just binding an object to a Global variable (the ILogger for the BackgroundWork).
And the second is for an ActionFilter. I read http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/, but I don't see how it plugs into the actual registration (filter.Add).
I don't want to use the Property Inject if I can avoid it.
Any thoughts on the proper way to do this?
Thanks
MVC 3 introduces the DependencyResolver which is populated into a singleton, and the Ninject extension supports it. You could use that in your MvcApplication class if you need it:
protected void Application_Start()
{
// ...
var logger = DependencyResolver.Current.GetService<ILogger>();
}
Now I should point out that it is unnecessary to do this with action filters. In Ninject.MVC3 you are supposed to use the BindFilter syntax, like so:
// Declare empty attribute
public class MyFilterAttribute : FilterAttribute { }
// Dependency module
public class MyModule : NinjectModule
{
public override void Load()
{
// Other bindings
// ...
this.BindFilter<MyActionFilter>(FilterScope.Action, 1)
.WhenControllerHas<MyFilterAttribute>();
}
}
Note that you have to use this because BindFilter is an extension method, and you also have to reference the Ninject.Web.Mvc.FilterBindingSyntax namespace.

Resources