Examples of using Ikc5.Prism.Settings

This post describes an example of the using NuGet packages under the common title Ikc5.Prism.Settings: Ikc5.Prism.Settings.Library, Ikc5.Prism.Settings.Module and Ikc5.Prism.Settings.Application. These packages allow manipulate user settings in Prism applications and serialize/deserialize them in xml files. All package contains the same library and last two packages add models, view models and views to the project. Full code is accessible on GitHub Blog repository.

Application

Let’s create Windows application in WPF using the Prism Library. Application and two modules have their own sets of user settings and two common properties: BackgroundColor and Name. These values will be used in order to show current values of user settings. At first launch all settings have default values and application window looks in the following way:

Application window
Application window with default user settings

Then user may call the settings window, modify and save settings:

Default user settings
Default user settings
New user settings for application
New user settings for application
New user settings for module Part1
New user settings for module Part1
New user settings for module Part2
New user settings for module Part2

Application window changes look according to new values:

Application window with new user settings
Application window with new user settings

Folder NewSettings located in application launch folder contains three files for user settings:

Settings files
Settings files

When user will launch application at the next time, it deserializes user settings and will look exactly in the same way.

Solution

Now describe steps of the development. Let’s create new solution and add 4 projects:

  • Class library CommonLibrary. It is shared library that contains custom user settings provider. For example, we just override name of folder where settings are stored;
  • Wpf user control library Part1Module that contains Prism module;
  • Wpf user control library Part2Module that contains Prism module;
  • Wpf Application WpfApplication that is the startup project.

CommonLibrary

At first, add NuGet package Ikc5.Prism.Settings.Library to the library.

CommonLibrary - add Ikc5.Prism.Settings.Library
CommonLibrary – add Ikc5.Prism.Settings.Library

It adds two other packages, Ikc5.TypeLibrary and Prism.Core. Let’s add FileXmlUserSettingsProvider.cs file for custom file provider, and write the following code:

public class FileXmlUserSettingsProvider<T> : LocalXmlUserSettingsProvider<T> where T : class, IUserSettings
{
	public FileXmlUserSettingsProvider(ILiteObjectService liteObjectService, ILoggerFacade logger)
		: base(liteObjectService, logger)
	{
		var assembly = Assembly.GetEntryAssembly();
		FolderName = Path.Combine(Path.GetDirectoryName(assembly.Location) ?? "", "NewSettings");
	}
}

In default constructor it overrides folder name, and makes it equals NewSettings.

Part1Module and Part2Module

These two projects are modified in the similar way. Let’s add NuGet package Ikc5.Prism.Settings.Module to the module projects.

Modules - add Ikc5.Prism.Settings.Module
Modules – add Ikc5.Prism.Settings.Module

This package depends on several packages: Ikc5.TypeLibrary, Prism.Core, Prism.Wpf, and Prism.Unity. Also, it adds empty settings models, settings view models and views to the project.

Modules - added files and readme
Modules – added files and readme

In the readme file code for Module class is listed, and therefore we add Part1Module.cs and Part2Module.cs files and modified them:

Modules - add Module files
Modules – add Module files
public class Part1Module : IModule
{
	private readonly IRegionManager _regionManager;

	private readonly IUnityContainer _container;

	public Part1Module(IRegionManager regionManager, IUnityContainer container)
	{
		_regionManager = regionManager;
		_container = container;
		ConfigureContainer();
	}

	private void ConfigureContainer()
	{
		_container.RegisterType<ISettings, Models.Settings>(new ContainerControlledLifetimeManager());
	}

	public void Initialize()
	{
		_regionManager.RegisterViewWithRegion($"{GetType().Name}{RegionNames.ModuleSettingsRegion}", typeof(SettingsView));
		_regionManager.RegisterViewWithRegion($"{GetType().Name}{RegionNames.ModuleViewRegion}", typeof(UserControl1));
	}
}
public class Part2Module : IModule
{
	private readonly IRegionManager _regionManager;

	private readonly IUnityContainer _container;

	public Part2Module(IRegionManager regionManager, IUnityContainer container)
	{
		_regionManager = regionManager;
		_container = container;
		ConfigureContainer();
	}

	private void ConfigureContainer()
	{
		_container.RegisterType<ISettings, Models.Settings>(new ContainerControlledLifetimeManager());
	}

	public void Initialize()
	{
		_regionManager.RegisterViewWithRegion($"{GetType().Name}{RegionNames.ModuleSettingsRegion}", typeof(SettingsView));
		_regionManager.RegisterViewWithRegion($"{GetType().Name}{RegionNames.ModuleViewRegion}", typeof(UserControl1));
	}
}

Now we need to add some properties to modules. Module Part1Module has four properties:

/// <summary>
/// Common settings for Module.
/// </summary>
public interface ISettings
{
	/// <summary>
	/// Module's name.
	/// </summary>
	string Name { get; set; }

	/// <summary>
	/// Background color.
	/// </summary>
	Color BackgroundColor { get; set; }

	/// <summary>
	/// Checked state.
	/// </summary>
	bool IsChecked { get; set; }

	/// <summary>
	/// Desired count of something.
	/// </summary>
	int Count { get; set; }
}

Respectively, module Part2Module has other four properties:

/// <summary>
/// Common settings for Module.
/// </summary>
public interface ISettings
{
	/// <summary>
	/// Module's name.
	/// </summary>
	string Name { get; set; }

