I upgraded a WinForms App to .NET Core 3.1 these days. It's an open-source on-screen ruler created by Jeff Key in 2004, the original code was for .NET Framework 2.0, I've already upgraded it to .NET Core 3.0 in September this year, it was very smooth without any code change. But this time, .NET Core 3.1 does require some code changes.
The project is on my GitHub: https://github.com/EdiWang/Ruler
According to Microsoft .NET Blog, .NET Core 3.1 for Windows Forms has some breaking changes by removing some controls.
The following Windows Forms controls have been removed from .NET Core 3.1:
- DataGrid
- ToolBar
- ContextMenu
- Menu
- MainMenu
- MenuItem
These controls were replaced with more powerful controls in .NET Framework 2.0, back in 2005. They have not been available by default in the Visual Studio Designer Toolbox for many years. As a result, we decided to remove these controls and focus only on the new ones.
And they have recommended replacements for these controls:
Old Control (API) | Recommended Replacement | Other associated APIs removed |
---|---|---|
DataGrid | DataGridView | DataGridCell, DataGridRow, DataGridTableCollection, DataGridColumnCollection, DataGridTableStyle, DataGridColumnStyle, DataGridLineStyle, DataGridParentRowsLabel, DataGridParentRowsLabelStyle, DataGridBoolColumn, DataGridTextBox, GridColumnStylesCollection, GridTableStylesCollection, HitTestType |
ToolBar | ToolStrip | ToolBarAppearance |
ToolBarButton | ToolStripButton | ToolBarButtonClickEventArgs, ToolBarButtonClickEventHandler, ToolBarButtonStyle, ToolBarTextAlign |
ContextMenu | ContextMenuStrip | |
Menu | ToolStripDropDown, ToolstripDropDownMenu | MenuItemCollection |
MainMenu | MenuStrip | |
MenuItem | ToolstripMenuItem |
In the Ruler project, I need to migrate just the menu controls besides retargeting the runtime version.
<TargetFramework>netcoreapp3.1</TargetFramework>
Type Replacement
Replace ContextMenu with ContextMenuStrip, and replace MenuItem with ToolStripMenuItem
For example, the old code:
private readonly ContextMenu _menu = new ContextMenu();
private MenuItem _verticalMenuItem;
private MenuItem _toolTipMenuItem;
Is replaced with
private readonly ContextMenuStrip _menu = new ContextMenuStrip();
private ToolStripMenuItem _verticalMenuItem;
private ToolStripMenuItem _toolTipMenuItem;
API Differences
Shortcut Enum that used by MenuItem
isn't there anymore. Replace old code:
private MenuItem AddMenuItem(string text, Shortcut shortcut = Shortcut.None)
{
MenuItem mi = new MenuItem(text);
mi.Click += MenuHandler;
mi.Shortcut = shortcut;
_menu.MenuItems.Add(mi);
return mi;
}
with new code
private ToolStripMenuItem AddMenuItem(string text, Keys shortcut = Keys.None)
{
ToolStripMenuItem mi = new ToolStripMenuItem(text);
mi.Click += MenuHandler;
mi.ShortcutKeys = shortcut;
_menu.Items.Add(mi);
return mi;
}
In the old Menu control, the "-" string represented a separator, which is now replaced by ToolStripSeparator
. So, old code:
AddMenuItem("-");
Is now
_menu.Items.Add(new ToolStripSeparator());
Finally, the new menu looks like this:
The project is very simple, so everything works after a few code changes in .NET Core 3.1. As you can see, to replace the old controls isn't too much difficult. Hope you can also get your old project running on the latest platform soon!
Mike Gratsas
If you still intend to use deprecated controls from Windows Forms <a href="https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms">System.Windows.Forms</a> namespace you can add NuGet package reference to your project:
<code> dotnet add package SharpImg.System.Windows.Forms.Controls --version 1.0.5000 </code> and replace <a href="https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.contextmenu">Control.ContextMenu</a> property as described on the <a href="https://github.com/MikeGratsas/System.Windows.Forms.Controls">GitHub repository</a> to the corresponding extension methods:
<code> ContextMenu contextMenu = propertyGrid.GetContextMenu(); if (contextMenu == null) { contextMenu = new ContextMenu(); propertyGrid.SetContextMenu(contextMenu); } </code>