Skip to content

Commit 8ccc834

Browse files
committed
Support both process and surface isolated designers
From 16.4 Visual Studio enables surface isolated designer for XAML projects. Isolate common code and implement shims to make it work with both designers.
1 parent 3d907bf commit 8ccc834

34 files changed

+437
-398
lines changed

Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.Design/Controls/DataGrid.Metadata.cs

Lines changed: 73 additions & 70 deletions
Large diffs are not rendered by default.

Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.Design/MetadataRegistration.cs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@
44

55
using System;
66
using System.Reflection;
7-
87
using Microsoft.Toolkit.Uwp.Design.Common;
8+
using Microsoft.Toolkit.Uwp.UI.Controls.Design;
9+
10+
#if VS_DESIGNER_PROCESS_ISOLATION
911
using Microsoft.Windows.Design.Metadata;
12+
#endif
1013

11-
[assembly: ProvideMetadata(typeof(Microsoft.Toolkit.Uwp.UI.Controls.Design.MetadataRegistration))]
14+
[assembly: ProvideMetadata(typeof(MetadataRegistration))]
1215

1316
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design
1417
{
15-
public class MetadataRegistration : MetadataRegistrationBase, IProvideAttributeTable
18+
public class MetadataRegistration : MetadataRegistrationBase
1619
{
1720
public MetadataRegistration() : base()
1821
{
@@ -23,25 +26,12 @@ public MetadataRegistration() : base()
2326
// (or Default namespace in Project -> Properties -> Application tab)
2427
// must be the same as runtime assembly's main namespace (t.Namespace)
2528
// plus .Design.
26-
Type t = typeof(Microsoft.Toolkit.Uwp.UI.Controls.DataGrid);
29+
#if VS_DESIGNER_PROCESS_ISOLATION
30+
Type t = typeof(DataGrid);
2731
AssemblyName an = t.Assembly.GetName();
2832
AssemblyFullName = ", " + an.FullName;
2933
XmlResourceName = t.Namespace + ".Design." + an.Name + ".xml";
34+
#endif
3035
}
31-
32-
#region IProvideAttributeTable Members
33-
34-
/// <summary>
35-
/// Gets the AttributeTable for design time metadata.
36-
/// </summary>
37-
public AttributeTable AttributeTable
38-
{
39-
get
40-
{
41-
return BuildAttributeTable();
42-
}
43-
}
44-
45-
#endregion
4636
}
4737
}

Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.Design/Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.Design.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
</PropertyGroup>
3232
<PropertyGroup>
3333
<AssetTargetFallback>$(AssetTargetFallback);uap10.0.16299</AssetTargetFallback>
34+
<DefineConstants>$(DefineConstants);VS_DESIGNER_PROCESS_ISOLATION</DefineConstants>
3435
</PropertyGroup>
3536
<ItemGroup>
3637
<Reference Include="System.Runtime" />

Microsoft.Toolkit.Uwp.UI.Controls.Design/Common/MetadataRegistrationBase.cs

Lines changed: 63 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,20 @@
77
using System.ComponentModel;
88
using System.Diagnostics;
99
using System.Diagnostics.CodeAnalysis;
10-
using System.IO;
1110
using System.Linq;
1211
using System.Reflection;
1312
using System.Xml.Linq;
1413

14+
using Microsoft.Toolkit.Uwp.Design.Types;
15+
16+
#if VS_DESIGNER_PROCESS_ISOLATION
17+
using Microsoft.Windows.Design;
1518
using Microsoft.Windows.Design.Metadata;
19+
#endif
1620

