Search code examples
c#wpfmapsui

How to use two EditingWidgets in C# Mapsui.WPF simultaneously?


I´m currently trying to draw Polygons and Lines on a Map with the C# Mapsui library for Wpf. The Goal is that when I click the "DrawPolygon" button that I´m able to draw my polygons and the when Clicking the "DrawLines" button the same with lines. And when one Drawing Mode is active and the other Button is clicked then the first one should be disabled. To achive this the "Draw" Button are RadioButton and the respective Widgets always has the same enabled status as the IsChecked Attribute of the Button has.

So I´m able to get it working however I do encounter some wierd issues. I treid two different Approaches and each of them has its drawbacks.

  1. When initializing the EditManager and Widget in the Start up function which is called when the XAML is loaded.

When they are created on start up I want to disable them so that i can´t accidentially draw on my map if i don´t want to. However in doing so the widgets seem to be disabled permenantly. Because on ButtonClick() they are Enabled again but i can´t draw anything. This is very annoying and I dont want to use my other option (see below) which is that I call test on every buttonclick() if the widgets already exist. That seems unneccassary and causes another problem (see below)

  public void LoadModelData(object sender, RoutedEventArgs e)
  {
      DataContext = ViewModel;

      // mapsui load new MapControl to XAML-Tag and add OpenStreetMap
      // then add it to Content of ContentControl-Tag
      mapControl = new Mapsui.UI.Wpf.MapControl();
      mapControl.Map?.Layers.Add(Mapsui.Tiling.OpenStreetMap.CreateTileLayer());
      MapContainer.Content = mapControl;
      mapControl.Map.Widgets.Add(new MapInfoWidget(mapControl.Map)); // should always be first widget
      mapControl.Map.Layers.Add(ViewModel.PolygonLayer, ViewModel.LineLayer);

      mapControl.Info += MapControlOnInfo;
      mapControl.MouseMove += MapControlOnMouseMove;

      
      ViewModel.LineEditManager = new EditManager
      {
          Layer = (WritableLayer)mapControl.Map.Layers.First(l => l.Name == "Line"),
          EditMode = EditMode.AddLine,
      };
      IWidget widget = new EditingWidget(mapControl, ViewModel.LineEditManager, new EditManipulation());
      mapControl.Map.Widgets.Add(widget);
      ViewModel.LineWidgetIndex = mapControl.Map.Widgets.ToList().IndexOf(widget);
// Especially here seems to be the problem
      mapControl.Map.Widgets.ElementAt(ViewModel.LineWidgetIndex).Enabled = false;

      ViewModel.BBoxEditManager = new EditManager
      {
          Layer = (WritableLayer)mapControl.Map.Layers.First(l => l.Name == "Polygon"),
          EditMode = EditMode.AddPolygon,
      };
      widget = new EditingWidget(mapControl, ViewModel.BBoxEditManager, new EditManipulation());
      mapControl.Map.Widgets.Add(widget);
      ViewModel.BBoxWidgetIndex = mapControl.Map.Widgets.ToList().IndexOf(widget);
// and also here 
      mapControl.Map.Widgets.ElementAt(ViewModel.BBoxWidgetIndex).Enabled = false;
  }
  1. As described when initializing the widgets on buttonClick() if the not already exist isn´t that nice. However if i do that I can draw ether the Polygon or the Line first but after using the otherone, the first one won´t be able to be drawn again.
/// <summary>
/// enables or disables Widget for LineLayer
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void DrawLine(object sender, RoutedEventArgs e)
{
    if (ViewModel.LineEditManager.Layer != ViewModel.LineLayer)
    {
        ViewModel.LineEditManager = new EditManager
        {
            Layer = (WritableLayer)mapControl.Map.Layers.First(l => l.Name == "Line"),
            EditMode = EditMode.AddLine,
        };
        IWidget widget = new EditingWidget(mapControl, ViewModel.LineEditManager, new EditManipulation());
        mapControl.Map.Widgets.Add(widget);
        ViewModel.LineWidgetIndex = mapControl.Map.Widgets.ToList().IndexOf(widget);
    }

    mapControl.Map.Widgets.ElementAt(ViewModel.LineWidgetIndex).Enabled = drawSection.IsChecked.Value; 
}

/// <summary>
/// enables or disables Widget for PolygonLayer
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DrawBBox(object sender, RoutedEventArgs e)
{
    if (ViewModel.BBoxEditManager.Layer != ViewModel.PolygonLayer)
    {
        ViewModel.BBoxEditManager = new EditManager
        {
            Layer = (WritableLayer)mapControl.Map.Layers.First(l => l.Name == "Polygon"),
            EditMode = EditMode.AddPolygon,
        };
        IWidget widget = new EditingWidget(mapControl, ViewModel.BBoxEditManager, new EditManipulation());
        mapControl.Map.Widgets.Add(widget);
        ViewModel.BBoxWidgetIndex = mapControl.Map.Widgets.ToList().IndexOf(widget);
    }

    mapControl.Map.Widgets.ElementAt(ViewModel.BBoxWidgetIndex).Enabled = drawBBox.IsChecked.Value; 
}

If someone has an Idea how to fix any of these approaches (or even another), I would be grateful.

Thanks in Advance.


Solution

  • Use a custom widget.

    The editing widget was recently added to Mapsui and is not yet very sophisticated. You have requirements that we did not have in mind when creating the first version. Your best option is probably to take things under your own control and create a custom widget.

    Clone the source code of Mapsui and look for CustomWidgetSample.cs and CustomWidgetSkiaRenderer.cs (you need to register the renderer). If you have that working look at the EditingWidget. Copy that code to your custom widget and modify it to your own needs.