Skip to content

Commit

Permalink
Merge branch 'main' into live
Browse files Browse the repository at this point in the history
  • Loading branch information
cxwtool committed Aug 4, 2023
2 parents b5f68cf + e1601a1 commit 582a4d4
Show file tree
Hide file tree
Showing 59 changed files with 2,790 additions and 193 deletions.
344 changes: 186 additions & 158 deletions .openpublishing.redirection.winforms.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ If your components are defined by a project in the currently open solution, they

- Does not have <xref:System.ComponentModel.DesignTimeVisibleAttribute> set to `false`.

> [!NOTE]
> The **Toolbox** does not follow reference chains, so it won't display items that are not built by a project in your solution.
[!INCLUDE [visual-studio-designer-net](../includes/visual-studio-designer-net.md)]

This walkthrough demonstrates how a custom component automatically appears in the **Toolbox** once the component is built. Tasks illustrated in this walkthrough include:

Expand All @@ -33,6 +32,9 @@ This walkthrough demonstrates how a custom component automatically appears in th

When you are finished, you will see that the **Toolbox** is populated with a component that you have created.

> [!NOTE]
> The **Toolbox** only displays components from libraries directly referenced by your project or components defined by a project in the solution.
## Create the project

1. In Visual Studio, create a Windows-based application project called `ToolboxExample` (**File** > **New** > **Project** > **Visual C#** or **Visual Basic** > **Classic Desktop** > **Windows Forms Application**).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ dev_langs:

The Visual Designer for Windows Forms for .NET has had some improvements and changes since .NET Framework. These changes largely affect custom control designers. This article describes the key differences from .NET Framework.

[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)]

Visual Studio is a .NET Framework-based application, and as such, the Visual Designer you see for Windows Forms is also based on .NET Framework. With a .NET Framework project, both the Visual Studio environment and the Windows Forms app being designed, run within the same process: **devenv.exe**. This poses a problem when you're working with a Windows Forms .NET (not .NET Framework) app. Both .NET and .NET Framework code can't work within the same process. As a result, Windows Forms .NET uses a different designer, the "out-of-process" designer.

[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)]

## Out-of-process designer

The out-of-process designer is a process called **DesignToolsServer.exe**, and is run along-side Visual Studio's **devenv.exe** process. The **DesignToolsServer.exe** process runs on the same version and platform of .NET that your app has been set up to target, such as .NET 7 and x64.
Expand Down
452 changes: 452 additions & 0 deletions dotnet-desktop-guide/net/winforms/controls-design/designer-errors.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ helpviewer_keywords:
- "controls [Windows Forms], composite"
---

# Overview about Visual Studio design-time support for custom controls (Windows Forms .NET)
# Visual Studio design-time support for custom controls (Windows Forms .NET)

As you've noticed when interacting with the Windows Forms designer, there are many different design-time features offered by the Windows Forms controls. Some of the features offered by the Visual Studio Designer include snap lines, action items, and the property grid. All of these features offer you an easier way to interact and customize a control during design-time. This article is an overview about what kind of support you can add to your custom controls, to make the design-time experience better for the consumers of your controls.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
title: Design-time properties overview
description: Learn about how the Windows Forms Designer interacts with control and form properties during design-time.
ms.date: 07/14/2023
ms.topic: overview
no-loc: ["UserControl"]
dev_langs:
- "csharp"
- "vb"
f1_keywords:
- "UserControl"
helpviewer_keywords:
- "controls [Windows Forms], composite"
---

# Design-time properties for custom controls (Windows Forms .NET)

This article teaches you about how properties are handled for controls in the Windows Forms Visual Designer in Visual Studio.

Every control inherits many properties from the base class <xref:System.Windows.Forms.Control?displayProperty=nameWithType>, such as:

- <xref:System.Windows.Forms.Control.Enabled%2A>
- <xref:System.Windows.Forms.Control.Font%2A>
- <xref:System.Windows.Forms.Control.ForeColor%2A>
- <xref:System.Windows.Forms.Control.Focused%2A>
- <xref:System.Windows.Forms.Control.Visible%2A>
- <xref:System.Windows.Forms.Control.Width%2A>