	/// <summary>
	/// Background color.
	/// </summary>
	Color BackgroundColor { get; set; }

	/// <summary>
	/// Desired width of Part2.
	/// </summary>
	int Width { get; set; }

	/// <summary>
	/// Desired height of Part2.
	/// </summary>
	int Height { get; set; }
}

Then we need add implementation to Settings.cs and SettingsViewModel.cs. As Settings class is derived from UserSettings class, and it implements INotifyPropertyChanged interface, it worth to implement properties in notifiable way. Also, properties are initialize only by their DefaultValue attribute. For example, implementation of Settings.cs is the following:

[Serializable]
public class Settings : UserSettings, ISettings
{
	public Settings(IUserSettingsService userSettingsService, IUserSettingsProvider<Settings> userSettingsProvider)
		: base(userSettingsService, userSettingsProvider)
	{
	}

	#region ISettings

	private string _name;               // = "Part1";
	private Color _backgroundColor;     // = Colors.DarkSeaGreen;
	private bool _isChecked;            // = true;
	private int _count;                 // = 100;

	/// <summary>
	/// Module's name.
	/// </summary>
	[DefaultValue("Part1")]
	public string Name
	{
		get { return _name; }
		set { SetProperty(ref _name, value); }
	}

	/// <summary>
	/// Background color.
	/// </summary>
	[DefaultValue(typeof(Color), "#FF8FBC8F")]
	public Color BackgroundColor
	{
		get { return _backgroundColor; }
		set { SetProperty(ref _backgroundColor, value); }
	}

	/// <summary>
	/// Checked state.
	/// </summary>
	[DefaultValue(true)]
	public bool IsChecked
	{
		get { return _isChecked; }
		set { SetProperty(ref _isChecked, value); }
	}

	/// <summary>
	/// Desired count of something.
	/// </summary>
	[DefaultValue(100)]
	public int Count
	{
		get { return _count; }
		set { SetProperty(ref _count, value); }
	}

	#endregion

}

The last step is to modify SettingsView.xaml in order to provide user possibility to change values of user settings. In this sample, we provide simple list-looks set of corresponding user controls that are bound to user setting properties. For example,

<TextBlock
    Grid.Row="0"
    Grid.Column="0"
    Text="Name"/>

<TextBox
    Grid.Row="0"
    Grid.Column="1"
    Text="{Binding Name, Mode=TwoWay}" 
    TabIndex="101"
    Margin="5 2 5 2"/>

There are all steps for the implementing user settings in Prism module.

WpfApplication

Similar to previous projects, we add NuGet package Ikc5.Prism.Settings.Application.

WpfApplication - add Ikc5.Prism.Settings.Application
WpfApplication – add Ikc5.Prism.Settings.Application

This package depends on several packages: Ikc5.TypeLibrary, Prism.Core, Prism.Wpf, and Prism.Unity. Also, it adds empty settings models, settings view models and views to the project.

WpfApplication - added files and readme
WpfApplication – added files and readme

Most of steps are similar to adding properties to the Prism modules. In addition, application includes SettingsWindow window that contains region for application settings and tab control with tab items for user settings for all modules. Also, readme file describes necessary modification in Bootstrapper.cs file:

public class Bootstrapper : UnityBootstrapper
{
	/// <summary>
	/// Configures the <see cref="IUnityContainer"/>. May be overwritten in a derived class to add specific
	/// type mappings required by the application.
	/// </summary>
	protected override void ConfigureContainer()
	{
		base.ConfigureContainer();

		ViewModelLocationProvider.SetDefaultViewModelFactory((type) => Container.Resolve(type));
		// create singleton of UserSettingsService
		Container
			.RegisterType<IUserSettingsService, UserSettingsService>(new ContainerControlledLifetimeManager())
			.RegisterType<ILiteObjectService, LiteObjectService>(new ContainerControlledLifetimeManager())
			.RegisterType<ISettings, Settings>(new ContainerControlledLifetimeManager())
			.RegisterType<IMainViewModel, MainViewModel>();

		Container.RegisterType(
			typeof(IUserSettingsProvider<>),
			typeof(FileXmlUserSettingsProvider<>),
			new ContainerControlledLifetimeManager());
	}


	/// <summary>
	/// Initializes the shell.
	/// </summary>
	/// <remarks>
	/// The base implemention ensures the shell is composed in the container.
	/// </remarks>
	protected override void InitializeShell()
	{
		// add some views to region adapter
		var regionManager = Container.Resolve<IRegionManager>();
		regionManager.RegisterViewWithRegion(RegionNames.AppSettingsRegion, typeof(SettingsView));

		Application.Current.MainWindow.Show();
	}

	protected override void ConfigureModuleCatalog()
	{
		var catalog = (ModuleCatalog)ModuleCatalog;
		// add all modules
		catalog.AddModule(typeof(Part1Module.Part1Module));
		catalog.AddModule(typeof(Part2Module.Part2Module));
	}
}

1. All used IP-addresses, names of servers, workstations, domains, are fictional and are used exclusively as a demonstration only.
2. Information is provided «AS IS».

2 thoughts on “Examples of using Ikc5.Prism.Settings

  1. […] The packages are open-source project, full code is accessible on GitHub NuGet repository. Repository contains nuspec files and file trees for Ikc5.Prism.Settings.Application and Ikc5.Prism.Settings.Module packages. Symbol’s packages was pushed to SymbolSource.org. Example of the using this package is considered in the post Examples of using Ikc5.Prism.Settings. […]

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.