# Add a new control model

WebMap provides basic set of controls that represent the most common controls used in the Windows Forms framework, these controls are implemented within the WebMap DCPs and they ready to be use by any WebMap application that may require them, however, there are several instances in which it may be needed to create a new control model that it is not part of the default set of controls provided. This section will provide a basic guide on how to create a new control model.

**A common occurrence in which a new control may be required is when it forms part of a third-party set of controls that is been used instead of the default Windows Forms controls provided by .NET.**

To create a new control model, it requires the following:

* Create a new class that inherits from **Mobilize.Web.Control**.
* The class must have the **Mobilize.WebMap.Common.Attributes.Observable** attribute.
* All visual properties should have the **Mobilize.WebMap.Common.Attributes.Intercepted** attribute, in order to be able to be synchronized with the front-end.
* The control must have an equivalent component in the front-end.
* A Mapper/DTO may be needed to be implemented in order to synchronize data between the back-end and the front-end.

### Create a new model step by step

To create a new control model, the following steps need to be made.

**Step 1.** Create a new class

![](/files/kbTkgRbgRk7YIMCAfk6c)

**Step 2.** Inherit from the Control class.

{% hint style="info" %}
The new control may inherit directly from any specific control like a Button, Label, Grid, among many other, however, it is required to inherit from Control albeit directly or indirectly.
{% endhint %}

{% hint style="warning" %}
It is possible to avoid the Control inheritance, this topic will be addressed in a different section.
{% endhint %}

```csharp
namespace CustomControlDemo.Controls
{
    public class MyCustomControl : Mobilize.Web.Control
    {
    }
}
```

**Step 3.** Add the Observable attribute

```csharp
namespace CustomControlDemo.Controls
{
    [Mobilize.WebMap.Common.Attributes.Observable]
    public class MyCustomControl : Mobilize.Web.Control
    {
    }
}
```

**Step 4.** Implement the desired properties, methods, and events

{% hint style="warning" %}
It is highly recommended that all visual properties get mark with the Intercepted attribute to optimize their synchronization between the front-end and the back-end.
{% endhint %}

```csharp
namespace CustomControlDemo.Controls
{
    [Mobilize.WebMap.Common.Attributes.Observable]
    public class MyCustomControl : Mobilize.Web.Control
    {
        public MyCustomControl()
        {
            this.BackColor = System.Drawing.Color.Red;
            this.ActAsAButton = false;
            this.Click += (o, s) => this.MyCutomEvent?.Invoke(null, null);
        }
        
        [Mobilize.WebMap.Common.Attributes.Intercepted]
        public bool ActAsAButton { get; set; }
        
        [Mobilize.WebMap.Common.Attributes.Intercepted]
        public int ClickCount { get; set; }
        
        [Mobilize.WebMap.Common.Attributes.Intercepted]
        public EventHandler MyCutomEvent { get; set; }
        
        public void TrackUserInteractions()
        {
            // Some logic here.
        }
    }
}
```

**Step 5.** Create a DTO

{% hint style="info" %}
This is an optional step, however, is highly recommended to create a DTO associated to the control, for more info visit this [section](/webmap/general/backend/dcp-desktop-compatibly-platform/library-bundles/bundle-dto/dto-data-transfer-objects.md).
{% endhint %}

```csharp
namespace CustomControlDemo.DataTransfer
{
    [Mobilize.WebMap.Common.Attributes.DataTransfer("mctmcntrl")]
    public class MyCustomControl
    {
        public bool? ActAsAButton { get; set; }
    }
}
```

**Step 6.** Crete a mapper associated to the new DTO

{% hint style="info" %}
This is an optional step, however, is highly recommended to create a Mapper associated to the control, for more info visit this [section](/webmap/general/backend/dcp-desktop-compatibly-platform/library-bundles/bundle-dto/mappers.md).
{% endhint %}

```csharp
public class MyCutomControlMapper<TObservable, TDto> : Mobilize.WebMap.Common.Messaging.Mapper<TObservable, TDto>
    where TObservable : CustomControlDemo.Controls.MyCustomControl, new()
    where TDto : CustomControlDemo.DataTransfer.MyCustomControl, new()
{
    public override void ApplyChanges(TObservable target, TDto source)
    {
        if(source.ActAsAButton.HasValue && target.ActAsAButton != target.ActAsAButton)
        {
            target.ActAsAButton = source.ActAsAButton.Value;
        }
    }
    public override void Map(TDto target, TObservable source)
    {
        target.ActAsAButton = source.GetChange(x => x.ActAsAButton);
    }
}
```

**Step 7.** Register the new Mapper

```csharp
public class Registrations : Mobilize.WebMap.Common.Core.IRegistration
{
    public void RegisterMappers(IMapperCatalog catalog, ILogger logger)
    {
        catalog.AddMapper(new CustomControlDemo.DataTransfer. MyCutomControlMapper ());
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.gapvelocity.ai/webmap/winforms/extend-or-modify-the-converted-application/add-a-new-control-model.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