When creating a control, you can define new properties and control how they appear in the designer.

[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)]

## Define a property

Any public property with a **get** accessor defined by a control is automatically visible in the Visual Studio **Properties** window. If the property also defines a **set** accessor, the property can be changed in the **Properties** window. However, properties can be explicitly displayed or hidden from the **Properties** window by applying the <xref:System.ComponentModel.BrowsableAttribute>. This attribute takes a single boolean parameter to indicate whether or not it's displayed. For more information about attributes, see [Attributes (C#)](/dotnet/csharp/programming-guide/concepts/attributes/index) or [Attributes overview (Visual Basic)](/dotnet/visual-basic/programming-guide/concepts/attributes/index).

:::code language="csharp" source="./snippets/designer-properties-overview/csharp/CompassRose.cs" id="browsable":::
:::code language="vb" source="./snippets/designer-properties-overview/vb/CompassRose.vb" id="browsable":::

> [NOTE]
> Complex properties that can't be implicitly converted to and from a string require a type converter.
## Serialized properties

Properties set on a control are serialized into the designer's code-behind file. This happens when the value of a property is set to something other than its default value.

When the designer detects a change to a property, it evaluates all properties for the control and serializes any property whose value doesn't match the default value for the property. The value of a property is serialized into the designer's code-behid file. Default values help the designer to determine which property values should be serialized.

## Default values

A property is considered to have a default value when it either applies the <xref:System.ComponentModel.DefaultValueAttribute> attribute, or the property's class contains property-specific `Reset` and `ShouldSerialize` methods. For more information about attributes, see [Attributes (C#)](/dotnet/csharp/programming-guide/concepts/attributes/index) or [Attributes overview (Visual Basic)](/dotnet/visual-basic/programming-guide/concepts/attributes/index).

By setting a default value, you enable the following:

- The property provides visual indication in the **Properties** window if it has been modified from its default value.
- The user can right-click on the property and choose **Reset** to restore the property to its default value.
- The designer generates more efficient code.

If a property uses a simple type, such as a primitive type, the default value can be set by applying the `DefaultValueAttribute` to the property. However, properties with this attribute don't automatically start with that assigned value. You must set the property's backing field to the same default value. You can set the property on the declaration or in the class's constructor.

When a property is a complex type, or you want to control the designer's reset and serialization behavior, define the `Reset<PropertyName>` and `ShouldSerialize<PropertyName>` methods on the class. For example, if the control defines an `Age` property, the methods are named `ResetAge` and `ShouldSerializeAge`.

> [!IMPORTANT]
> Either apply the `DefaultValueAttribute` to the property, or provide both `Reset<PropertyName>` and `ShouldSerialize<PropertyName>` methods. Don't use both.
Properties can be "reset" to their default values through the **Properties** window by right-clicking on the property name and selecting **Reset**.

:::image type="content" source="media/designer-properties-overview/vs-properties-reset.png" alt-text="The Reset context menu item in the properties grid.":::

The availability of the **Properties** > **Right-click** > **Reset** context menu option is enabled when:

- The property has the <xref:System.ComponentModel.DefaultValueAttribute> attribute applied, and the value of the property doesn't match the attribute's value.
- The property's class defines a `Reset<PropertyName>` method without a `ShouldSerialize<PropertyName>`.
- The property's class defines a `Reset<PropertyName>` method and the `ShouldSerialize<PropertyName>` returns true.

### DefaultValueAttribute

If a property's value doesn't match the value provided by <xref:System.ComponentModel.DefaultValueAttribute>, the property is considered changed and can be reset through the **Properties** window.

> [!IMPORTANT]
> This attribute shouldn't be used on properties that have corresponding `Reset<PropertyName>` and `ShouldSerialize<PropertyName>` methods.
The following code declares two properties, an enumeration with a default value of `North` and an integer with a default value of 10.

:::code language="csharp" source="./snippets/designer-properties-overview/csharp/CompassRose.cs" id="defaultvalue":::
:::code language="vb" source="./snippets/designer-properties-overview/vb/CompassRose.vb" id="defaultvalue":::

### Reset and ShouldSerialize

