Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a basic HOW TO on adding a new property page #7140

Merged
merged 6 commits into from
Apr 23, 2021
Merged
Show file tree
Hide file tree
Changes from 2 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
6 changes: 6 additions & 0 deletions docs/repo/property-pages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ This documentation details the updated Project Properties UI and associated back
4. Extensibility. We need to support 3rd parties (both internal and external) adding both entirely new pages _and_ customizing the pages we provide.
5. Support new functionality. We want to enable scenarios such as searching for properties, editing the MSBuild expressions that underpin many properties, and collecting the most commonly used properties in one area.

## How-To Guides

These guides describe how to get specific scenarios up and running, step by step.

- [HOW TO: Add a new property page](how-to-add-a-new-property-page.md)

tmeschter marked this conversation as resolved.
Show resolved Hide resolved
## Architecture

The Property Pages can be broken down into two high-level layers, the UI via through which the user interacts, and the back-end through which the UI communicates with the underlying project system to retrieve and update data. This separation allows the feature to work in Codespaces, where the project system is running on the server and the client contains only UI code.
Expand Down
88 changes: 88 additions & 0 deletions docs/repo/property-pages/how-to-add-a-new-property-page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# HOW TO: Add a New Property Page

Property pages are defined by XAML files describing an instance of the [Rule](https://docs.microsoft.com/en-us/dotnet/api/microsoft.build.framework.xamltypes.rule) class. Visual Studio uses these XAML files to dynamically build the UI and bind the controls to properties in your project. This HOW TO describes two options for defining and distributing these XAML files. At the end your property page will look something like this:

![New Property Page](new-property-page.png)

## Option 1: XAML file on disk

In this option, the XAML resides in a standalone .xaml file on disk and is included in the end user's project as a specific kind of MSBuild item, `PropertyPageSchema`. Visual Studio reads these items from the project to determine which property pages to show.

This may be an attractive option if you already have a NuGet package or Visual Studio extension that injects MSBuild .props and .targets files into the end user's project, or if you want to use MSBuild `Condition`s to control when the property page is available to a project.

### Step 1: Define the XAML file

Add a new XAML file named "MyPropertyPage.xaml" to your project. Depending on how the file is created you may end up with a `<Page>` item in your project but this is not what we want as we're not using the file to describe a piece of WPF UI.

Update your project to replace the `<Page>` item with one of the following:

- SDK-style projects:
``` xml
<None Update="MyPropertyPage.xaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Comment on lines +25 to +27
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For SDK-style, this style is preferred:

Suggested change
<None Update="MyPropertyPage.xaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="MyPropertyPage.xaml" CopyToOutputDirectory="PreserveNewest" />

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's better supported in SDK-style projects, but it's hard to call it preferred. If you update the property of a file through the Properties window (e.g. set "Copy to Output Directory" to "Copy if newer") we won't use the attribute style, even for SDK-style projects.

The only place it's really common right now is PackageReference.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, a few years back, I migrated a bunch of projects from csproj-style to SDK-style. And, at that time, I found documentation on the format with a decent migration guide. Right now, I just spent some time searching, and literally everything I found from the past is no longer there. No idea where it went, but the internet has lost information as it does over time. However, I can find remnants of why I said this is 'preferred':

I can find answers, posts, questions, issues, etc. showing it being used as an attribute versus a node. But, I honestly cannot find the source of behind it. I would not take the actions of VS to be an 'absolute' on the format. But, I do know there had been information on what should be used as attributes versus nodes. I just can't find it anymore. 😭

```
- Non-SDK-style projects:
``` xml
<None Include="MyPropertyPage.xaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
```

Now VS won't do anything with this file but copy it to the output directory when you build.

### Step 2 (optional): Add the Microsoft.Build.Framework package

Use the NuGet Package Manager to add the Microsoft.Build.Framework package to your project. This is an optional step, but it will allow the XAML editor to find the [Rule](https://docs.microsoft.com/en-us/dotnet/api/microsoft.build.framework.xamltypes.rule) type (and related types) and provide code completion, tool tips, Go to Definition, and other features while you type.

### Step 3: Describe the property page

Replace the contents of MyPropertyPage.xaml with the following:

```xml
<?xml version="1.0" encoding="utf-8" ?>
<Rule Name="MyPropertyPage"
Description="A description of my project properties page."
DisplayName="My Properties"
PageTemplate="generic"
Order="500"
xmlns="http://schemas.microsoft.com/build/2009/properties">

<Rule.DataSource>
<DataSource Persistence="ProjectFile"
SourceOfDefaultValue="AfterContext"
HasConfigurationCondition="False" />
</Rule.DataSource>

<StringProperty Name="MyProperty"
DisplayName="My property"
Description="A property that writes to the project file." />

</Rule>
```

The format of the file is described in detail in [Property Specification](property-specification.md), but the most important points are:
- The `Name` must be unique.
- The `PageTemplate` attribute must have the value `"generic"`.

You should now be able to build and see the MyPropertyPage.xaml copied as-is to the output directory.

### Step 4: Define the `PropertyPageSchema` item
tmeschter marked this conversation as resolved.
Show resolved Hide resolved

Next you need to update your .props or .targets files to properly reference the property page so Visual Studio can find it. Note that the creation and distribution of the .props and .targets files (as well as the distribution of MyPropertyPage.xaml itself) is beyond the scope of this document.

Add the following item to your .targets file:
tmeschter marked this conversation as resolved.
Show resolved Hide resolved

``` xml
<PropertyPageSchema Include="path\to\MyPropertyPage.xaml">
<Context>Project</Context>
</PropertyPageSchema>
```

And you're done. Projects that import the .targets file will now show this page when editing the project properties.

## Option 2: Embedded XAML file

In this option the XAML file is embedded in an assembly as a resource and discovered by means of a MEF export. Compared to Option 1 this requires more initial setup but does not require you to distribute an additional file. This may be an attractive option if you are already exporting MEF components for use in Visual Studio.

_Steps to be determined._
Binary file added docs/repo/property-pages/new-property-page.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.