1721
namespace Microsoft.Toolkit.Uwp.Design.Common
1822
{
19-
public class MetadataRegistrationBase
23+
public abstract class MetadataRegistrationBase : IProvideAttributeTable
2024
{
2125
private AttributeTable masterMetadataTable;
2226

@@ -28,15 +32,25 @@ internal MetadataRegistrationBase() { }
2832
/// <returns>Custom attribute table.</returns>
2933
protected virtual AttributeTable BuildAttributeTable()
3034
{
31-
AttributeTableBuilder builder = new AttributeTableBuilder();
35+
var builder = new AttributeTableBuilder();
3236

3337
AddDescriptions(builder);
3438
AddAttributes(builder);
3539
AddTables(builder, this);
40+
3641
masterMetadataTable = builder.CreateTable();
3742
return masterMetadataTable;
3843
}
3944

45+
#region IProvideAttributeTable Members
46+
47+
/// <summary>
48+
/// Gets the AttributeTable for design time metadata.
49+
/// </summary>
50+
public AttributeTable AttributeTable => BuildAttributeTable();
51+
52+
#endregion
53+
4054
/// <summary>
4155
/// Find all AttributeTableBuilder subclasses in the assembly
4256
/// and add their attributes to the assembly attribute table.
@@ -54,7 +68,7 @@ private void AddTables(AttributeTableBuilder builder, object parent)
5468
{
5569
try
5670
{
57-
AttributeTableBuilder atb = (AttributeTableBuilder)Activator.CreateInstance(t);
71+
var atb = (AttributeTableBuilder)Activator.CreateInstance(t);
5872
builder.AddTable(atb.CreateTable());
5973
}
6074
catch (Exception)
@@ -76,44 +90,44 @@ private void AddTables(AttributeTableBuilder builder, object parent)
7690
protected string AssemblyFullName { get; set; }
7791

7892
/// <summary>
79-
/// Create description attribute from run time assembly xml file.
93+
/// Create description attribute from run time assembly XML file.
8094
/// </summary>
8195
/// <param name="builder">The assembly attribute table builder.</param>
8296
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Design time dll should not fail.")]
8397
private void AddDescriptions(AttributeTableBuilder builder)
8498
{
8599
Debug.Assert(builder != null, "AddDescriptions is called with null parameter!");
86100

87-
if (string.IsNullOrEmpty(XmlResourceName) ||
88-
string.IsNullOrEmpty(AssemblyFullName))
89-
{
90-
return;
91-
}
92-
XDocument xdoc = null;
101+
if (string.IsNullOrEmpty(XmlResourceName) || string.IsNullOrEmpty(AssemblyFullName)) return;
102+
103+
XDocument xdoc;
93104
try
94105
{
95-
xdoc = XDocument.Load(new StreamReader(
96-
Assembly.GetExecutingAssembly().GetManifestResourceStream(XmlResourceName)));
106+
xdoc = XDocument.Load(Assembly.GetExecutingAssembly().GetManifestResourceStream(XmlResourceName));
97107
}
98-
catch { return; }
99-
if (xdoc == null)
108+
catch
100109
{
101110
return;
102111
}
103112

113+
if (xdoc == null) return;
114+
104115
foreach (XElement member in xdoc.Descendants("member"))
105116
{
106117
try
107118
{
108119
string name = (string)member.Attribute("name");
109-
if (name == null)
110-
continue;
120+
121+
if (name == null) continue;
122+
111123
bool isType = name.StartsWith("T:", StringComparison.OrdinalIgnoreCase);
112-
if (isType ||
113-
name.StartsWith("P:", StringComparison.OrdinalIgnoreCase))
124+
bool isProperty = name.StartsWith("P:", StringComparison.OrdinalIgnoreCase);
125+
126+
if (isType || isProperty)
114127
{
115128
int lastDot = name.Length;
116129
string typeName;
130+
117131
if (isType)
118132
{
119133
typeName = name.Substring(2); // skip leading "T:"
@@ -123,86 +137,74 @@ private void AddDescriptions(AttributeTableBuilder builder)
123137
lastDot = name.LastIndexOf('.');
124138
typeName = name.Substring(2, lastDot - 2);
125139
}
126-
typeName += AssemblyFullName;
127140

128-
Type t = Type.GetType(typeName);
129-
if (t != null && t.IsPublic && t.IsClass &&
130-
t.IsSubclassOf(Types.PlatformTypes.DependencyObjectType))
141+
var type = Type.GetType(typeName + ", " + AssemblyFullName);
142+
143+
if (type != null && type.IsPublic && type.IsClass && type.IsSubclassOf(PlatformTypes.DependencyObject))
131144
{
132145
string desc = ParseDescription(member);
133-
if (desc == null)
134-
continue;
135146

136-
desc = desc.Trim();
137-
desc = string.Join(" ", desc.Split(new char[] { ' ', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries));
147+
if (desc == null) continue;
148+
149+
desc = string.Join(" ", desc.Trim().Split(new char[] { ' ', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries));
150+
138151
if (isType)
139152
{
140-
bool isBrowsable = true;
141-
try
153+
if (IsBrowsable(type))
142154
{
143-
isBrowsable = IsBrowsable(t);
155+
builder.AddCustomAttributes(type, new DescriptionAttribute(desc));
144156
}
145-
catch { isBrowsable = false; }
146-
if (isBrowsable)
147-
builder.AddCallback(t, b => b.AddCustomAttributes(new DescriptionAttribute(desc)));
148157
else //Hide from intellisense
149158
{
150-
builder.AddCallback(t, b => b.AddCustomAttributes(
159+
builder.AddCustomAttributes(type,
151160
new BrowsableAttribute(false),
152-
new Microsoft.Windows.Design.ToolboxBrowsableAttribute(false),
153-
new ToolboxItemAttribute(false)));
161+
new ToolboxBrowsableAttribute(false),
162+
new ToolboxItemAttribute(false));
154163
}
155164
}
156165
else
157166
{
158-
string propName = name.Substring(lastDot + 1);
159-
PropertyInfo pi = t.GetProperty(propName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
167+
var propertyName = name.Substring(lastDot + 1);
168+
PropertyInfo pi = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
160169
if (pi != null)
161170
{
162-
bool isBrowsable = true;
163-
try
171+
if (IsBrowsable(type))
164172
{
165-
isBrowsable = IsBrowsable(pi);
173+
builder.AddCustomAttributes(type, propertyName, new DescriptionAttribute(desc));
166174
}
167-
catch { isBrowsable = false; }
168-
if (isBrowsable)
169-
builder.AddCallback(t, b => b.AddCustomAttributes(propName, new DescriptionAttribute(desc)));
170175
else //Hide from intellisense
171-
builder.AddCallback(t, b => b.AddCustomAttributes(new BrowsableAttribute(false)));
176+
{
177+
builder.AddCustomAttributes(type, new BrowsableAttribute(false));
178+
}
172179
}
173180
}
174181
}
175182
}
176183
}
177-
catch (Exception)
184+
catch
178185
{
179186
}
180187
}
181188
}
182-
private static bool IsBrowsable(Type t)
189+
190+
private static bool IsBrowsable(MemberInfo typeOrMember)
183191
{
184-
var attrs = t.GetCustomAttributes(Types.PlatformTypes.EditorBrowsableAttributeType, false);
185-
foreach (var attr in attrs)
192+
EditorBrowsableAttribute attribute;
193+
try
186194
{
187-
return Types.PlatformTypes.IsBrowsable(attr);
195+
attribute = typeOrMember.GetCustomAttribute<EditorBrowsableAttribute>(false);
188196
}
189-
return true;
190-
}
191-
192-
private static bool IsBrowsable(System.Reflection.PropertyInfo pi)
193-
{
194-
var attrs = pi.GetCustomAttributes(Types.PlatformTypes.EditorBrowsableAttributeType, false);
195-
foreach (var attr in attrs)
197+
catch
196198
{
197-
return Types.PlatformTypes.IsBrowsable(attr);
199+
return true; // If there is no [EditorBrowsable] attribute present, we'll show it by default.
198200
}
199-
return true;
201+
return attribute.State != EditorBrowsableState.Never;
200202
}
201203

202204
/// <summary>
203-
/// Create description string from xml doc summary tag.
205+
/// Create description string from XML doc summary tag.
204206
/// </summary>
205-
/// <param name="member">A single node of the xml doc.</param>
207+
/// <param name="member">A single node of the XML doc.</param>
206208
/// <returns>Description string.</returns>
207209
private static string ParseDescription(XElement member)
208210
{

Microsoft.Toolkit.Uwp.UI.Controls.Design/Common/PlatformTypes.cs

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,25 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6+
using Windows.UI.Xaml;
7+
using Windows.UI.Xaml.Controls;
68

9+
#if VS_DESIGNER_PROCESS_ISOLATION
710
using Microsoft.Windows.Design.Metadata;
8-
9-
using Windows.UI.Xaml;
11+
#endif
1012

1113
namespace Microsoft.Toolkit.Uwp.Design.Types
1214
{
1315
internal class PlatformTypes
1416
{
15-
public static readonly Type DependencyObjectType = typeof(DependencyObject);
16-
public static readonly Type UIElementType = typeof(UIElement);
17-
public static readonly Type FrameworkElementType = typeof(FrameworkElement);
18-
public static readonly Type EditorBrowsableAttributeType = typeof(System.ComponentModel.EditorBrowsableAttribute);
19-
20-
/// <summary>
21-
/// Used by MetadataRegistrationBase to get the browsable state
22-
/// </summary>
23-
/// <param name="editorBrowsableAttribute">This parameter must be of type 'System.ComponentModel.EditorBrowsableAttribute'</param>
24-
/// <returns></returns>
25-
public static bool IsBrowsable(object editorBrowsableAttribute)
26-
{
27-
if (editorBrowsableAttribute is System.ComponentModel.EditorBrowsableAttribute)
28-
return (editorBrowsableAttribute as System.ComponentModel.EditorBrowsableAttribute).State !=
29-
System.ComponentModel.EditorBrowsableState.Never;
30-
return true;
31-
}
32-
33-
public static class Control
34-
{
35-
public static readonly TypeIdentifier TypeId = new TypeIdentifier("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Control");
36-
public static readonly PropertyIdentifier BackgroundProperty = new PropertyIdentifier(TypeId, "Background");
37-
public static readonly PropertyIdentifier BorderBrushProperty = new PropertyIdentifier(TypeId, "BorderBrush");
38-
public static readonly PropertyIdentifier BorderThicknessProperty = new PropertyIdentifier(TypeId, "BorderThickness");
39-
}
17+
public static readonly Type DependencyObject = typeof(DependencyObject);
18+
public static readonly Type UIElement = typeof(UIElement);
19+
public static readonly Type FrameworkElement = typeof(FrameworkElement);
20+
public static readonly Type Control = typeof(Control);
21+
}
4022

23+
internal class XamlTypes
24+
{
4125
public static class FrameworkElement
4226
{
4327
public static readonly TypeIdentifier TypeId = new TypeIdentifier("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "FrameworkElement");
@@ -47,5 +31,13 @@ public static class FrameworkElement
4731
public static readonly PropertyIdentifier HeightProperty = new PropertyIdentifier(TypeId, "Height");
4832
public static readonly PropertyIdentifier WidthProperty = new PropertyIdentifier(TypeId, "Width");
4933
}
34+
35+
public static class Control
36+
{
37+
public static readonly TypeIdentifier TypeId = new TypeIdentifier("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Control");
38+
public static readonly PropertyIdentifier BackgroundProperty = new PropertyIdentifier(TypeId, "Background");
39+
public static readonly PropertyIdentifier BorderBrushProperty = new PropertyIdentifier(TypeId, "BorderBrush");
40+
public static readonly PropertyIdentifier BorderThicknessProperty = new PropertyIdentifier(TypeId, "BorderThickness");
41+
}
5042
}
5143
}

Microsoft.Toolkit.Uwp.UI.Controls.Design/Common/ToolboxCategoryPaths.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System;
56
using System.Diagnostics.CodeAnalysis;
67

78
[assembly: SuppressMessage("General", "SWC1001:XmlDocumentationCommentShouldBeSpelledCorrectly", MessageId = "Theming", Justification = "Correct spelling")]
89

9-
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design.Common
10+
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design
1011
{
1112
/// <summary>
1213
/// Names for ToolboxCategoryAttribute.

0 commit comments

Comments
 (0)