As previously mentioned, the `Reset<PropertyName>` and `ShouldSerialize<PropertyName>` methods provide the opportunity to guide not only the reset behavior of a property, but also in determining if a value is changed and should be serialized into the designer's code-behind file. Both methods work together and you shouldn't define one without the other.

> [!IMPORTANT]
> The `Reset<PropertyName>` and `ShouldSerialize<PropertyName>` methods shouldn't be created for a property that has a <xref:System.ComponentModel.DefaultValueAttribute>.
When `Reset<PropertyName>` is defined, the **Properties** window displays a **Reset** context menu option for that property. When **Reset** is selected, the `Reset<PropertyName>` method is invoked. The **Reset** context menu option is enabled or disabled by what is returned by the `ShouldSerialize<PropertyName>` method. When `ShouldSerialize<PropertyName>` returns `true`, it indicates that the property has changed from its default value and should be serialized into the code-behind file and enables the **Reset** context menu option. When `false` is returned, the **Reset** context menu option is disabled and the code-behind has the property-set code removed.

> [!TIP]
> Both methods can and should be defined with private scope so that they don't make up the public API of the control.
The following code snippet declares a property named `Direction`. This property's designer behavior is controlled by the `ResetDirection` and `ShouldSerializeDirection` methods.

:::code language="csharp" source="./snippets/designer-properties-overview/csharp/CompassRose.cs" id="shouldserialize_reset":::
:::code language="vb" source="./snippets/designer-properties-overview/vb/CompassRose.vb" id="shouldserialize_reset":::

## Type converters

While type converters typically convert one type to another, they also provide string-to-value conversion for the property grid and other design-time controls. String-to-value conversion allows complex properties to be represented in these design-time controls.

Most built-in data types (numbers, enumerations, and others) have default type converters that provide string-to-value conversions and perform validation checks. The default type converters are in the `System.ComponentModel` namespace and are named after the type being converted. The converter type names use the following format: `{type name}Converter`. For example, <xref:System.ComponentModel.StringConverter>, <xref:System.ComponentModel.TimeSpanConverter>, and <xref:System.ComponentModel.Int32Converter>.

Type converters are used extensively at design-time with the **Properties** window. A type converter can be applied to a property or a type, using the <xref:System.ComponentModel.TypeConverterAttribute>.

The **Properties** window uses converters to display the property as a string value when the `TypeConverterAttribute` is declared on the property. When the `TypeConverterAttribute` is declared on a type, the **Properties** window uses the converter on every property of that type. The type converter also helps with serializing the property value in the designer's code-behind file.

<!--
Example is available at https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2013/ayybcxe5(v=vs.120)#type-converters-that-provide-a-list-of-standard-values-to-a-properties-window
This should be converted into examples
-->

## Type editors

The **Properties** window automatically uses a type editor for a property when the type of the property is a built-in or known type. For example, a boolean value is edited as a combo box with **True** and **False** values and the <xref:System.DateTime> type uses a calendar dropdown.

> [!IMPORTANT]
> Custom type editors have changed since .NET Framework. For more information, see [The designer changes since .NET Framework (Windows Forms .NET)](designer-differences-framework.md).
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ helpviewer_keywords:

If you want to add more features to an existing control, you can create a control that inherits from an existing control. The new control contains all of the capabilities and visual aspect of the base control, but gives you opportunity to extend it. For example, if you created a control that inherits <xref:System.Windows.Forms.Button>, your new control would look and act exactly like a button. You could create new methods and properties to customize the behavior of the control. Some controls allow you to override the <xref:System.Windows.Forms.Control.OnPaint%2A> method to change the way the control looks.

[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)]

## Add a custom control to a project

After creating a new project, use the Visual Studio templates to create a user control. The following steps demonstrate how to add a user control to your project:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ The user control is made up of _constituent controls_, which are the controls yo
01. Make the following code changes:

