Development troubleshooting

From Maria GDK Wiki
Jump to navigation Jump to search

MariaUserControl not found.

Map info not displayed

FileLoadException unhandled

Appears when available version of an assembly to be loaded does not match the expected version.

Example:

Trs fileloadexept.png
Trs fileexplorer.png

The version of the loaded protobuf-net assembly (in binary folder) is higher than the version expected by the Maira2012 NuGet assemblies.

This is fixed by adding a redirection statement for the assembly in the app.config file.

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            <assemblyIdentity name="protobuf-net"
                publicKeyToken="257b51d87d2e4d67"
                culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-2.0.0.666"
                newVersion="2.0.0.666" />
        </dependentAssembly>
    </assemblyBinding>
</runtime>

Memory leaks in MariaUserControl.

Memory leaks are quite common in WPF applications. Maria GDK is tested for memory problems before every release, but many of the problems can be caused by WPF usage outside of Maria GDK. Below are some pointers to common mistakes.

  • Timers in own view model has to be disposed/stopped.
  • Events that has been subscribed in your own view models needs to be unsubscribed.
  • The suggestion here is to implement IDisposable on your own view models and stop any timers and unsubscribe from events.

Sample Dispose method for code behind of XAML that contains the MariaUserControl:

public void Dispose()
{
   BindingOperations.ClearAllBindings(this);
   //MariaCtrl is the name given to the MariaUserControl instance in XAML
   MariaCtrl.Dispose();
   MariaCtrl = null;

   //Setting DataContext to null avoids many problems that occur
   //with bindings to parts of Maria.
   DataContext = null;

   //_myViewModels is a list of all your own view models.
   foreach(var vm in _myViewModels)
   {
      IDisposable disposableVm = vm as IDisposable.
      if(disposableVm != null)
         disposableVm.Dispose();
   }
}

Displaying service connection info

Working with services, displaying the service URIs and connection status can be informative.

For each service you are connecting to, add the following GUI elements to your main window:

  • Text box displaying the service connection URI.
  • Text block displaying the connection status.

The XAML could look something like this:

...
<GroupBox Header="Service connections">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="auto" />
        </Grid.ColumnDefinitions>

        <Label Grid.Row="0" Grid.Column="0" Content="Service" FontWeight="DemiBold" />
        <Label Grid.Row="1" Grid.Column="0" Content="Catalog" FontWeight="DemiBold" />
        <Label Grid.Row="2" Grid.Column="0" Content="Template" FontWeight="DemiBold" />
        <Label Grid.Row="3" Grid.Column="0" Content="Track" FontWeight="DemiBold" />
        <Label Grid.Row="4" Grid.Column="0" Content="Draw Object" FontWeight="DemiBold" />

        <Label Grid.Row="0" Grid.Column="1" Content="URI" FontWeight="DemiBold" />
        <TextBox Grid.Row="1" Grid.Column="1" Height="22" Margin="5,0,5,0"
                 Text="{Binding MapViewModel.CatalogUri, Mode=OneWay}"   
                 IsReadOnly="True"/>
        <TextBox Grid.Row="2" Grid.Column="1" Height="22" Margin="5,0,5,0"
                 Text="{Binding MapViewModel.TemplateUri, Mode=OneWay}"  
                 IsReadOnly="True"/>
        <TextBox Grid.Row="3" Grid.Column="1"  Height="22" Margin="5,0,5,0"
                 Text="{Binding TrackViewModel.TrackServiceUri, Mode=OneWay}" 
                 IsReadOnly="True"/>
        <TextBox Grid.Row="4" Grid.Column="1" Height="22" Margin="5,0,5,0"
                 Text="{Binding  DrawObjectViewModel.DrawObjectServiceUri, Mode=OneWay}"
                 IsReadOnly="True"/>

        <Label Grid.Row="0" Grid.Column="2" Content="Connected" FontWeight="DemiBold" />
        <TextBlock Grid.Row="1" Grid.Column="2" Margin="5,0,0,0" 
                   Text="{Binding MapViewModel.CatalogStatus}" TextAlignment="Center"/>
        <TextBlock Grid.Row="2" Grid.Column="2" Margin="5,0,0,0" 
                   Text="{Binding MapViewModel.TemplateStatus}"  TextAlignment="Center"/>
        <TextBlock Grid.Row="3" Grid.Column="2" Margin="5,0,0,0" 
                   Text="{Binding TrackViewModel.TrackServiceStatus}" TextAlignment="Center"/>
        <TextBlock Grid.Row="4" Grid.Column="2" Margin="5,0,0,0" 
                   Text="{Binding DrawObjectViewModel.DrawObjectServiceStatus}" TextAlignment="Center"/>
    </Grid>
</GroupBox>
...

In the respective view models, add:

  • URI string property (get only)
  • connection status property.
MapViewModel
...
public string CatalogUri { get { return _mapLayer.MapCatalogServiceClient.Endpoint.Uri.AbsoluteUri; } }
public bool CatalogStatus { get { return _mapLayer.MapCatalogServiceClient.Connected; } }
public string TemplateUri { get { return _mapLayer.MapTemplateServiceClient.Endpoint.Uri.AbsoluteUri; } }
public bool TemplateStatus { get { return _mapLayer.MapTemplateServiceClient.Connected; } }
...
DrawObjectViewModel
...
public string DrawObjectServiceUri { get { return _drawObjectService?.Uri != null ? _drawObjectService.Uri : "--"; } }
public bool DrawObjectServiceStatus { get; private set; }
...
private void DrawObjectLayer_LayerInitialized()
{
    NotifyPropertyChanged(() => DrawObjectServiceStatus);
    NotifyPropertyChanged(() => DrawObjectServiceUri);
...
private void DrawObjectLayer_ServiceConnected(object sender, MariaServiceEventArgs args)
{
    DrawObjectServiceStatus = true;
    NotifyPropertyChanged(() => DrawObjectServiceStatus);
    NotifyPropertyChanged(() => DrawObjectServiceUri);
...
TrackViewModel
...
public string TrackServiceUri { get { return _trackService?.Uri != null ? _trackService.Uri : "--"; } }
public bool TrackServiceStatus { get; private set; }
...
private void TrackLayer_LayerInitialized()
{
    NotifyPropertyChanged(() => TrackServiceStatus);
    NotifyPropertyChanged(() => TrackServiceUri);
...
private void TrackLayer_ServiceConnected(object sender, MariaServiceEventArgs args)
{
    TrackServiceStatus = true;
    NotifyPropertyChanged(() => TrackServiceStatus);
    NotifyPropertyChanged(() => TrackServiceUri);
...

The output will look something like this:

Displaying service connections