MMP Video Editor (RCE): adding configuration parameters

If you want to extend RCE by adding a new module, it is possible taht you need to add some configuration parameters for the module’s logic. Depending of the nature of your module, you will set the configuration parameter when deploying the application in your server or using another approach you could allow the user to modify this configuration parameters in the application UI.

To analyze these two situations let’s suppose we need to implement an alerts module to check for alerts provided by a remote service. This new module depends on a integer parameter that sets the interval the alert service will be checked. This parameter cannot be modified by the user. What the user can decide is to enable or disable the alerts module while running the application.

So, we will create a new module following RCE architecture (that is based on Prism) and we will add our new module to the ModuleCatalag in the shell project.

To manage the interval parameter, we will add a new entry in the Settings.xml file in the RCE.Web project.

[code lang=”xml”]<Parameter Name="AlertsInterval" Value="10000"/>[/code]

Then, to access this parameter, we can use the IConfigurationService provided by the RCE.Infrastructure assembly. We just have to declare this interface to be injected by the container into our instance.

[code lang=”csharp”]
public AlertsPresenter(IEventAggregator eventAggregator, IAlertsView view, IAlertService alertService, IConfigurationService configurationService)
{
int interval = configurationService.GetParameterValueAsInt("AlertsInterval").GetValueOrDefault(1000);
// perform additional initialization logic here
}
[/code]

Note that GetParameterValueAsInt is an extension method and to be able to use it, you have to add a using statement for RCE.Infrastructure.

To manage the other parameter that can be modified by the user to enable/disable the module, we should use the settings module, just to be consistent with the application. As it is provided, the settings module was not designed in a extensible way, I mean, if we need to manage a new parameter in the settings view, we have to modify the settings module each time we want to add something new. We could modify the settings module to handle our specific parameters, but instead of that we will modify the settings module to make it more flexible and avoid future modifications.

We will start by adding a new Region inside the Settings view, to allow each new module to add its own settings view. To do this, we have to include the following declaration at the beginning of the file SettingsView.xaml file.

[code lang=”xml”]<UserControl xmlns:input="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"&nbsp; x:Class="RCE.Modules.Settings.SettingsView" xmlns=<a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation">http://schemas.microsoft.com/winfx/2006/xaml/presentation</a> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&nbsp; xmlns:d="http://schemas.microsoft.com/expression/blend/2008"&nbsp; xmlns:mc=<a href="http://schemas.openxmlformats.org/markup-compatibility/2006">http://schemas.openxmlformats.org/markup-compatibility/2006</a>&nbsp; xmlns:Regions="clr-namespace:Microsoft.Practices.Composite.Presentation.Regions;assembly=Microsoft.Practices.Composite.Presentation" mc:Ignorable="d" xmlns:Commands="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation" xmlns:Interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" <br>xmlns:Behaviors="clr-namespace:RCE.Modules.Settings.Behaviors" BorderThickness="0" d:DesignHeight="926">[/code]

Then, we need to add a new row to the container Grid

[code lang=”xml”]<RowDefinition Height="80"/>[/code]

Finally, we add the new region in the new row at the end of the file.

[code lang=”xml”] <Border Grid.Column="0" Grid.Row="14" Background="{StaticResource ComboBrush}" CornerRadius="8,8,8,8" Grid.ColumnSpan="2" HorizontalAlignment="Center" Width="350" VerticalAlignment="Center" Height="85" Style="{StaticResource SharedBorderStyle}">
<ItemsControl Regions:RegionManager.RegionName="ExtendedSettingsRegion" /></Border>[/code]

Now, we need to add the ExtendedSettingsRegion region to the RegionNames class in the RCE.Infrastructure project.

[code lang=”csharp”]public const string ExtendedSettingsRegion = "ExtendedSettingsRegion";[/code]

At this point, if we run the application, we will see the following Settings view.

image

Now, each new module should define a view to be loaded in the ExtendedSettingsRegion (of course it is not mandatory, it is just in case the module requires to manage settings). In the case of our AlertsModule we have just 3 visual controls, a textblock, a check box and a button.

[code]<UserControl x:Class="RCE.Modules.SWUAlerts.Views.AlertsSettingsView" xmlns=<a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation">http://schemas.microsoft.com/winfx/2006/xaml/presentation</a> xmlns:x=<a href="http://schemas.microsoft.com/winfx/2006/xaml">http://schemas.microsoft.com/winfx/2006/xaml</a> xmlns:d="http://schemas.microsoft.com/expression/blend/2008"&nbsp;&nbsp;&nbsp;&nbsp; xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"&nbsp;&nbsp;&nbsp;&nbsp; xmlns:Commands="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mc:Ignorable="d"&gt;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Grid&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Grid.ColumnDefinitions&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ColumnDefinition Width="0.5*"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ColumnDefinition Width="0.5*"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/Grid.ColumnDefinitions&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Grid.RowDefinitions&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RowDefinition Height="0.5*"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RowDefinition Height="0.5*"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/Grid.RowDefinitions&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock Grid.Column="0" Grid.Row="0" Text="Alerts enabled" FontWeight="Bold" FontSize="11" Foreground="{StaticResource ForegroundBrush}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,5,0"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CheckBox x:Name="AlertsEnabled" Grid.Column="1" Grid.Row="0" IsChecked="{Binding Path=AlertsEnabled, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}" VerticalAlignment="Center" />
<Button Grid.Column="1"&nbsp; Grid.Row="1" Content="Apply" Commands:Click.Command="{Binding ApplyAlertsSettignsCommand}" VerticalAlignment="Center" Width="110" Margin="0,0,10,0" Cursor="Hand" HorizontalAlignment="Left" Foreground="{StaticResource ForegroundBrushAlternative}" Background="{StaticResource ToolBarBrush}" Template="{StaticResource SetttingsButtonTemplate}"/></Grid>
</UserControl>;
[/code]

image

The other extension point to consider is the persistence of the parameter. The settings module manages the persistence using the configuration service, so we can use it and it will be almost the same we did for the static parameter. We just have to declare the dependency to be injected in the constructor and adding a new entry in the settings file.

[code lang=”charp”]public AlertsSettingsPresenter(IAlertsSettingsView view, IConfigurationService configurationService){..}[/code]

[code]<Parameter Name="AlertsEnabled" Value="True"/>[/code]

And use it when handling the apply event.

[code lang=”chsarp”]public void ApplySettings(object parameter)
{
var valuesToUpdate = new Dictionary<string, string>();
valuesToUpdate.Add("AlertsEnabled", this.AlertsEnabled.ToString
this.configurationService.UpdateParameters(valuesToUpdate);
}
[/code]

If our module needs to updated itself when a configuration value changes, we could subscribe to the ConfigurationChanged event of the configurationService.

That’s all folks! Let’s do a recap:

  • We modified the settings Module to include a new Region (ExtendedSettingsRegion)
  • We created a Settings view in our module (AlertsSettingsView)
  • We added the the corresponding presenter (AlertsSettingPresenter) to able the update of the parameters

Below is a screenshot of the final project of my module.

image

TODOs:

The way this solution is implemented requires each module to handle the persistence, I mean, each module has to provide a “save” button and call the configuration service. I think that applying a refactoring this logic could be handled by the settings module, but that is part of another post.



Leave a Reply