Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions aspnetcore/blazor/hybrid/tutorials/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ uid: blazor/hybrid/tutorials/index

* <xref:blazor/hybrid/tutorials/maui>

* <xref:blazor/hybrid/tutorials/windows-forms>

For more information on Blazor hosting models, see <xref:blazor/hosting-models>.
256 changes: 256 additions & 0 deletions aspnetcore/blazor/hybrid/tutorials/windows-forms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
---
title: Build a Windows Forms Blazor app
author: guardrex
description: Build a Windows Forms Blazor app step-by-step.
monikerRange: '>= aspnetcore-6.0'
ms.author: riande
ms.custom: mvc
ms.date: 02/15/2022
no-loc: [Home, Privacy, Kestrel, appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR]
uid: blazor/hybrid/tutorials/windows-forms
---
# Build a Windows Forms Blazor app

This tutorial shows you how to build and run a Windows Forms Blazor app. You learn how to:

> [!div class="checklist"]
> * Create a Windows Forms Blazor app project
> * Run the app on Windows

## Prerequisites

* [Supported platforms (Windows Forms documentation)](/dotnet/desktop/winforms/overview/)
* [Visual Studio 2022 Preview](https://visualstudio.microsoft.com/vs/preview/) with the **.NET desktop development** workload

## Visual Studio workload

If the **.NET desktop development** workload isn't installed, use the Visual Studio installer to install the workload:

:::image type="content" source="windows-forms/_static/install-workload.png" alt-text="Visual Studio installer .NET desktop development workload selection.":::

## Create a Windows Forms Blazor project

Start Visual Studio 2022 Preview. Select **Create a new project**.

In the **Create a new project** dialog, select the C# project template **Windows Forms App** and select the **Next** button:

:::image type="content" source="windows-forms/_static/create-project.png" alt-text="Create a new project in Visual Studio.":::

In the **Configure your new project** dialog, set the **Project name** to **`WinFormsBlazor`**, choose a suitable location for the project, and select the **Next** button. Using `WinFormsBlazor` as the project name matches the donor Blazor project names created in the preceding section, which aligns the namespaces of the three projects.

:::image type="content" source="windows-forms/_static/configure-project.png" alt-text="Configure the project.":::

In the **Additional information** dialog, select the framework version, which must be .NET 6.0 or later. Select the **Create** button.

Use [NuGet Package Manager](/nuget/consume-packages/install-use-packages-visual-studio) to install the [`Microsoft.AspNetCore.Components.WebView.WindowsForms`](https://nuget.org/packages/Microsoft.AspNetCore.Components.WebView.WindowsForms) preview NuGet package.

In **Solution Explorer**, right-click the project's name, `WinFormsBlazor` and select **Edit Project File** to open the project file (`WinFormsBlazor.csproj`).

At the top of the project file, change the SDK to `Microsoft.NET.Sdk.Razor`:

```xml
<Project Sdk="Microsoft.NET.Sdk.Razor">
```

Add the following [MSBuild `Content` item](/visualstudio/msbuild/common-msbuild-project-items#content) to the project file, which copies the contents of the `wwwroot` folder to the output directory without compiling the assets in the folder:

```xml
<ItemGroup>
<Content Update="wwwroot\**" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
```

Save the changes to the project file (`WinFormsBlazor.csproj`).

Add an `_Imports.razor` file to the root of the project with an [`@using`](xref:mvc/views/razor#using) directive for <xref:Microsoft.AspNetCore.Components.Web?displayProperty=fullName>.

`_Imports.razor`:

```razor
@using Microsoft.AspNetCore.Components.Web
```

Add a `wwwroot` folder to the project.

Add an `index.html` file to the `wwwroot` folder with the following markup.

`wwwroot\index.html`:

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>WinFormsBlazor</title>
<base href="/" />
<link href="css/app.css" rel="stylesheet" />
<link href="WinFormsBlazor.styles.css" rel="stylesheet" />
</head>

<body>

<div id="app">Loading...</div>

<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>

<script src="_framework/blazor.webview.js"></script>

</body>

</html>
```

Inside the `wwwroot` folder, create a `css` folder to hold stylesheets.

Add an `app.css` stylesheet to the `wwwroot/css` folder with the following content.

`wwwroot/css/app.css`:

```css
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050;
}

.invalid {
outline: 1px solid red;
}

.validation-message {
color: red;
}

#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}

#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
```

Add the following `Counter` component to the root of the project, which is the default `Counter` component found in Blazor project templates.

`Counter.razor`:

```razor
<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount = 0;

private void IncrementCount()
{
currentCount++;
}
}
```

In **Solution Explorer**, double-click on the `Form1.cs` file to open the designer:

:::image type="content" source="windows-forms/_static/solution-explorer-1.png" alt-text="The Form1.cs file in Solution Explorer.":::

Open the **Toolbox** by either selecting the **Toolbox** button along the left edge of the Visual Studio window or selecting the **View** > **Toolbox** menu item.

Locate the `BlazorWebView` control under `Microsoft.AspNetCore.Components.WebView.WindowsForms`:

:::image type="content" source="windows-forms/_static/toolbox.png" alt-text="BlazorWebView in the Toolbox.":::

Drag `BlazorWebView` from the **Toolbox** into the `Form1` designer:

:::image type="content" source="windows-forms/_static/form1.png" alt-text="BlazorWebView in the Form1 designer.":::

In `Form1`, select `BlazorWebView` with a single click.

In `BlazorWebView`'s **Properties**, change its **Dock** value to **Fill**:

:::image type="content" source="windows-forms/_static/properties.png" alt-text="BlazorWebView properties with Dock set to Fill.":::

In the `Form1` designer, right-click `Form1` and select **View Code**.

Add namespaces for `Microsoft.AspNetCore.Components.WebView.WindowsForms` and <xref:Microsoft.Extensions.DependencyInjection?displayProperty=fullName> to the top of the `Form1.cs` file:

```csharp
using Microsoft.AspNetCore.Components.WebView.WindowsForms;
using Microsoft.Extensions.DependencyInjection;
```

Inside the `Form1` constructor, below the `InitializeComponent()` method call, add the following code:

```csharp
var services = new ServiceCollection();
services.AddBlazorWebView();
blazorWebView1.HostPage = "wwwroot\\index.html";
blazorWebView1.Services = services.BuildServiceProvider();
blazorWebView1.RootComponents.Add<Counter>("#app");
```

The final, complete C# code of `Form1.cs`:

```csharp
using Microsoft.AspNetCore.Components.WebView.WindowsForms;
using Microsoft.Extensions.DependencyInjection;

namespace WinFormsBlazor
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();

var services = new ServiceCollection();
services.AddBlazorWebView();
blazorWebView1.HostPage = "wwwroot\\index.html";
blazorWebView1.Services = services.BuildServiceProvider();
blazorWebView1.RootComponents.Add<Counter>("#app");
}
}
}
```

## Run the app

Select the start button in the Visual Studio toolbar:

:::image type="content" source="windows-forms/_static/start-button.png" alt-text="Start button of the Visual Studio toolbar.":::

The app running on Windows:

:::image type="content" source="windows-forms/_static/running-app.png" alt-text="The app running on Windows.":::

## Next steps

In this tutorial, you learned how to:

> [!div class="checklist"]
> * Create a Windows Forms Blazor app project
> * Run the app on Windows

Learn more about Blazor Hybrid apps:

> [!div class="nextstepaction"]
> <xref:blazor/hybrid/index>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions aspnetcore/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@ items:
uid: blazor/hybrid/tutorials/index
- name: .NET MAUI
uid: blazor/hybrid/tutorials/maui
- name: Windows Forms
uid: blazor/hybrid/tutorials/windows-forms
- name: Project structure
uid: blazor/project-structure
- name: Fundamentals
Expand Down