01. At the top of the code file, import the `System.ComponentModel` namespace.
01. Add the `DefaultEvent` attribute to the class. This attribute sets which event is generated by the consumer when the control is double-clicked in the designer. The consumer being the object declaring and using this control.
01. Add the `DefaultEvent` attribute to the class. This attribute sets which event is generated by the consumer when the control is double-clicked in the designer. The consumer being the object declaring and using this control. For more information about attributes, see [Attributes (C#)](/dotnet/csharp/programming-guide/concepts/attributes/index) or [Attributes overview (Visual Basic)](/dotnet/visual-basic/programming-guide/concepts/attributes/index).

:::code language="csharp" source="./snippets/how-to-create-usercontrol/csharp/ClearableTextBox.cs" id="default_event":::
:::code language="vb" source="./snippets/how-to-create-usercontrol/vb/ClearableTextBox.vb" id="default_event":::
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
title: How to use the Reset and ShouldSerialize methods
description: Learn how to implement the Reset and ShouldSerialize methods to control a property during design-time in Windows Forms.
ms.date: 07/20/2023
ms.topic: how-to
dev_langs:
- "csharp"
- "vb"
f1_keywords:
- "Reset"
- "ShouldSerialize"
helpviewer_keywords:
- "design-time properties"
- "designer properties"
- "reset property"
---

# Use Reset and ShouldSerialize to control a property (Windows Forms .NET)

In this article, you learn how to create the `Reset<PropertyName>` and `ShouldSerialize<PropertyName>` methods to manage a property for the **Properties** window in Visual Studio. `Reset` and `ShouldSerialize` are optional methods that you can provide for a property, if the property doesn't have a simple default value. If the property has a simple default value, you should apply the <xref:System.ComponentModel.DefaultValueAttribute> and supply the default value to the attribute class constructor instead. Either of these mechanisms enables the following features in the designer:

- The property provides visual indication in the property browser if it has been modified from its default value.
- The user can right-click on the property and choose **Reset** to restore the property to its default value.
- The designer generates more efficient code.

For more information about properties, see [Reset and ShouldSerialize](designer-properties-overview.md#reset-and-shouldserialize).

[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)]

## Supporting code

This article demonstrates the `Reset` and `ShouldSerialize` methods by creating a compass rose control. If you're working with your own user control, you can skip this section.

01. Add the following enumeration to your code:

:::code language="csharp" source="./snippets/how-to-designer-properties-shouldserialize-reset/csharp/Directions.cs" id="enum":::
:::code language="vb" source="./snippets/how-to-designer-properties-shouldserialize-reset/vb/Directions.vb" id="enum":::

01. Add a user control named `CompassRose`.
01. Add a property named `Direction` of type `Directions` to the user control.

:::code language="csharp" source="./snippets/how-to-designer-properties-shouldserialize-reset/csharp/CompassRose.cs" id="property":::
:::code language="vb" source="./snippets/how-to-designer-properties-shouldserialize-reset/vb/CompassRose.vb" id="property":::

## Reset

The `Reset<PropertyName>` method resets the corresponding `<PropertyName>` property to its default value.

The following code resets the `Direction` property to `None`, which is considered the default value for the compass rose control:

:::code language="csharp" source="./snippets/how-to-designer-properties-shouldserialize-reset/csharp/CompassRose.cs" id="reset":::
:::code language="vb" source="./snippets/how-to-designer-properties-shouldserialize-reset/vb/CompassRose.vb" id="reset":::

## ShouldSerialize

The `ShouldSerialize<PropertyName>` method returns a boolean value that indicates whether or not the backing property has changed from its default value and should be serialized into the designer's code.

The following code returns true when the `Direction` property doesn't equal `None`, indicating that a direction has been chosen:

:::code language="csharp" source="./snippets/how-to-designer-properties-shouldserialize-reset/csharp/CompassRose.cs" id="shouldserialize":::
:::code language="vb" source="./snippets/how-to-designer-properties-shouldserialize-reset/vb/CompassRose.vb" id="shouldserialize":::

## Example

The following code shows the `Reset` and `ShouldSerialize` methods for the `Direction` property:

:::code language="csharp" source="./snippets/how-to-designer-properties-shouldserialize-reset/csharp/CompassRose.cs" id="control":::
:::code language="vb" source="./snippets/how-to-designer-properties-shouldserialize-reset/vb/CompassRose.vb" id="control":::
Loading

0 comments on commit 582a4d4

Please sign in to comment.