diff --git a/dotnet-desktop-guide/TOC.yml b/dotnet-desktop-guide/TOC.yml index 18bad91192..3b9a23733e 100644 --- a/dotnet-desktop-guide/TOC.yml +++ b/dotnet-desktop-guide/TOC.yml @@ -9,6 +9,9 @@ items: - name: Windows Presentation Foundation expanded: true items: + - name: ".NET 5 (and .NET Core 3.1)" + href: net/wpf/index.yml?view=netdesktop-5.0&preserve-view=true - name: .NET Framework href: framework/wpf/index.md?view=netframeworkdesktop-4.8&preserve-view=true - + - name: XAML language reference + href: xaml-services/?view=&preserve-view=true diff --git a/dotnet-desktop-guide/docfx.json b/dotnet-desktop-guide/docfx.json index e801a39eb7..125b4899a1 100644 --- a/dotnet-desktop-guide/docfx.json +++ b/dotnet-desktop-guide/docfx.json @@ -135,23 +135,32 @@ "ms.author": "adegeo" }, "fileMetadata": { + "breadcrumb_path": { + "xaml-services/**/**.md": "/dotnet/desktop/xaml-services/breadcrumb/toc.json" + }, "titleSuffix": { "framework/winforms/**/**.md": "Windows Forms .NET Framework", "net/winforms/**/**.md": "Windows Forms .NET", "framework/wpf/**/**.md": "WPF .NET Framework", - "net/wpf/**/**.md": "WPF .NET" + "net/wpf/**/**.md": "WPF .NET", + "xaml-services/**/*.md": "XAML" }, "ms.technology": { "framework/winforms/**/**.md": "dotnet-winforms", "framework/wpf/**/**.md": "dotnet-wpf", "net/winforms/**/**.md": "dotnet-winforms", - "net/wpf/**/**.md": "dotnet-wpf" + "net/wpf/**/**.md": "dotnet-wpf", + "xaml-services/**/*.md": "dotnet-wpf" }, "ms.prod": { "framework/winforms/**/**.md": "dotnet-framework", "framework/wpf/**/**.md": "dotnet-framework", "net/winforms/**/**.md": "dotnet-desktop", - "net/wpf/**/**.md": "dotnet-desktop" + "net/wpf/**/**.md": "dotnet-desktop", + "xaml-services/**/*.md": "dotnet-desktop" + }, + "ms.topic": { + "xaml-services/**/*.md": "reference" } }, "template": [], diff --git a/dotnet-desktop-guide/framework/breadcrumb/toc.yml b/dotnet-desktop-guide/framework/breadcrumb/toc.yml index 46329baeca..5673b945fa 100644 --- a/dotnet-desktop-guide/framework/breadcrumb/toc.yml +++ b/dotnet-desktop-guide/framework/breadcrumb/toc.yml @@ -1,15 +1,15 @@ items: - name: Docs - tocHref: /?view=&preserve-view=true - topicHref: /?view=&preserve-view=true + tocHref: / + topicHref: / items: - name: .NET - tocHref: /dotnet/?view=&preserve-view=true - topicHref: /dotnet/index?view=&preserve-view=true + tocHref: /dotnet/ + topicHref: /dotnet/index items: - name: Desktop Guide - tocHref: /dotnet/desktop?view=&preserve-view=true - topicHref: /dotnet/desktop/index?view=&preserve-view=true + tocHref: /dotnet/desktop + topicHref: /dotnet/desktop/index items: - name: .NET Framework items: diff --git a/dotnet-desktop-guide/net/breadcrumb/toc.yml b/dotnet-desktop-guide/net/breadcrumb/toc.yml index ce5dc076d8..4850d05174 100644 --- a/dotnet-desktop-guide/net/breadcrumb/toc.yml +++ b/dotnet-desktop-guide/net/breadcrumb/toc.yml @@ -1,18 +1,31 @@ items: - name: Docs - tocHref: /?view=&preserve-view=true - topicHref: /?view=&preserve-view=true + tocHref: / + topicHref: / items: - name: .NET - tocHref: /dotnet/?view=&preserve-view=true - topicHref: /dotnet/index?view=&preserve-view=true + tocHref: /dotnet/ + topicHref: /dotnet/index items: - name: Desktop Guide - tocHref: /dotnet/desktop?view=&preserve-view=true - topicHref: /dotnet/desktop/index?view=&preserve-view=true + tocHref: /dotnet/desktop + topicHref: /dotnet/desktop/index items: - name: ".NET 5 (and .NET Core 3.1)" items: - name: Windows Forms tocHref: /dotnet/desktop/winforms/ topicHref: /dotnet/desktop/winforms/index + - name: Windows Presentation Foundation + tocHref: /dotnet/desktop/wpf/ + topicHref: /dotnet/desktop/wpf/index + items: + - name: Get started + tocHref: /visualstudio/get-started/csharp/tutorial-wpf + topicHref: /dotnet/desktop/wpf/getting-started/index + - name: Migration + tocHref: /dotnet/desktop/wpf/migration + topicHref: /dotnet/desktop/wpf/migration/index + - name: Data binding + tocHref: /dotnet/desktop/wpf/data + topicHref: /dotnet/desktop/wpf/data/index diff --git a/dotnet-desktop-guide/net/includes/desktop-guide-preview-note.md b/dotnet-desktop-guide/net/includes/desktop-guide-preview-note.md index e787a90b92..88a03dcfff 100644 --- a/dotnet-desktop-guide/net/includes/desktop-guide-preview-note.md +++ b/dotnet-desktop-guide/net/includes/desktop-guide-preview-note.md @@ -1,3 +1,3 @@ > [!IMPORTANT] -> The Desktop Guide documentation for .NET 5 (and .NET Core) and later versions is under construction and hasn't been published yet. +> The Desktop Guide documentation for .NET 5 (and .NET Core) and is under construction. diff --git a/dotnet-desktop-guide/net/wpf/data/data-binding-overview.md b/dotnet-desktop-guide/net/wpf/data/data-binding-overview.md new file mode 100644 index 0000000000..5f2ca5b738 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/data-binding-overview.md @@ -0,0 +1,445 @@ +--- +title: Data binding overview +description: Learn about the different data sources you can add to your project in Windows Presentation Foundation for .NET Core. Data sources can be bound to XAML elements to create dynamic apps. +author: adegeo +ms.date: 09/19/2019 +ms.author: adegeo +dev_langs: + - "csharp" + - "vb" +--- + +# Data binding overview in WPF + +Data binding in Windows Presentation Foundation (WPF) provides a simple and consistent way for apps to present and interact with data. Elements can be bound to data from a variety of data sources in the form of .NET objects and XML. Any such as and any , such as and , have built-in functionality to enable flexible styling of single data items or collections of data items. Sort, filter, and group views can be generated on top of the data. + +The data binding functionality in WPF has several advantages over traditional models, including inherent support for data binding by a broad range of properties, flexible UI representation of data, and clean separation of business logic from UI. + +This article first discusses concepts fundamental to WPF data binding and then covers the usage of the class and other features of data binding. + +[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)] + +## What is data binding? + +Data binding is the process that establishes a connection between the app UI and the data it displays. If the binding has the correct settings and the data provides the proper notifications, when the data changes its value, the elements that are bound to the data reflect changes automatically. Data binding can also mean that if an outer representation of the data in an element changes, then the underlying data can be automatically updated to reflect the change. For example, if the user edits the value in a `TextBox` element, the underlying data value is automatically updated to reflect that change. + +A typical use of data binding is to place server or local configuration data into forms or other UI controls. In WPF, this concept is expanded to include binding a broad range of properties to a variety of data sources. In WPF, dependency properties of elements can be bound to .NET objects (including ADO.NET objects or objects associated with Web Services and Web properties) and XML data. + +For an example of data binding, take a look at the following app UI from the [Data Binding Demo][data-binding-demo], which displays a list of auction items. + +![Data binding sample screenshot](./media/data-binding-overview/demo.png "DataBinding_DataBindingDemo") + +The app demonstrates the following features of data binding: + +- The content of the ListBox is bound to a collection of *AuctionItem* objects. An *AuctionItem* object has properties such as *Description*, *StartPrice*, *StartDate*, *Category*, *SpecialFeatures*, and so on. + +- The data (*AuctionItem* objects) displayed in the `ListBox` is templated so that the description and the current price are shown for each item. The template is created by using a . In addition, the appearance of each item depends on the *SpecialFeatures* value of the *AuctionItem* being displayed. If the *SpecialFeatures* value of the *AuctionItem* is *Color*, the item has a blue border. If the value is *Highlight*, the item has an orange border and a star. The [Data Templating](#data-templating) section provides information about data templating. + +- The user can group, filter, or sort the data using the `CheckBoxes` provided. In the image above, the **Group by category** and **Sort by category and date** `CheckBoxes` are selected. You may have noticed that the data is grouped based on the category of the product, and the category name is in alphabetical order. It is difficult to notice from the image but the items are also sorted by the start date within each category. Sorting is done using a *collection view*. The [Binding to collections](#binding-to-collections) section discusses collection views. + +- When the user selects an item, the displays the details of the selected item. This experience is called the *Master-detail scenario*. The [Master-detail scenario](#master-detail-binding-scenario) section provides information about this type of binding. + +- The type of the *StartDate* property is , which returns a date that includes the time to the millisecond. In this app, a custom converter has been used so that a shorter date string is displayed. The [Data conversion](#data-conversion) section provides information about converters. + +When the user selects the *Add Product* button, the following form comes up. + +![Add Product Listing page](./media/data-binding-overview/demo-addproductlisting.png "DataBinding_Demo_AddProductListing") + +The user can edit the fields in the form, preview the product listing using the short or detailed preview panes, and select `Submit` to add the new product listing. Any existing grouping, filtering and sorting settings will apply to the new entry. In this particular case, the item entered in the above image will be displayed as the second item within the *Computer* category. + +Not shown in this image is the validation logic provided in the *Start Date* . If the user enters an invalid date (invalid formatting or a past date), the user will be notified with a and a red exclamation point next to the . The [Data Validation](#data-validation) section discusses how to create validation logic. + +Before going into the different features of data binding outlined above, we will first discuss the fundamental concepts that are critical to understanding WPF data binding. + +## Basic data binding concepts + +Regardless of what element you are binding and the nature of your data source, each binding always follows the model illustrated by the following figure. + +![Diagram that shows the basic data binding model.](./media/data-binding-overview/basic-data-binding-diagram.png) + +As the figure shows, data binding is essentially the bridge between your binding target and your binding source. The figure demonstrates the following fundamental WPF data binding concepts: + +- Typically, each binding has four components: + + - A binding target object. + - A target property. + - A binding source. + - A path to the value in the binding source to use. + + > For example, if you want to bind the content of a `TextBox` to the `Employee.Name` property, your target object is the `TextBox`, the target property is the property, the value to use is *Name*, and the source object is the *Employee* object. + +- The target property must be a dependency property. Most properties are dependency properties, and most dependency properties, except read-only ones, support data binding by default. (Only types derived from can define dependency properties; and all types derive from `DependencyObject`.) + +- Although not shown in the figure, it should be noted that the binding source object is not restricted to being a custom .NET object. WPF data binding supports data in the form of .NET objects and XML. To provide some examples, your binding source may be a , any list object, an ADO.NET or Web Services object, or an XmlNode that contains your XML data. For more information, see [Binding sources overview](../../../framework/wpf/data/binding-sources-overview.md). + +It is important to remember that when you are establishing a binding, you are binding a binding target *to* a binding source. For example, if you are displaying some underlying XML data in a using data binding, you are binding your `ListBox` to the XML data. + +To establish a binding, you use the object. The rest of this article discusses many of the concepts associated with and some of the properties and usage of the `Binding` object. + +### Direction of the data flow + +As indicated by the arrow in the previous figure, the data flow of a binding can go from the binding target to the binding source (for example, the source value changes when a user edits the value of a `TextBox`) and/or from the binding source to the binding target (for example, your `TextBox` content is updated with changes in the binding source) if the binding source provides the proper notifications. + +You may want your app to enable users to change the data and propagate it back to the source object. Or you may not want to enable users to update the source data. You can control the flow of data by setting the . + +This figure illustrates the different types of data flow: + +![Data binding data flow](./media/data-binding-overview/databinding-dataflow.png "DataBinding_DataFlow") + +- binding causes changes to the source property to automatically update the target property, but changes to the target property are not propagated back to the source property. This type of binding is appropriate if the control being bound is implicitly read-only. For instance, you may bind to a source such as a stock ticker, or perhaps your target property has no control interface provided for making changes, such as a data-bound background color of a table. If there is no need to monitor the changes of the target property, using the binding mode avoids the overhead of the binding mode. + +- binding causes changes to either the source property or the target property to automatically update the other. This type of binding is appropriate for editable forms or other fully interactive UI scenarios. Most properties default to binding, but some dependency properties (typically properties of user-editable controls such as the and [CheckBox.IsChecked](xref:System.Windows.Controls.Primitives.ToggleButton.IsChecked) default to binding. A programmatic way to determine whether a dependency property binds one-way or two-way by default is to get the property metadata with and then check the Boolean value of the property. + +- is the reverse of binding; it updates the source property when the target property changes. One example scenario is if you only need to reevaluate the source value from the UI. + +- Not illustrated in the figure is binding, which causes the source property to initialize the target property but does not propagate subsequent changes. If the data context changes or the object in the data context changes, the change is *not* reflected in the target property. This type of binding is appropriate if either a snapshot of the current state is appropriate or the data is truly static. This type of binding is also useful if you want to initialize your target property with some value from a source property and the data context is not known in advance. This mode is essentially a simpler form of binding that provides better performance in cases where the source value does not change. + +To detect source changes (applicable to and bindings), the source must implement a suitable property change notification mechanism such as . See [How to: Implement property change notification](../../../framework/wpf/data/how-to-implement-property-change-notification.md) for an example of an implementation. + +The property provides more information about binding modes and an example of how to specify the direction of a binding. + +### What triggers source updates + +Bindings that are or listen for changes in the target property and propagate them back to the source, known as updating the source. For example, you may edit the text of a TextBox to change the underlying source value. + +However, is your source value updated while you are editing the text or after you finish editing the text and the control loses focus? The property determines what triggers the update of the source. The dots of the right arrows in the following figure illustrate the role of the property. + +![Diagram that shows the role of the UpdateSourceTrigger property.](./media/data-binding-overview/data-binding-updatesource-trigger.png) + +If the `UpdateSourceTrigger` value is , then the value pointed to by the right arrow of or the bindings is updated as soon as the target property changes. However, if the `UpdateSourceTrigger` value is , then that value only is updated with the new value when the target property loses focus. + +Similar to the property, different dependency properties have different default values. The default value for most dependency properties is , while the `TextBox.Text` property has a default value of . `PropertyChanged` means the source updates usually happen whenever the target property changes. Instant changes are fine for CheckBoxes and other simple controls. However, for text fields, updating after every keystroke can diminish performance and denies the user the usual opportunity to backspace and fix typing errors before committing to the new value. + +See the property page for information about how to find the default value of a dependency property. + +The following table provides an example scenario for each value using the as an example. + +| UpdateSourceTrigger value | When the source value is updated | Example scenario for TextBox | +| ------------------------- | ---------------------------------- | ---------------------------- | +| `LostFocus` (default for ) | When the TextBox control loses focus. | A TextBox that is associated with validation logic (see [Data Validation](#data-validation) below). | +| `PropertyChanged` | As you type into the . | TextBox controls in a chat room window. | +| `Explicit` | When the app calls . | TextBox controls in an editable form (updates the source values only when the user clicks the submit button). | + +For an example, see [How to: Control when the TextBox text updates the source](../../../framework/wpf/data/how-to-control-when-the-textbox-text-updates-the-source.md). + +## Creating a binding + +To restate some of the concepts discussed in the previous sections, you establish a binding using the object, and each binding usually has four components: a binding target, a target property, a binding source, and a path to the source value to use. This section discusses how to set up a binding. + +Consider the following example, in which the binding source object is a class named *MyData* that is defined in the *SDKSample* namespace. For demonstration purposes, *MyData* has a string property named *ColorName* whose value is set to "Red". Thus, this example generates a button with a red background. + +[!code-xaml[BindNonTextProperty](./snippets/data-binding-overview/csharp/AutoConvertPropertyToColor.xaml#BindAutoConvertColor)] + +For more information on the binding declaration syntax and examples of how to set up a binding in code, see [Binding Declarations Overview](../../../framework/wpf/data/binding-declarations-overview.md). + +If we apply this example to our basic diagram, the resulting figure looks like the following. This figure describes a binding because the Background property supports binding by default. + +![Diagram that shows the data binding Background property.](./media/data-binding-overview/data-binding-button-background-example.png) + +You may wonder why this binding works even though the *ColorName* property is of type string while the property is of type . This binding uses default type conversion, which is discussed in the [Data conversion](#data-conversion) section. + +### Specifying the binding source + +Notice that in the previous example, the binding source is specified by setting the [DockPanel.DataContext](xref:System.Windows.FrameworkElement.DataContext) property. The then inherits the value from the , which is its parent element. To reiterate, the binding source object is one of the four necessary components of a binding. Therefore, without the binding source object being specified, the binding would do nothing. + +There are several ways to specify the binding source object. Using the property on a parent element is useful when you are binding multiple properties to the same source. However, sometimes it may be more appropriate to specify the binding source on individual binding declarations. For the previous example, instead of using the property, you can specify the binding source by setting the property directly on the binding declaration of the button, as in the following example. + +[!code-xaml[BindNonTextPropertyCompactBinding](./snippets/data-binding-overview/csharp/AutoConvertPropertyToColor.xaml#BindAutoConvertColorCompactBinding)] + +Other than setting the property on an element directly, inheriting the value from an ancestor (such as the button in the first example), and explicitly specifying the binding source by setting the property on the binding (such as the button the last example), you can also use the property or the property to specify the binding source. The property is useful when you are binding to other elements in your app, such as when you are using a slider to adjust the width of a button. The property is useful when the binding is specified in a or a . For more information, see [How to: Specify the binding source](../../../framework/wpf/data/how-to-specify-the-binding-source.md). + +### Specifying the path to the value + +If your binding source is an object, you use the property to specify the value to use for your binding. If you are binding to XML data, you use the property to specify the value. In some cases, it may be applicable to use the property even when your data is XML. For example, if you want to access the Name property of a returned XmlNode (as a result of an XPath query), you should use the property in addition to the property. + +For more information, see the and properties. + +Although we have emphasized that the to the value to use is one of the four necessary components of a binding, in the scenarios that you want to bind to an entire object, the value to use would be the same as the binding source object. In those cases, it is applicable to not specify a . Consider the following example. + +[!code-xaml[EmptyBinding](./snippets/data-binding-overview/csharp/EmptyBinding.xaml#EmptyBinding)] + +The above example uses the empty binding syntax: {Binding}. In this case, the inherits the DataContext from a parent DockPanel element (not shown in this example). When the path is not specified, the default is to bind to the entire object. In other words, in this example, the path has been left out because we are binding the property to the entire object. (See the [Binding to collections](#binding-to-collections) section for an in-depth discussion.) + +Other than binding to a collection, this scenario is also useful when you want to bind to an entire object instead of just a single property of an object. For example, if your source object is of type , you may simply want to bind to the string itself. Another common scenario is when you want to bind an element to an object with several properties. + +You may need to apply custom logic so that the data is meaningful to your bound target property. The custom logic may be in the form of a custom converter if default type conversion does not exist. See [Data conversion](#data-conversion) for information about converters. + +### Binding and BindingExpression + +Before getting into other features and usages of data binding, it is useful to introduce the class. As you have seen in previous sections, the class is the high-level class for the declaration of a binding; it provides many properties that allow you to specify the characteristics of a binding. A related class, , is the underlying object that maintains the connection between the source and the target. A binding contains all the information that can be shared across several binding expressions. A is an instance expression that cannot be shared and contains all the instance information of the . + +Consider the following example, where `myDataObject` is an instance of the `MyData` class, `myBinding` is the source object, and `MyData` is a defined class that contains a string property named `ColorName`. This example binds the text content of `myText`, an instance of , to `ColorName`. + +[!code-csharp[CodeOnlyBinding](./snippets/data-binding-overview/csharp/ManualBinding.cs#CodeOnlyBinding)] +[!code-vb[CodeOnlyBinding](./snippets/data-binding-overview/vb/ManualBinding.vb#CodeOnlyBinding)] + +You can use the same *myBinding* object to create other bindings. For example, you can use the *myBinding* object to bind the text content of a check box to *ColorName*. In that scenario, there will be two instances of sharing the *myBinding* object. + +A object is returned by calling on a data-bound object. The following articles demonstrate some of the usages of the class: + +- [Get the binding object from a bound target property](../../../framework/wpf/data/how-to-get-the-binding-object-from-a-bound-target-property.md) + +- [Control When the TextBox text updates the source](../../../framework/wpf/data/how-to-control-when-the-textbox-text-updates-the-source.md) + +## Data conversion + +In the [Creating a binding](#creating-a-binding) section, the button is red because its property is bound to a string property with the value "Red". This string value works because a type converter is present on the type to convert the string value to a . + +Adding this information to the figure in the [Creating a Binding](#creating-a-binding) section looks like this. + +![Diagram that shows the data binding Default property.](./media/data-binding-overview/data-binding-button-default-conversion.png) + +However, what if instead of having a property of type string your binding source object has a *Color* property of type ? In that case, in order for the binding to work you would need to first turn the *Color* property value into something that the property accepts. You would need to create a custom converter by implementing the interface, as in the following example. + +[!code-csharp[CodeOnlyBinding](./snippets/data-binding-overview/csharp/ColorBrushConverter.cs#ColorBrushConverter)] +[!code-vb[CodeOnlyBinding](./snippets/data-binding-overview/vb/ColorBrushConverter.vb#ColorBrushConverter)] + +See for more information. + +Now the custom converter is used instead of default conversion, and our diagram looks like this. + +![Diagram that shows the data binding custom converter.](./media/data-binding-overview/data-binding-converter-color-example.png) + +To reiterate, default conversions may be available because of type converters that are present in the type being bound to. This behavior will depend on which type converters are available in the target. If in doubt, create your own converter. + +The following are some typical scenarios where it makes sense to implement a data converter: + +- Your data should be displayed differently, depending on culture. For instance, you might want to implement a currency converter or a calendar date/time converter based on the conventions used in a particular culture. + +- The data being used is not necessarily intended to change the text value of a property, but is instead intended to change some other value, such as the source for an image, or the color or style of the display text. Converters can be used in this instance by converting the binding of a property that might not seem to be appropriate, such as binding a text field to the Background property of a table cell. + +- More than one control or multiple properties of controls are bound to the same data. In this case, the primary binding might just display the text, whereas other bindings handle specific display issues but still use the same binding as source information. + +- A target property has a collection of bindings, which is termed . For , you use a custom to produce a final value from the values of the bindings. For example, color may be computed from red, blue, and green values, which can be values from the same or different binding source objects. See for examples and information. + +## Binding to collections + +A binding source object can be treated either as a single object whose properties contain data or as a data collection of polymorphic objects that are often grouped together (such as the result of a query to a database). So far we've only discussed binding to single objects. However, binding to a data collection is a common scenario. For example, a common scenario is to use an such as a , , or to display a data collection, such as in the app shown in the [What is data binding](#what-is-data-binding) section. + +Fortunately, our basic diagram still applies. If you are binding an to a collection, the diagram looks like this. + +![Diagram that shows the data binding ItemsControl object.](./media/data-binding-overview/data-binding-itemscontrol.png) + +As shown in this diagram, to bind an to a collection object, property is the property to use. You can think of `ItemsSource` as the content of the . The binding is because the `ItemsSource` property supports `OneWay` binding by default. + +### How to implement collections + +You can enumerate over any collection that implements the interface. However, to set up dynamic bindings so that insertions or deletions in the collection update the UI automatically, the collection must implement the interface. This interface exposes an event that should be raised whenever the underlying collection changes. + +WPF provides the class, which is a built-in implementation of a data collection that exposes the interface. To fully support transferring data values from source objects to targets, each object in your collection that supports bindable properties must also implement the interface. For more information, see [Binding sources overview](../../../framework/wpf/data/binding-sources-overview.md). + +Before implementing your own collection, consider using or one of the existing collection classes, such as , , and , among many others. If you have an advanced scenario and want to implement your own collection, consider using , which provides a non-generic collection of objects that can be individually accessed by the index, and thus provides the best performance. + +### Collection views + +Once your is bound to a data collection, you may want to sort, filter, or group the data. To do that, you use collection views, which are classes that implement the interface. + +#### What Are collection views? + +A collection view is a layer on top of a binding source collection that allows you to navigate and display the source collection based on sort, filter, and group queries, without having to change the underlying source collection itself. A collection view also maintains a pointer to the current item in the collection. If the source collection implements the interface, the changes raised by the event are propagated to the views. + +Because views do not change the underlying source collections, each source collection can have multiple views associated with it. For example, you may have a collection of *Task* objects. With the use of views, you can display that same data in different ways. For example, on the left side of your page you may want to show tasks sorted by priority, and on the right side, grouped by area. + +#### How to create a view + +One way to create and use a view is to instantiate the view object directly and then use it as the binding source. For example, consider the [Data binding demo][data-binding-demo] app shown in the [What is data binding](#what-is-data-binding) section. The app is implemented such that the binds to a view over the data collection instead of the data collection directly. The following example is extracted from the [Data binding demo][data-binding-demo] app. The class is the XAML proxy of a class that inherits from . In this particular example, the of the view is bound to the *AuctionItems* collection (of type ) of the current app object. + +[!code-xaml[CollectionView](./snippets/data-binding-overview/csharp/CollectionView.xaml#CollectionView)] + +The resource *listingDataView* then serves as the binding source for elements in the app, such as the . + +[!code-xaml[ListBoxCollectionView](./snippets/data-binding-overview/csharp/CollectionView.xaml#ListBoxCollectionView)] + +To create another view for the same collection, you can create another instance and give it a different `x:Key` name. + +The following table shows what view data types are created as the default collection view or by based on the source collection type. + +| Source collection type | Collection view type | Notes | +| ----------------------------------------- | -------------------- | ----- | +| | An internal type based on | Cannot group items. | +| | | Fastest. | +| | | | + +#### Using a default view + +Specifying a collection view as a binding source is one way to create and use a collection view. WPF also creates a default collection view for every collection used as a binding source. If you bind directly to a collection, WPF binds to its default view. This default view is shared by all bindings to the same collection, so a change made to a default view by one bound control or code (such as sorting or a change to the current item pointer, discussed later) is reflected in all other bindings to the same collection. + +To get the default view, you use the method. For an example, see [Get the default view of a data collection](../../../framework/wpf/data/how-to-get-the-default-view-of-a-data-collection.md). + +#### Collection views with ADO.NET DataTables + +To improve performance, collection views for ADO.NET or objects delegate sorting and filtering to the , which causes sorting and filtering to be shared across all collection views of the data source. To enable each collection view to sort and filter independently, initialize each collection view with its own object. + +#### Sorting + +As mentioned before, views can apply a sort order to a collection. As it exists in the underlying collection, your data may or may not have a relevant, inherent order. The view over the collection allows you to impose an order, or change the default order, based on comparison criteria that you supply. Because it is a client-based view of the data, a common scenario is that the user might want to sort columns of tabular data per the value that the column corresponds to. Using views, this user-driven sort can be applied, again without making any changes to the underlying collection or even having to requery for the collection content. For an example, see [Sort a GridView column when a header is clicked](../../../framework/wpf/controls/how-to-sort-a-gridview-column-when-a-header-is-clicked.md). + +The following example shows the sorting logic of the "Sort by category and date" of the app UI in the [What is data binding](#what-is-data-binding) section. + +[!code-csharp[AddSortChecked](./snippets/data-binding-overview/csharp/CollectionView.xaml.cs#AddSortChecked)] +[!code-vb[AddSortChecked](./snippets/data-binding-overview/vb/CollectionView.xaml.vb#AddSortChecked)] + +#### Filtering + +Views can also apply a filter to a collection, so that the view shows only a certain subset of the full collection. You might filter on a condition in the data. For instance, as is done by the app in the [What is data binding](#what-is-data-binding) section, the "Show only bargains" contains logic to filter out items that cost $25 or more. The following code is executed to set *ShowOnlyBargainsFilter* as the event handler when that is selected. + +[!code-csharp[ListingViewFilter](./snippets/data-binding-overview/csharp/CollectionView.xaml.cs#ListingViewFilter)] +[!code-vb[ListingViewFilter](./snippets/data-binding-overview/vb/CollectionView.xaml.vb#ListingViewFilter)] + +The *ShowOnlyBargainsFilter* event handler has the following implementation. + +[!code-csharp[FilterEvent](./snippets/data-binding-overview/csharp/CollectionView.xaml.cs#FilterEvent)] +[!code-vb[FilterEvent](./snippets/data-binding-overview/vb/CollectionView.xaml.vb#FilterEvent)] + +If you are using one of the classes directly instead of , you would use the property to specify a callback. For an example, see [Filter Data in a View](../../../framework/wpf/data/how-to-filter-data-in-a-view.md). + +#### Grouping + +Except for the internal class that views an collection, all collection views support *grouping*, which allows the user to partition the collection in the collection view into logical groups. The groups can be explicit, where the user supplies a list of groups, or implicit, where the groups are generated dynamically depending on the data. + +The following example shows the logic of the "Group by category" . + +[!code-csharp[ListingGroupCheck](./snippets/data-binding-overview/csharp/CollectionView.xaml.cs#ListingGroupCheck)] +[!code-vb[ListingGroupCheck](./snippets/data-binding-overview/vb/CollectionView.xaml.vb#ListingGroupCheck)] + +For another grouping example, see [Group Items in a ListView That Implements a GridView](../../../framework/wpf/controls/how-to-group-items-in-a-listview-that-implements-a-gridview.md). + +#### Current item pointers + +Views also support the notion of a current item. You can navigate through the objects in a collection view. As you navigate, you are moving an item pointer that allows you to retrieve the object that exists at that particular location in the collection. For an example, see [Navigate through the objects in a data CollectionView](../../../framework/wpf/data/how-to-navigate-through-the-objects-in-a-data-collectionview.md). + +Because WPF binds to a collection only by using a view (either a view you specify, or the collection's default view), all bindings to collections have a current item pointer. When binding to a view, the slash ("/") character in a `Path` value designates the current item of the view. In the following example, the data context is a collection view. The first line binds to the collection. The second line binds to the current item in the collection. The third line binds to the `Description` property of the current item in the collection. + +```xaml + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/AutoConvertPropertyToColor.xaml.cs b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/AutoConvertPropertyToColor.xaml.cs new file mode 100644 index 0000000000..a11de385f7 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/AutoConvertPropertyToColor.xaml.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace bindings +{ + /// + /// Interaction logic for DockPanelBindRedExample.xaml + /// + public partial class AutoConvertPropertyToColor : UserControl + { + public AutoConvertPropertyToColor() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/CollectionView.xaml b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/CollectionView.xaml new file mode 100644 index 0000000000..62355db605 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/CollectionView.xaml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Description: + + + + Current Price: + + + + + + + + + + + Color + + + + + + + + + + + + Highlight + + + + + + + + + + + + + + + + + + + + Add Sorting + Add Filtering + Add Grouping + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/CollectionView.xaml.cs b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/CollectionView.xaml.cs new file mode 100644 index 0000000000..047ac336c1 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/CollectionView.xaml.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace bindings +{ + /// + /// Interaction logic for CollectionView.xaml + /// + public partial class CollectionView : Window + { + public CollectionViewSource listingDataView; + + public CollectionView() + { + InitializeComponent(); + } + + private void Window_Loaded(object sender, RoutedEventArgs e) + { + listingDataView = (CollectionViewSource)Resources["listingDataView"]; + } + + // + private void AddFilteringCheckBox_Checked(object sender, RoutedEventArgs e) + { + if (((CheckBox)sender).IsChecked == true) + listingDataView.Filter += ListingDataView_Filter; + else + listingDataView.Filter -= ListingDataView_Filter; + } + // + + private void AddGroupingCheckBox_Checked(object sender, RoutedEventArgs e) + { + // + // This groups the items in the view by the property "Category" + var groupDescription = new PropertyGroupDescription(); + groupDescription.PropertyName = "Category"; + listingDataView.GroupDescriptions.Add(groupDescription); + // + } + + // + private void ListingDataView_Filter(object sender, FilterEventArgs e) + { + // Start with everything excluded + e.Accepted = false; + + // Only inlcude items with a price less than 25 + if (e.Item is AuctionItem product && product.CurrentPrice < 25) + e.Accepted = true; + } + // + + // + private void AddSortCheckBox_Checked(object sender, RoutedEventArgs e) + { + // Sort the items first by Category and then by StartDate + listingDataView.SortDescriptions.Add(new SortDescription("Category", ListSortDirection.Ascending)); + listingDataView.SortDescriptions.Add(new SortDescription("StartDate", ListSortDirection.Ascending)); + } + // + } +} diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/ColorBrushConverter.cs b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/ColorBrushConverter.cs new file mode 100644 index 0000000000..c19dfbd25d --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/ColorBrushConverter.cs @@ -0,0 +1,23 @@ +using System; +using System.Windows.Data; +using System.Windows.Media; + +namespace bindings +{ + // + [ValueConversion(typeof(Color), typeof(SolidColorBrush))] + public class ColorBrushConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + Color color = (Color)value; + return new SolidColorBrush(color); + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + return null; + } + } + // +} diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/DataValidation.xaml b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/DataValidation.xaml new file mode 100644 index 0000000000..265886ba81 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/DataValidation.xaml @@ -0,0 +1,79 @@ + + + + + + ! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/DataValidation.xaml.cs b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/DataValidation.xaml.cs new file mode 100644 index 0000000000..2cfed7ca1f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/DataValidation.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace bindings +{ + /// + /// Interaction logic for DataValidation.xaml + /// + public partial class DataValidation : Window + { + public DataValidation() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/DateConverter.cs b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/DateConverter.cs new file mode 100644 index 0000000000..4360d0a968 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/DateConverter.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; +using System.Globalization; +using System.Windows.Data; + +namespace bindings +{ + [ValueConversion(typeof(DateTime), typeof(string))] + public class DateConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + DateTime date = (DateTime)value; + return date.ToShortDateString(); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + string strValue = value.ToString(); + DateTime resultDateTime; + if (DateTime.TryParse(strValue, out resultDateTime)) + { + return resultDateTime; + } + return value; + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/EmptyBinding.xaml b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/EmptyBinding.xaml new file mode 100644 index 0000000000..0c40cdf764 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/EmptyBinding.xaml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/EmptyBinding.xaml.cs b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/EmptyBinding.xaml.cs new file mode 100644 index 0000000000..8369efa14c --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/EmptyBinding.xaml.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace bindings +{ + /// + /// Interaction logic for EmptyBinding.xaml + /// + public partial class EmptyBinding : UserControl + { + public EmptyBinding() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/FutureDateRule.cs b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/FutureDateRule.cs new file mode 100644 index 0000000000..bf55bd1c76 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/FutureDateRule.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Windows.Controls; + +namespace bindings +{ + // + public class FutureDateRule : ValidationRule + { + public override ValidationResult Validate(object value, CultureInfo cultureInfo) + { + // Test if date is valid + if (DateTime.TryParse(value.ToString(), out DateTime date)) + { + // Date is not in the future, fail + if (DateTime.Now > date) + return new ValidationResult(false, "Please enter a date in the future."); + } + else + { + // Date is not a valid date, fail + return new ValidationResult(false, "Value is not a valid date."); + } + + // Date is valid and in the future, pass + return ValidationResult.ValidResult; + } + } + // +} diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/MainWindow.xaml new file mode 100644 index 0000000000..978ffcdcb2 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/MainWindow.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/MainWindow.xaml.cs b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/MainWindow.xaml.cs new file mode 100644 index 0000000000..660283f372 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/MainWindow.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace bindings +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/ManualBinding.cs b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/ManualBinding.cs new file mode 100644 index 0000000000..ef9ab4956b --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/ManualBinding.cs @@ -0,0 +1,26 @@ +using System.Windows.Controls; +using System.Windows.Data; +using SDKSample; + +namespace bindings +{ + class ManualBinding + { + public TextBox myText; + + public void BindTextBox() + { + // + // Make a new source + var myDataObject = new MyData(); + var myBinding = new Binding("ColorName") + { + Source = myDataObject + }; + + // Bind the data source to the TextBox control's Text dependency property + myText.SetBinding(TextBlock.TextProperty, myBinding); + // + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/MyData.cs b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/MyData.cs new file mode 100644 index 0000000000..d1dd33f15b --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/MyData.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SDKSample +{ + class MyData + { + public string ColorName => "Red"; + } +} diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/SpecialFeatures.cs b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/SpecialFeatures.cs new file mode 100644 index 0000000000..2ade086fbe --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/SpecialFeatures.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace bindings +{ + public enum SpecialFeatures + { + None, + Color, + Highlight + } +} diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/bindings.csproj b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/bindings.csproj new file mode 100644 index 0000000000..248170e468 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/csharp/bindings.csproj @@ -0,0 +1,9 @@ + + + + WinExe + netcoreapp3.1 + true + + + \ No newline at end of file diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/Application.xaml new file mode 100644 index 0000000000..2db4e85fc7 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/Application.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/Application.xaml.vb new file mode 100644 index 0000000000..1b090eb16d --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/Application.xaml.vb @@ -0,0 +1,10 @@ +Imports System.Collections.ObjectModel + +Class Application + + ' Application-level events, such as Startup, Exit, and DispatcherUnhandledException + ' can be handled in this file. + + Public ReadOnly Property AuctionItems As ObservableCollection(Of AuctionItem) = New ObservableCollection(Of AuctionItem) + +End Class diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/AuctionItem.vb b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/AuctionItem.vb new file mode 100644 index 0000000000..549c7bc610 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/AuctionItem.vb @@ -0,0 +1,10 @@ +Imports System.ComponentModel + +Public Class AuctionItem + Implements INotifyPropertyChanged + + Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged + + Public CurrentPrice As Integer + +End Class diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/CollectionView.xaml b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/CollectionView.xaml new file mode 100644 index 0000000000..81e63a670c --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/CollectionView.xaml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + Add Sorting + Add Filtering + Add Grouping + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/CollectionView.xaml.vb b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/CollectionView.xaml.vb new file mode 100644 index 0000000000..84c05c060f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/CollectionView.xaml.vb @@ -0,0 +1,58 @@ +Imports System.ComponentModel + +Public Class CollectionView + + Public listingDataView As CollectionViewSource + + Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) + listingDataView = CType(Resources("listingDataView"), CollectionViewSource) + + End Sub + + ' + Private Sub AddFilteringCheckBox_Checked(sender As Object, e As RoutedEventArgs) + Dim checkBox = DirectCast(sender, CheckBox) + + If checkBox.IsChecked = True Then + AddHandler listingDataView.Filter, AddressOf ListingDataView_Filter + Else + RemoveHandler listingDataView.Filter, AddressOf ListingDataView_Filter + End If + End Sub + ' + + Private Sub AddGroupingCheckBox_Checked(sender As Object, e As RoutedEventArgs) + ' + ' This groups the items in the view by the property "Category" + Dim groupDescription = New PropertyGroupDescription() + groupDescription.PropertyName = "Category" + listingDataView.GroupDescriptions.Add(groupDescription) + ' + End Sub + + ' + Private Sub ListingDataView_Filter(sender As Object, e As FilterEventArgs) + + ' Start with everything excluded + e.Accepted = False + + Dim product As AuctionItem = TryCast(e.Item, AuctionItem) + + If product IsNot Nothing Then + + ' Only include products with prices lower than 25 + If product.CurrentPrice < 25 Then e.Accepted = True + + End If + + End Sub + ' + + ' + Private Sub AddSortCheckBox_Checked(sender As Object, e As RoutedEventArgs) + ' Sort the items first by Category And then by StartDate + listingDataView.SortDescriptions.Add(New SortDescription("Category", ListSortDirection.Ascending)) + listingDataView.SortDescriptions.Add(New SortDescription("StartDate", ListSortDirection.Ascending)) + End Sub + ' +End Class diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/ColorBrushConverter.vb b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/ColorBrushConverter.vb new file mode 100644 index 0000000000..0018d0efca --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/ColorBrushConverter.vb @@ -0,0 +1,14 @@ +' + +Public Class ColorBrushConverter + Implements IValueConverter + Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert + Dim color As Color = CType(value, Color) + Return New SolidColorBrush(color) + End Function + + Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack + Return Nothing + End Function +End Class +' diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/FutureDateRule.vb b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/FutureDateRule.vb new file mode 100644 index 0000000000..e30e10e20e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/FutureDateRule.vb @@ -0,0 +1,30 @@ +Imports System.Globalization + +' +Public Class FutureDateRule + Inherits ValidationRule + + Public Overrides Function Validate(value As Object, cultureInfo As CultureInfo) As ValidationResult + + Dim inputDate As Date + + ' Test if date is valid + If Date.TryParse(value.ToString, inputDate) Then + + ' Date is not in the future, fail + If Date.Now > inputDate Then + Return New ValidationResult(False, "Please enter a date in the future.") + End If + + Else + ' // Date Is Not a valid date, fail + Return New ValidationResult(False, "Value is not a valid date.") + End If + + ' Date is valid and in the future, pass + Return ValidationResult.ValidResult + + End Function + +End Class +' diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/MainWindow.xaml new file mode 100644 index 0000000000..065ad48a50 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/MainWindow.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/MainWindow.xaml.vb new file mode 100644 index 0000000000..922a5deddb --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/MainWindow.xaml.vb @@ -0,0 +1,3 @@ +Class MainWindow + +End Class diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/ManualBinding.vb b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/ManualBinding.vb new file mode 100644 index 0000000000..1646c04d8e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/ManualBinding.vb @@ -0,0 +1,19 @@ +Imports bindings.SDKSample + +Public Class ManualBinding + + Public myText As TextBox + + Public Sub BindTextBox() + ' + ' Make a New source + Dim myDataObject As New MyData + Dim myBinding As New Binding("ColorName") + myBinding.Source = myDataObject + + ' Bind the data source to the TextBox control's Text dependency property + myText.SetBinding(TextBlock.TextProperty, myBinding) + ' + End Sub + +End Class diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/MyData.vb b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/MyData.vb new file mode 100644 index 0000000000..02e86e53bb --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/MyData.vb @@ -0,0 +1,9 @@ +Namespace SDKSample + + Public Class MyData + + Public ReadOnly Property ColorName As String = "Red" + + End Class + +End Namespace diff --git a/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/bindings.vbproj b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/bindings.vbproj new file mode 100644 index 0000000000..6eab484593 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/data/snippets/data-binding-overview/vb/bindings.vbproj @@ -0,0 +1,22 @@ + + + + WinExe + netcoreapp3.1 + bindings + true + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/create-a-style-explicit-textblock.png b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/create-a-style-explicit-textblock.png new file mode 100644 index 0000000000..81d0145396 Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/create-a-style-explicit-textblock.png differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-eventtriggers.png b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-eventtriggers.png new file mode 100644 index 0000000000..e3c7d79d6e Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-eventtriggers.png differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-listboxbefore.png b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-listboxbefore.png new file mode 100644 index 0000000000..40b8e15e85 Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-listboxbefore.png differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-photosasimages.png b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-photosasimages.png new file mode 100644 index 0000000000..cbbbb2b9a6 Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-photosasimages.png differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-textblocks.png b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-textblocks.png new file mode 100644 index 0000000000..e03d4f86a0 Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-textblocks.png differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-textblocksbasestyle.png b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-textblocksbasestyle.png new file mode 100644 index 0000000000..1517b885b3 Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-textblocksbasestyle.png differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-textblocksbefore.png b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-textblocksbefore.png new file mode 100644 index 0000000000..b1707b963f Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-textblocksbefore.png differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-triggers.png b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-triggers.png new file mode 100644 index 0000000000..24cb704e6a Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/media/styles-and-templates-overview/stylingintro-triggers.png differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/App.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/App.cs new file mode 100644 index 0000000000..50bab6f682 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/App.cs @@ -0,0 +1,14 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Windows; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} \ No newline at end of file diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/App.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/App.xaml new file mode 100644 index 0000000000..a4bba90757 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/App.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/CSharpExample.csproj b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/CSharpExample.csproj new file mode 100644 index 0000000000..661e3a79d0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/CSharpExample.csproj @@ -0,0 +1,29 @@ + + + + WinExe + netcoreapp3.1 + IntroToStylingAndTemplating + true + IntroToStylingAndTemplating + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/MainWindow.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/MainWindow.cs new file mode 100644 index 0000000000..185500d374 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/MainWindow.cs @@ -0,0 +1,27 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Windows; +using System.Windows.Data; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + private PhotoList _photos; + + public MainWindow() + { + InitializeComponent(); + } + + private void WindowLoaded(object sender, RoutedEventArgs e) + { + _photos = (PhotoList) (Resources["MyPhotos"] as ObjectDataProvider).Data; + _photos.Path = "images"; + } + } +} \ No newline at end of file diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/MainWindow.xaml new file mode 100644 index 0000000000..b263d5a91b --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/MainWindow.xaml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + My Pictures + Check out my new pictures! + + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Photo.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Photo.cs new file mode 100644 index 0000000000..34bd270476 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Photo.cs @@ -0,0 +1,19 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace IntroToStylingAndTemplating +{ + // + public class Photo + { + public Photo(string path) + { + Source = path; + } + + public string Source { get; } + + public override string ToString() => Source; + } + // +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/PhotoList.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/PhotoList.cs new file mode 100644 index 0000000000..8c78cd7bb9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/PhotoList.cs @@ -0,0 +1,55 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.ObjectModel; +using System.IO; + +namespace IntroToStylingAndTemplating +{ + public class PhotoList : ObservableCollection + { + private DirectoryInfo _directory; + + public PhotoList() + { + } + + public PhotoList(string path) : this(new DirectoryInfo(path)) + { + } + + public PhotoList(DirectoryInfo directory) + { + _directory = directory; + Update(); + } + + public string Path + { + set + { + _directory = new DirectoryInfo(value); + Update(); + } + get { return _directory.FullName; } + } + + public DirectoryInfo Directory + { + set + { + _directory = value; + Update(); + } + get { return _directory; } + } + + private void Update() + { + foreach (var f in _directory.GetFiles("*.jpg")) + { + Add(new Photo(f.FullName)); + } + } + } +} \ No newline at end of file diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window1.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window1.xaml new file mode 100644 index 0000000000..4358f6639e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window1.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + My Pictures + Check out my new pictures! + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window1.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window1.xaml.cs new file mode 100644 index 0000000000..dbfa52e78e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window1.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window1.xaml + /// + public partial class Window1 : Window + { + public Window1() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window2.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window2.xaml new file mode 100644 index 0000000000..cf47444b5d --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window2.xaml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + My Pictures + Check out my new pictures! + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window2.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window2.xaml.cs new file mode 100644 index 0000000000..65023c6f1e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window2.xaml.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window2.xaml + /// + public partial class Window2 : Window + { + public Window2() + { + InitializeComponent(); + } + + private void Window_Loaded(object sender, RoutedEventArgs e) + { + // + textblock1.Style = (Style)Resources["TitleText"]; + // + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window3.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window3.xaml new file mode 100644 index 0000000000..5de67078c0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window3.xaml @@ -0,0 +1,20 @@ + + + + + + My Pictures + Check out my new pictures! + + + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window3.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window3.xaml.cs new file mode 100644 index 0000000000..960a9049ea --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window3.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window3.xaml + /// + public partial class Window3 : Window + { + public Window3() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window4.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window4.xaml new file mode 100644 index 0000000000..541d94a084 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window4.xaml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + My Pictures + Check out my new pictures! + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window4.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window4.xaml.cs new file mode 100644 index 0000000000..e6a7dffdca --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window4.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window4.xaml + /// + public partial class Window4 : Window + { + public Window4() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window5.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window5.xaml new file mode 100644 index 0000000000..c2ea90cd24 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window5.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + My Pictures + Check out my new pictures! + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window5.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window5.xaml.cs new file mode 100644 index 0000000000..95cf6d8612 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window5.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window5.xaml + /// + public partial class Window5 : Window + { + public Window5() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window6.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window6.xaml new file mode 100644 index 0000000000..2851b1e516 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window6.xaml @@ -0,0 +1,53 @@ + + + + + + + + My Pictures + Check out my new pictures! + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window6.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window6.xaml.cs new file mode 100644 index 0000000000..8db370c23e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/Window6.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window6.xaml + /// + public partial class Window6 : Window + { + public Window6() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/WindowExplicitStyle.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/WindowExplicitStyle.xaml new file mode 100644 index 0000000000..254fe997fa --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/WindowExplicitStyle.xaml @@ -0,0 +1,25 @@ + + + + + + + + + My Pictures + Check out my new pictures! + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/WindowExplicitStyle.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/WindowExplicitStyle.xaml.cs new file mode 100644 index 0000000000..f28be5f957 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/WindowExplicitStyle.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for ExplicitStyle.xaml + /// + public partial class ExplicitStyle : Window + { + public ExplicitStyle() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/WindowSingleResource.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/WindowSingleResource.xaml new file mode 100644 index 0000000000..3c2510b1b0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/WindowSingleResource.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/WindowSingleResource.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/WindowSingleResource.xaml.cs new file mode 100644 index 0000000000..66e60e8052 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/WindowSingleResource.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for WindowSingleResource.xaml + /// + public partial class WindowSingleResource : Window + { + public WindowSingleResource() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/flower1.jpg b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/flower1.jpg new file mode 100644 index 0000000000..6eb28def82 Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/flower1.jpg differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/flower2.jpg b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/flower2.jpg new file mode 100644 index 0000000000..f3004f29ad Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/flower2.jpg differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/leaf1.jpg b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/leaf1.jpg new file mode 100644 index 0000000000..1ab47b0140 Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/leaf1.jpg differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/leaf2.jpg b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/leaf2.jpg new file mode 100644 index 0000000000..8dae26ff5c Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/leaf2.jpg differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/winter1.jpg b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/winter1.jpg new file mode 100644 index 0000000000..8baa8b4961 Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/csharp/images/winter1.jpg differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/Application.xaml new file mode 100644 index 0000000000..7f4e220d66 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/Application.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/Application.xaml.vb new file mode 100644 index 0000000000..084cbe917e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/Application.xaml.vb @@ -0,0 +1,6 @@ +Class Application + + ' Application-level events, such as Startup, Exit, and DispatcherUnhandledException + ' can be handled in this file. + +End Class diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/MainWindow.xaml new file mode 100644 index 0000000000..e8ad57a8ff --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/MainWindow.xaml @@ -0,0 +1,33 @@ + + + + + + + + + + My Pictures + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/MainWindow.xaml.vb new file mode 100644 index 0000000000..0adf714f8d --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/MainWindow.xaml.vb @@ -0,0 +1,7 @@ +Class MainWindow + Private Sub Window_Loaded(sender As Object, e As Windows.RoutedEventArgs) + ' + textblock1.Style = CType(Resources("TitleText"), Windows.Style) + ' + End Sub +End Class diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/Photo.vb b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/Photo.vb new file mode 100644 index 0000000000..59866e0d99 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/Photo.vb @@ -0,0 +1,13 @@ +' +Public Class Photo + Sub New(ByVal path As String) + Source = path + End Sub + + Public ReadOnly Property Source As String + + Public Overrides Function ToString() As String + Return Source + End Function +End Class +' diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/VBExample.vbproj b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/VBExample.vbproj new file mode 100644 index 0000000000..c453c2b9c6 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-create-apply-style/vb/VBExample.vbproj @@ -0,0 +1,11 @@ + + + + WinExe + netcoreapp3.1 + IntroToStylingAndTemplating + true + IntroToStylingAndTemplating + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/App.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/App.cs new file mode 100644 index 0000000000..50bab6f682 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/App.cs @@ -0,0 +1,14 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Windows; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} \ No newline at end of file diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/App.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/App.xaml new file mode 100644 index 0000000000..a4bba90757 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/App.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/CSharpExample.csproj b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/CSharpExample.csproj new file mode 100644 index 0000000000..661e3a79d0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/CSharpExample.csproj @@ -0,0 +1,29 @@ + + + + WinExe + netcoreapp3.1 + IntroToStylingAndTemplating + true + IntroToStylingAndTemplating + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/MainWindow.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/MainWindow.cs new file mode 100644 index 0000000000..185500d374 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/MainWindow.cs @@ -0,0 +1,27 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Windows; +using System.Windows.Data; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + private PhotoList _photos; + + public MainWindow() + { + InitializeComponent(); + } + + private void WindowLoaded(object sender, RoutedEventArgs e) + { + _photos = (PhotoList) (Resources["MyPhotos"] as ObjectDataProvider).Data; + _photos.Path = "images"; + } + } +} \ No newline at end of file diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/MainWindow.xaml new file mode 100644 index 0000000000..b263d5a91b --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/MainWindow.xaml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + My Pictures + Check out my new pictures! + + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Photo.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Photo.cs new file mode 100644 index 0000000000..34bd270476 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Photo.cs @@ -0,0 +1,19 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace IntroToStylingAndTemplating +{ + // + public class Photo + { + public Photo(string path) + { + Source = path; + } + + public string Source { get; } + + public override string ToString() => Source; + } + // +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/PhotoList.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/PhotoList.cs new file mode 100644 index 0000000000..8c78cd7bb9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/PhotoList.cs @@ -0,0 +1,55 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.ObjectModel; +using System.IO; + +namespace IntroToStylingAndTemplating +{ + public class PhotoList : ObservableCollection + { + private DirectoryInfo _directory; + + public PhotoList() + { + } + + public PhotoList(string path) : this(new DirectoryInfo(path)) + { + } + + public PhotoList(DirectoryInfo directory) + { + _directory = directory; + Update(); + } + + public string Path + { + set + { + _directory = new DirectoryInfo(value); + Update(); + } + get { return _directory.FullName; } + } + + public DirectoryInfo Directory + { + set + { + _directory = value; + Update(); + } + get { return _directory; } + } + + private void Update() + { + foreach (var f in _directory.GetFiles("*.jpg")) + { + Add(new Photo(f.FullName)); + } + } + } +} \ No newline at end of file diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window1.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window1.xaml new file mode 100644 index 0000000000..4358f6639e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window1.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + My Pictures + Check out my new pictures! + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window1.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window1.xaml.cs new file mode 100644 index 0000000000..dbfa52e78e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window1.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window1.xaml + /// + public partial class Window1 : Window + { + public Window1() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window2.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window2.xaml new file mode 100644 index 0000000000..cf47444b5d --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window2.xaml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + My Pictures + Check out my new pictures! + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window2.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window2.xaml.cs new file mode 100644 index 0000000000..65023c6f1e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window2.xaml.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window2.xaml + /// + public partial class Window2 : Window + { + public Window2() + { + InitializeComponent(); + } + + private void Window_Loaded(object sender, RoutedEventArgs e) + { + // + textblock1.Style = (Style)Resources["TitleText"]; + // + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window3.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window3.xaml new file mode 100644 index 0000000000..5de67078c0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window3.xaml @@ -0,0 +1,20 @@ + + + + + + My Pictures + Check out my new pictures! + + + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window3.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window3.xaml.cs new file mode 100644 index 0000000000..960a9049ea --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window3.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window3.xaml + /// + public partial class Window3 : Window + { + public Window3() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window4.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window4.xaml new file mode 100644 index 0000000000..541d94a084 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window4.xaml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + My Pictures + Check out my new pictures! + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window4.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window4.xaml.cs new file mode 100644 index 0000000000..e6a7dffdca --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window4.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window4.xaml + /// + public partial class Window4 : Window + { + public Window4() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window5.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window5.xaml new file mode 100644 index 0000000000..c2ea90cd24 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window5.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + My Pictures + Check out my new pictures! + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window5.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window5.xaml.cs new file mode 100644 index 0000000000..95cf6d8612 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window5.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window5.xaml + /// + public partial class Window5 : Window + { + public Window5() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window6.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window6.xaml new file mode 100644 index 0000000000..2851b1e516 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window6.xaml @@ -0,0 +1,53 @@ + + + + + + + + My Pictures + Check out my new pictures! + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window6.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window6.xaml.cs new file mode 100644 index 0000000000..8db370c23e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/Window6.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window6.xaml + /// + public partial class Window6 : Window + { + public Window6() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/WindowExplicitStyle.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/WindowExplicitStyle.xaml new file mode 100644 index 0000000000..254fe997fa --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/WindowExplicitStyle.xaml @@ -0,0 +1,25 @@ + + + + + + + + + My Pictures + Check out my new pictures! + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/WindowExplicitStyle.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/WindowExplicitStyle.xaml.cs new file mode 100644 index 0000000000..f28be5f957 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/WindowExplicitStyle.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for ExplicitStyle.xaml + /// + public partial class ExplicitStyle : Window + { + public ExplicitStyle() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/WindowSingleResource.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/WindowSingleResource.xaml new file mode 100644 index 0000000000..3c2510b1b0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/WindowSingleResource.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/WindowSingleResource.xaml.cs b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/WindowSingleResource.xaml.cs new file mode 100644 index 0000000000..66e60e8052 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/WindowSingleResource.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for WindowSingleResource.xaml + /// + public partial class WindowSingleResource : Window + { + public WindowSingleResource() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/flower1.jpg b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/flower1.jpg new file mode 100644 index 0000000000..6eb28def82 Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/flower1.jpg differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/flower2.jpg b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/flower2.jpg new file mode 100644 index 0000000000..f3004f29ad Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/flower2.jpg differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/leaf1.jpg b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/leaf1.jpg new file mode 100644 index 0000000000..1ab47b0140 Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/leaf1.jpg differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/leaf2.jpg b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/leaf2.jpg new file mode 100644 index 0000000000..8dae26ff5c Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/leaf2.jpg differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/winter1.jpg b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/winter1.jpg new file mode 100644 index 0000000000..8baa8b4961 Binary files /dev/null and b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/csharp/images/winter1.jpg differ diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/Application.xaml new file mode 100644 index 0000000000..7f4e220d66 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/Application.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/Application.xaml.vb new file mode 100644 index 0000000000..084cbe917e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/Application.xaml.vb @@ -0,0 +1,6 @@ +Class Application + + ' Application-level events, such as Startup, Exit, and DispatcherUnhandledException + ' can be handled in this file. + +End Class diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/MainWindow.xaml new file mode 100644 index 0000000000..e8ad57a8ff --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/MainWindow.xaml @@ -0,0 +1,33 @@ + + + + + + + + + + My Pictures + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/MainWindow.xaml.vb new file mode 100644 index 0000000000..0adf714f8d --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/MainWindow.xaml.vb @@ -0,0 +1,7 @@ +Class MainWindow + Private Sub Window_Loaded(sender As Object, e As Windows.RoutedEventArgs) + ' + textblock1.Style = CType(Resources("TitleText"), Windows.Style) + ' + End Sub +End Class diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/Photo.vb b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/Photo.vb new file mode 100644 index 0000000000..59866e0d99 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/Photo.vb @@ -0,0 +1,13 @@ +' +Public Class Photo + Sub New(ByVal path As String) + Source = path + End Sub + + Public ReadOnly Property Source As String + + Public Overrides Function ToString() As String + Return Source + End Function +End Class +' diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/VBExample.vbproj b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/VBExample.vbproj new file mode 100644 index 0000000000..c453c2b9c6 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/snippets/styles-templates-overview/vb/VBExample.vbproj @@ -0,0 +1,11 @@ + + + + WinExe + netcoreapp3.1 + IntroToStylingAndTemplating + true + IntroToStylingAndTemplating + + + diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/styles-templates-create-apply-style.md b/dotnet-desktop-guide/net/wpf/fundamentals/styles-templates-create-apply-style.md new file mode 100644 index 0000000000..4ad4de1f54 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/styles-templates-create-apply-style.md @@ -0,0 +1,106 @@ +--- +title: Create a style for a control +description: Learn how to create and reference a control style in Windows Presentation Foundation and .NET Core. +author: adegeo +ms.author: adegeo +ms.date: 09/12/2019 +dev_langs: + - "csharp" + - "vb" +#no-loc: [TextBlock, Setter] +--- + +# Create a style for a control in WPF + +With Windows Presentation Foundation (WPF), you can customize an existing control's appearance with your own reusable style. Styles can be applied globally to your app, windows and pages, or directly to controls. + +[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)] + +## Create a style + +You can think of a as a convenient way to apply a set of property values to one or more elements. You can use a style on any element that derives from or such as a or a . + +The most common way to declare a style is as a resource in the `Resources` section in a XAML file. Because styles are resources, they obey the same scoping rules that apply to all resources. Put simply, where you declare a style affects where the style can be applied. For example, if you declare the style in the root element of your app definition XAML file, the style can be used anywhere in your app. + +[!code-xaml[AppResources](./snippets/styles-templates-create-apply-style/csharp/App.xaml#AppResources)] + +If you declare the style in one of the app's XAML files, the style can be used only in that XAML file. For more information about scoping rules for resources, see [XAML Resources](xaml-resources-define.md). + +[!code-xaml[AppResources](./snippets/styles-templates-create-apply-style/csharp/WindowSingleResource.xaml#WindowResources)] + +A style is made up of `` child elements that set properties on the elements the style is applied to. In the example above, notice that the style is set to apply to `TextBlock` types through the `TargetType` attribute. The style will set the to `15` and the to `ExtraBold`. Add a `` for each property the style changes. + +## Apply a style implicitly + +A is a convenient way to apply a set of property values to more than one element. For example, consider the following elements and their default appearance in a window. + +[!code-xaml[TextBlocks](./snippets/styles-templates-create-apply-style/csharp/Window1.xaml#SnippetTextBlocks)] + +![Styling sample screenshot](./media/styles-and-templates-overview/stylingintro-textblocksbefore.png "StylingIntro_TextBlocksBefore") + +You can change the default appearance by setting properties, such as and , on each element directly. However, if you want your elements to share some properties, you can create a in the `Resources` section of your XAML file, as shown here. + +[!code-xaml[DefaultTextBlockStyle](./snippets/styles-templates-create-apply-style/csharp/Window1.xaml#SnippetDefaultTextBlockStyle)] + +When you set the of your style to the type and omit the `x:Key` attribute, the style is applied to all the elements scoped to the style, which is generally the XAML file itself. + +Now the elements appear as follows. + +![Styling sample screenshot](./media/styles-and-templates-overview/stylingintro-textblocksbasestyle.png "StylingIntro_TextBlocksBaseStyle") + +## Apply a style explicitly + +If you add an `x:Key` attribute with value to the style, the style is no longer implicitly applied to all elements of . Only elements that explicitly reference the style will have the style applied to them. + +Here is the style from the previous section, but declared with the `x:Key` attribute. + +[!code-xaml[ExplicitStyleDeclare](./snippets/styles-templates-create-apply-style/csharp/WindowExplicitStyle.xaml#ExplicitStyleDeclare)] + +To apply the style, set the property on the element to the `x:Key` value, using a [StaticResource markup extension](../../../framework/wpf/advanced/staticresource-markup-extension.md), as shown here. + +[!code-xaml[ExplicitStyleReference](./snippets/styles-templates-create-apply-style/csharp/WindowExplicitStyle.xaml#ExplicitStyleReference)] + +Notice that the first element has the style applied to it while the second TextBlock element remains unchanged. The implicit style from the previous section was changed to a style that declared the `x:Key` attribute, meaning, the only element affected by the style is the one that referenced the style directly. + +![Styling sample screenshot](./media/styles-and-templates-overview/create-a-style-explicit-textblock.png "create-a-style-explicit-textblock") + +Once a style is applied, explicitly or implicitly, it becomes sealed and can't be changed. If you want to change a style that has been applied, create a new style to replace the existing one. For more information, see the property. + +You can create an object that chooses a style to apply based on custom logic. For an example, see the example provided for the class. + +## Apply a style programmatically + +To assign a named style to an element programmatically, get the style from the resources collection and assign it to the element's property. The items in a resources collection are of type . Therefore, you must cast the retrieved style to a before assigning it to the `Style` property. For example, the following code sets the style of a `TextBlock` named `textblock1` to the defined style `TitleText`. + +[!code-csharp[SetStyleCode](./snippets/styles-templates-create-apply-style/csharp/Window2.xaml.cs#SnippetSetStyleCode)] +[!code-vb[SetStyleCode](./snippets/styles-templates-create-apply-style/vb/MainWindow.xaml.vb#SnippetSetStyleCode)] + +## Extend a style + +Perhaps you want your two elements to share some property values, such as the and the centered . But you also want the text **My Pictures** to have some additional properties. You can do that by creating a new style that is based on the first style, as shown here. + +[!code-xaml[DefaultTextBlockStyleBasedOn](./snippets/styles-templates-create-apply-style/csharp/Window2.xaml#SnippetDefaultTextBlockStyleBasedOn)] + +[!code-xaml[TextBlocksExplicit](./snippets/styles-templates-create-apply-style/csharp/Window2.xaml#SnippetTextBlocksExplicit)] + +This `TextBlock` style is now centered, uses a `Comic Sans MS` font with a size of `26`, and the foreground color set to the shown in the example. Notice that it overrides the value of the base style. If there's more than one pointing to the same property in a , the `Setter` that is declared last takes precedence. + +The following shows what the elements now look like: + +![Styled TextBlocks](./media/styles-and-templates-overview/stylingintro-textblocks.png "StylingIntro_TextBlocks") + +This `TitleText` style extends the style that has been created for the type, referenced with `BasedOn="{StaticResource {x:Type TextBlock}}"`. You can also extend a style that has an `x:Key` by using the `x:Key` of the style. For example, if there was a style named `Header1` and you wanted to extend that style, you would use `BasedOn="{StaticResource Header1}"`. + +## Relationship of the TargetType property and the x:Key attribute + +As previously shown, setting the property to `TextBlock` without assigning the style an `x:Key` causes the style to be applied to all elements. In this case, the `x:Key` is implicitly set to `{x:Type TextBlock}`. This means that if you explicitly set the `x:Key` value to anything other than `{x:Type TextBlock}`, the isn't applied to all `TextBlock` elements automatically. Instead, you must apply the style (by using the `x:Key` value) to the `TextBlock` elements explicitly. If your style is in the resources section and you don't set the `TargetType` property on your style, then you must set the `x:Key` attribute. + +In addition to providing a default value for the `x:Key`, the `TargetType` property specifies the type to which setter properties apply. If you don't specify a `TargetType`, you must qualify the properties in your objects with a class name by using the syntax `Property="ClassName.Property"`. For example, instead of setting `Property="FontSize"`, you must set to `"TextBlock.FontSize"` or `"Control.FontSize"`. + +Also note that many WPF controls consist of a combination of other WPF controls. If you create a style that applies to all controls of a type, you might get unexpected results. For example, if you create a style that targets the type in a , the style is applied to all `TextBlock` controls in the window, even if the `TextBlock` is part of another control, such as a . + +## See also + + +- [Overview of XAML Resources](xaml-resources-define.md) +- [XAML overview (WPF & .NET Core)](xaml.md) diff --git a/dotnet-desktop-guide/net/wpf/fundamentals/styles-templates-overview.md b/dotnet-desktop-guide/net/wpf/fundamentals/styles-templates-overview.md new file mode 100644 index 0000000000..85e3f50399 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/fundamentals/styles-templates-overview.md @@ -0,0 +1,242 @@ +--- +title: Styles and templates +description: Learn about XAML resources in Windows Presentation Foundation (WPF) for .NET Core. Understand the types of XAML resources related to styles and themes. +author: adegeo +ms.author: adegeo +ms.date: 09/09/2019 +dev_langs: + - "csharp" + - "vb" +--- + +# Styles and templates in WPF + +Windows Presentation Foundation (WPF) styling and templating refer to a suite of features that let developers and designers create visually compelling effects and a consistent appearance for their product. When customizing the appearance of an app, you want a strong styling and templating model that enables maintenance and sharing of appearance within and among apps. WPF provides that model. + +Another feature of the WPF styling model is the separation of presentation and logic. Designers can work on the appearance of an app by using only XAML at the same time that developers work on the programming logic by using C# or Visual Basic. + +This overview focuses on the styling and templating aspects of the app and doesn't discuss any data-binding concepts. For information about data binding, see [Data Binding Overview](../data/data-binding-overview.md). + +It's important to understand resources, which are what enable styles and templates to be reused. For more information about resources, see [XAML Resources](xaml-resources-define.md). + +[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)] + +## Sample + +The sample code provided in this overview is based on a [simple photo browsing application](https://github.com/Microsoft/WPF-Samples/tree/master/Styles%20&%20Templates/IntroToStylingAndTemplating) shown in the following illustration. + +![Styled ListView](./media/styles-and-templates-overview/stylingintro-triggers.png "StylingIntro_triggers") + +This simple photo sample uses styling and templating to create a visually compelling user experience. The sample has two elements and a control that is bound to a list of images. + +For the complete sample, see [Introduction to Styling and Templating Sample](https://github.com/Microsoft/WPF-Samples/tree/master/Styles%20&%20Templates/IntroToStylingAndTemplating). + +## Styles + +You can think of a as a convenient way to apply a set of property values to multiple elements. You can use a style on any element that derives from or such as a or a . + +The most common way to declare a style is as a resource in the `Resources` section in a XAML file. Because styles are resources, they obey the same scoping rules that apply to all resources. Put simply, where you declare a style affects where the style can be applied. For example, if you declare the style in the root element of your app definition XAML file, the style can be used anywhere in your app. + +For example, the following XAML code declares two styles for a `TextBlock`, one automatically applied to all `TextBlock` elements, and another that must be explicitly referenced. + +[!code-xaml[SnippetDefaultTextBlockStyleBasedOn](./snippets/styles-templates-overview/csharp/Window2.xaml#SnippetDefaultTextBlockStyleBasedOn)] + +Here is an example of the styles declared above being used. + +[!code-xaml[SnippetTextBlocksExplicit](./snippets/styles-templates-overview/csharp/Window2.xaml#SnippetTextBlocksExplicit)] + +![Styled textblocks](./media/styles-and-templates-overview/stylingintro-textblocks.png) + +For more information, see [Create a style for a control](styles-templates-create-apply-style.md). + +## ControlTemplates + +In WPF, the of a control defines the appearance of the control. You can change the structure and appearance of a control by defining a new and assigning it to a control. In many cases, templates give you enough flexibility so that you do not have to write your own custom controls. + +Each control has a default template assigned to the [Control.Template](xref:System.Windows.Controls.Control.Template) property. The template connects the visual presentation of the control with the control's capabilities. Because you define a template in XAML, you can change the control's appearance without writing any code. Each template is designed for a specific control, such as a . + +Commonly you declare a template as a resource on the `Resources` section of a XAML file. As with all resources, scoping rules apply. + +Control templates are a lot more involved than a style. This is because the control template rewrites the visual appearance of the entire control, while a style simply applies property changes to the existing control. However, since the template of a control is applied by setting the [Control.Template](xref:System.Windows.Controls.Control.Template) property, you can use a style to define or set a template. + +Designers generally allow you to create a copy of an existing template and modify it. For example, in the Visual Studio WPF designer, select a `CheckBox` control, and then right-click and select **Edit template** > **Create a copy**. This command generates a *style that defines a template*. + +```xaml + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/CSharpExample.csproj b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/CSharpExample.csproj new file mode 100644 index 0000000000..c453c2b9c6 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/CSharpExample.csproj @@ -0,0 +1,11 @@ + + + + WinExe + netcoreapp3.1 + IntroToStylingAndTemplating + true + IntroToStylingAndTemplating + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/MainWindow.cs b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/MainWindow.cs new file mode 100644 index 0000000000..224653181c --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/MainWindow.cs @@ -0,0 +1,28 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Windows; +using System.Windows.Data; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + } + + private void WindowLoaded(object sender, RoutedEventArgs e) + { + } + + private void Button_Click(object sender, RoutedEventArgs e) + { + MessageBox.Show("Clicked"); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/MainWindow.xaml new file mode 100644 index 0000000000..bd1bb12ee8 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/MainWindow.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window1.xaml b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window1.xaml new file mode 100644 index 0000000000..b49fd59146 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window1.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window1.xaml.cs b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window1.xaml.cs new file mode 100644 index 0000000000..dbfa52e78e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window1.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window1.xaml + /// + public partial class Window1 : Window + { + public Window1() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window2.xaml b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window2.xaml new file mode 100644 index 0000000000..ef27f8dc00 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window2.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window2.xaml.cs b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window2.xaml.cs new file mode 100644 index 0000000000..6184fbb8bf --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window2.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window2.xaml + /// + public partial class Window2 : Window + { + public Window2() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window3.xaml b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window3.xaml new file mode 100644 index 0000000000..018d7ce909 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window3.xaml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window3.xaml.cs b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window3.xaml.cs new file mode 100644 index 0000000000..960a9049ea --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window3.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window3.xaml + /// + public partial class Window3 : Window + { + public Window3() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window4.xaml b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window4.xaml new file mode 100644 index 0000000000..fe6cab1d33 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window4.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window4.xaml.cs b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window4.xaml.cs new file mode 100644 index 0000000000..e6a7dffdca --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window4.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window4.xaml + /// + public partial class Window4 : Window + { + public Window4() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window5.xaml b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window5.xaml new file mode 100644 index 0000000000..04274c9f88 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window5.xaml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window5.xaml.cs b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window5.xaml.cs new file mode 100644 index 0000000000..95cf6d8612 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window5.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window5.xaml + /// + public partial class Window5 : Window + { + public Window5() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window6.xaml b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window6.xaml new file mode 100644 index 0000000000..c61499a2ef --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window6.xaml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window6.xaml.cs b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window6.xaml.cs new file mode 100644 index 0000000000..8db370c23e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window6.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window6.xaml + /// + public partial class Window6 : Window + { + public Window6() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window7.xaml b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window7.xaml new file mode 100644 index 0000000000..5dbcb54373 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window7.xaml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window7.xaml.cs b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window7.xaml.cs new file mode 100644 index 0000000000..c37e7de2f4 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/Window7.xaml.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for Window7.xaml + /// + public partial class Window7 : Window + { + public Window7() + { + InitializeComponent(); + } + + private void Button_Click(object sender, RoutedEventArgs e) + { + MessageBox.Show("Clicked"); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/WindowExplicitStyle.xaml b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/WindowExplicitStyle.xaml new file mode 100644 index 0000000000..254fe997fa --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/WindowExplicitStyle.xaml @@ -0,0 +1,25 @@ + + + + + + + + + My Pictures + Check out my new pictures! + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/WindowExplicitStyle.xaml.cs b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/WindowExplicitStyle.xaml.cs new file mode 100644 index 0000000000..f28be5f957 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/WindowExplicitStyle.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for ExplicitStyle.xaml + /// + public partial class ExplicitStyle : Window + { + public ExplicitStyle() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/WindowSingleResource.xaml b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/WindowSingleResource.xaml new file mode 100644 index 0000000000..3c2510b1b0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/WindowSingleResource.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/WindowSingleResource.xaml.cs b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/WindowSingleResource.xaml.cs new file mode 100644 index 0000000000..66e60e8052 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/csharp/WindowSingleResource.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace IntroToStylingAndTemplating +{ + /// + /// Interaction logic for WindowSingleResource.xaml + /// + public partial class WindowSingleResource : Window + { + public WindowSingleResource() + { + InitializeComponent(); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/Application.xaml new file mode 100644 index 0000000000..7f4e220d66 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/Application.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/Application.xaml.vb new file mode 100644 index 0000000000..084cbe917e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/Application.xaml.vb @@ -0,0 +1,6 @@ +Class Application + + ' Application-level events, such as Startup, Exit, and DispatcherUnhandledException + ' can be handled in this file. + +End Class diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/MainWindow.xaml new file mode 100644 index 0000000000..f62477d1ba --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/MainWindow.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/MainWindow.xaml.vb new file mode 100644 index 0000000000..e2e55ee1a9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/MainWindow.xaml.vb @@ -0,0 +1,6 @@ +Class MainWindow + + Private Sub WindowLoaded(sender As Object, e As Windows.RoutedEventArgs) + + End Sub +End Class diff --git a/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/VBExample.vbproj b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/VBExample.vbproj new file mode 100644 index 0000000000..c453c2b9c6 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/themes/snippets/how-to-create-apply-template/vb/VBExample.vbproj @@ -0,0 +1,11 @@ + + + + WinExe + netcoreapp3.1 + IntroToStylingAndTemplating + true + IntroToStylingAndTemplating + + + diff --git a/dotnet-desktop-guide/net/wpf/toc.yml b/dotnet-desktop-guide/net/wpf/toc.yml new file mode 100644 index 0000000000..d125f7a48a --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/toc.yml @@ -0,0 +1,58 @@ +- name: Windows Presentation Foundation for .NET Core + href: index.yml +- name: Get started + items: + - name: Overview + href: overview/index.md + - name: Create a WPF application + href: https://docs.microsoft.com/visualstudio/get-started/csharp/tutorial-wpf + # - name: Create a control library + # href: getting-started/how-to-create-control-library.md +- name: Migration + items: + - name: Differences from .NET Framework + href: migration/differences-from-net-framework.md + - name: Migrate from Framework to Core + href: migration/convert-project-from-net-framework.md +- name: Fundamentals + items: + - name: XAML + href: fundamentals/xaml.md + - name: Define resources + href: fundamentals/xaml-resources-define.md + - name: Styles and templates + items: + - name: Overview + href: fundamentals/styles-templates-overview.md + - name: Create and apply a style + href: fundamentals/styles-templates-create-apply-style.md + - name: Create and apply a template + href: themes/how-to-create-apply-template.md + #- name: Accessibility overview + # href: fundamentals/accessibility.md + #- name: Localize your app + # href: fundamentals/localize-app.md + #- name: Draw shapes + # href: fundamentals/draw-shapes.md + #- name: Display a dialog popup + # href: fundamentals/display-dialog-popup.md + - name: XAML Language Reference + href: ../../xaml-services/ +- name: Work with data + items: + - name: Data binding overview + href: data/data-binding-overview.md + # - name: Add data binding to a control + # href: data/databind-control.md + # - name: Add validation to a control + # href: data/validate-control-input.md + # - name: Display data in a grid control + # href: data/use-datagrid-control.md +# - name: Package and distribute +# items: +# - name: Package your app with MSIX +# href: publishing/package-app-msix.md +# - name: Publish a library to NuGet +# href: publishing/create-nuget-package.md +# - name: Publish to the Microsoft Store +# href: publishing/publish-microsoft-store.md diff --git a/dotnet-desktop-guide/xaml-services/basic-reading-writing.md b/dotnet-desktop-guide/xaml-services/basic-reading-writing.md new file mode 100644 index 0000000000..0d58de406c --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/basic-reading-writing.md @@ -0,0 +1,77 @@ +--- +title: "XAMLServices Class and Basic XAML Reading or Writing" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML [XAML Services], XamlServices class" + - "XamlServices class [XAML Services], how to use" +ms.assetid: 6ac27fad-3687-4d7a-add1-3e90675fdfde +--- +# XAMLServices class and basic XAML reading or writing + + is a class provided by .NET that can be used to address XAML scenarios that don't require specific access to the XAML node stream or to XAML type system information obtained from those nodes. API can be summarized as follows: `Load` or `Parse` to support a XAML load path, `Save` to support a XAML save path, and `Transform` to provide a technique that joins a load path and save path. `Transform` can be used to change from one XAML schema to another. This topic summarizes each of these API classifications and describes the differences between particular method overloads. + +## Load + +Various overloads of implement the complete logic for a load path. The load path uses XAML in some form and outputs a XAML node stream. Most of these load paths use XAML in an encoded XML text-file form. However, you can also load a general stream, or you can load a preloaded XAML source that is already contained in a different implementation. + +The simplest overload for most scenarios is . This overload has a `fileName` parameter that is simply the name of a text file that contains the XAML to load. This is appropriate for application scenarios such as full trust applications that have previously serialized state or data to the local computer. This is also useful for frameworks where you are defining the application model and want to load one of the standard files that defines application behavior, starting UI, or other framework-defined capabilities that use XAML. + + has similar scenarios. This overload might be useful if you have the user choose files to load, because a is a frequent output of other APIs that can access a file system. Or you could be accessing XAML sources through asynchronous downloads or other network techniques that also provide a stream. (Loading from a stream or user-selected source may have security implications. For more information, see [XAML Security Considerations](security-considerations.md).) + + and are overloads that rely on readers of formats from previous versions of .NET. To use these overloads, you should have already created a reader instance and used its `Create` API to load the XAML in the relevant form (text or XML). If you have already moved record pointers in the other readers or performed other operations with them, this is not important. The load path logic from always processes the entire XAML input from the root down. The following scenarios might warrant the use of these overloads: + +- Design surfaces where you provide simple XAML editing capability from an existing XML-specific text editor. + +- Variants of the core scenarios, where you use the dedicated readers to open files or streams. Your logic performs rudimentary checking or processing of the contents before it tries to load as XAML. + +You can either load a file or stream, or you can load an , , or that wraps your XAML input by loading with the reader's APIs. + +Internally, each of the preceding overloads is ultimately , and the passed is used to create a new . + +The `Load` signature that provides for more advanced scenarios is . You can use this signature for one of the following cases: + +- You've defined your own implementation of a . + +- You need to specify settings for that vary from the default settings. + +Examples of non-default settings: + +\ +\ +\ +\ +. + +The default reader for is . If you provide your own with settings, the following are properties to set non-default : + +\ +\ +\ + + +## Parse + + is like `Load` because it is a load path API that creates a XAML node stream from XAML input. However, in this case, the XAML input is provided directly as a string that contains all the XAML to load. is a lightweight approach that is more appropriate for application scenarios than framework scenarios. For more information, see . is just a wrapped call that involves a internally. + +## Save + +Various overloads of implement the save path. All of the methods all take an object graph as input and produce output as a stream, file, or / instance. + +The input object is expected to be the root object of some object representation. This might be the single root of a business object, the root of an object tree for a page in a UI scenario, the working editing surface from a design tool, or other root object concepts that are appropriate for scenarios. + +In many scenarios, the object tree that you save is related to an original operation that loaded XAML either with or with other API implemented by a framework/application model. There might be differences captured in the object tree that are due to state changes, changes where your application captured runtime settings from a user, changed XAML because your application is a XAML design surface, etc. With or without changes, the concept of first loading XAML from markup and then saving it again and comparing the two XAML markup forms is sometimes referred as a round-trip representation of the XAML. + +The challenge with saving and serializing a complex object that is set in a markup form is in achieving a balance between full representation without information loss, versus verbosity that makes the XAML less human-readable. Moreover, different customers for XAML might have different definitions or expectations for how that balance should be set. The APIs represent one definition of that balance. The APIs use available XAML schema context and the default CLR-based characteristics of , , and other XAML intrinsic and XAML type system concepts to determine where certain XAML node stream constructs can be optimized when they are saved back into markup. For example, save paths can use CLR-based default XAML schema context to resolve for objects, can determine a , and then can omit property element tags when they write the property to the XAML content of the object. + + +## Transform + + converts or transforms XAML by linking a load path and a save path as a single operation. A different schema context or different backing type system can be used for and , which is what influences how the resulting XAML is transformed. This works well for broad transform operations. + +For operations that rely on examining each node in a XAML node stream, you typically do not use . Instead you need to define your own load path-save path operation series and interject your own logic. In one of the paths, use a XAML reader/XAML writer pair around your own node loop. For example, load the initial XAML using and step into the nodes with successive calls. Operating at the XAML node stream level you can now adjust individual nodes (types, members, other nodes) to apply a transformation, or leave the node as-is. Then you send the node onwards to the relevant `Write` API of a and write out the object. For more information, see [Understanding XAML Node Stream Structures and Concepts](understanding-xaml-node-stream-structures-and-concepts.md). + +## See also + +- +- +- [XAML Services](/dotnet/api/) diff --git a/dotnet-desktop-guide/xaml-services/breadcrumb/toc.yml b/dotnet-desktop-guide/xaml-services/breadcrumb/toc.yml new file mode 100644 index 0000000000..685c144f3b --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/breadcrumb/toc.yml @@ -0,0 +1,16 @@ +items: +- name: Docs + tocHref: / + topicHref: / + items: + - name: .NET + tocHref: /dotnet/ + topicHref: /dotnet/index + items: + - name: Desktop Guide + tocHref: /dotnet/desktop + topicHref: /dotnet/desktop/index + items: + - name: XAML Language Reference + tocHref: /dotnet/desktop/xaml-services + topicHref: /dotnet/desktop/xaml-services/index diff --git a/dotnet-desktop-guide/xaml-services/clr-attributes-with-custom-types-and-libraries.md b/dotnet-desktop-guide/xaml-services/clr-attributes-with-custom-types-and-libraries.md new file mode 100644 index 0000000000..829f66b98f --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/clr-attributes-with-custom-types-and-libraries.md @@ -0,0 +1,292 @@ +--- +title: "XAML-Related CLR Attributes for Custom Types and Libraries" +ms.date: "03/30/2017" +helpviewer_keywords: + - "CLR attributes for custom types [XAML Services]" +ms.assetid: 5dfb299a-b6e2-41b8-8694-e6ac987547f1 +--- +# XAML-related CLR attributes for custom types and libraries + +This topic describes the common language runtime (CLR) attributes that are defined by .NET XAML Services. It also describes other CLR attributes that are defined in .NET that have a XAML-related scenario for application to assemblies or types. Attributing assemblies, types, or members with these CLR attributes provides XAML type system information related to your types. Information is provided to any XAML consumer that uses .NET XAML Services for processing the XAML node stream directly or through the dedicated XAML readers and XAML writers. + +## XAML-Related CLR Attributes for Custom Types and Custom Members + +Using CLR attributes entails that you are using the overall CLR to define your types, otherwise such attributes are not available. If you use the CLR to define type backing, then the default XAML schema context used by .NET XAML Services XAML writers can read CLR attribution through reflection against backing assemblies. + +The following sections describe the XAML-related attributes that you can apply to custom types or custom members. Each CLR attribute communicates information that is relevant to a XAML type system. In the load path, the attributed information either helps the XAML reader form a valid XAML node stream, or it helps the XAML writer produce a valid object graph. In the save path, the attributed information either helps the XAML reader form a valid XAML node stream that reconstitutes XAML type system information; or it declares serialization hints or requirements for the XAML writer or other XAML consumers. + +### AmbientAttribute + +**Reference Documentation:** + +**Applies to:** Class, property, or `get` accessor members that support attachable properties. + +**Arguments:** None + + indicates that the property, or all properties that take the attributed type, should be interpreted under the ambient property concept in XAML. The ambient concept relates to how XAML processors determine type owners of members. An ambient property is a property where the value is expected to be available in the parser context when creating an object graph, but where typical type-member lookup is suspended for the immediate XAML node set being created. + +The ambient concept can be applied to attachable members, which are not represented as properties in terms of how CLR attribution defines . The method attribution usage should be applied only for a `get` accessor that supports attachable usage for XAML. + +### ConstructorArgumentAttribute + +**Reference Documentation:** + +**Applies to:** Class + +**Arguments:** A string that specifies the name of the property that matches a single constructor argument. + + specifies that an object can be initialized by using a non-parameterless constructor syntax, and that a property of the specified name supplies construction information. This information is primarily for XAML serialization. For more information, see . + +### ContentPropertyAttribute + +**Reference Documentation:** + +**Applies to:** Class + +**Arguments:** A string that specifies the name of a member of the attributed type. + + indicates that the property as named by the argument should serve as the XAML content property for that type. The XAML content property definition inherits to all derived types that are assignable to the defining type. You can override the definition on a specific derived type by applying on the specific derived type. + +For the property that serves as the XAML content property, property element tagging for the property can be omitted in the XAML usage. Typically, you designate XAML content properties that promote a streamlined XAML markup for your content and containment models. Because only one member can be designated as the XAML content property, you sometimes have design choices to make regarding which of several container properties of a type should be designated as the XAML content property. The other container properties must be used with explicit property elements. + +In the XAML node stream, XAML content properties still produce `StartMember` and `EndMember` nodes, using the name of the property for the . To determine whether a member is the XAML content property, examine the value from the `StartObject` position and obtain the value of . + +### ContentWrapperAttribute + +**Reference Documentation:** + +**Applies to:** Class, specifically collection types. + +**Arguments:** A that specifies the type to use as the content wrapper type for foreign content. + + specifies one or more types on the associated collection type that will be used to wrap foreign content. Foreign content refers to cases where the type system constraints on the type of the content property do not capture all of the possible content cases that XAML usage for the owning type would support. For example, XAML support for content of a particular type might support strings in a strongly typed generic . Content wrappers are useful for migrating pre-existing markup conventions into XAML's conception of assignable values for collections, such as migrating text-related content models. + +To specify more than one content wrapper type, apply the attribute multiple times. + +### DependsOnAttribute + +**Reference Documentation:** + +**Applies to:** Property + +**Arguments:** A string that specifies the name of another member of the attributed type. + + indicates that the attributed property depends on the value of another property. Applying this attribute to a property definition ensures that the dependent properties are processed first in XAML object writing. Usages of specify the exceptional cases of properties on types where a specific order of parsing must be followed for valid object creation. + +You can apply multiple cases to a property definition. + +### MarkupExtensionReturnTypeAttribute + +**Reference Documentation:** + +**Applies to:** Class, which is expected to be a derived type. + +**Arguments:** A that specifies the most precise type to expect as the `ProvideValue` result of the attributed . + +For more information, see [Markup Extensions for XAML Overview](markup-extensions-overview.md). + +### NameScopePropertyAttribute + +**Reference Documentation:** + +**Applies to:** Class + +**Arguments:** Supports two forms of attribution: + +- A string that specifies the name of a property on the attributed type. + +- A string that specifies the name of a property, and a for the type that defines the named property. This form is for specifying an attachable member as the XAML namescope property. + + specifies a property that provides the XAML namescope value for the attributed class. The XAML namescope property is expected to reference an object that implements and holds the actual XAML namescope, its store, and its behavior. + +### RuntimeNamePropertyAttribute + +**Reference Documentation:** + +**Applies to:** Class + +**Arguments:** A string that specifies the name of the run-time name property on the attributed type. + + reports a property of the attributed type that maps to the XAML [x:Name Directive](xname-directive.md). The property must be of type and must be read/write. + +The definition inherits to all derived types that are assignable to the defining type. You can override the definition on a specific derived type by applying on the specific derived type. + +### TrimSurroundingWhitespaceAttribute + +**Reference Documentation:** + +**Applies to:** Types + +**Arguments:** None. + + is applied to specific types that might appear as child elements within white-space significant content (content held by a collection that has ). is mainly relevant to the save path, but is available in the XAML type system in the load path by examining . For more information, see [White-space processing in XAML](white-space-processing.md). + +### TypeConverterAttribute + +**Reference Documentation:** + +**Applies to:** Class, property, method (the only XAML-valid method case is a `get` accessor that supports an attachable member). + +**Arguments:** The of the . + + in a XAML context references a custom . This provides type conversion behavior for custom types, or members of that type. + +Apply the attribute to your type, referencing your type converter implementation. You can define type converters for XAML on classes, structures, or interfaces. You do not need to provide type conversion for enumerations, that conversion is enabled natively. + +Your type converter should be able to convert from a string that is used for attributes or initialization text in markup, into your intended destination type. For more information, see [TypeConverters and XAML](../framework/wpf/advanced/typeconverters-and-xaml.md). + +Rather than applying to all values of a type, a type converter behavior for XAML can also be established on a specific property. In this case, you apply to the property definition (the outer definition, not the specific `get` and `set` definitions). + +A type converter behavior for XAML usage of a custom attachable member can be assigned by applying to the `get` method accessor that supports the XAML usage. + +Similar to , existed in .NET prior to the existence of XAML, and the type converter model served other purposes. In order to reference and use , you must fully qualify it or provide a `using` statement for . Also include the System assembly in your project. + +### UidPropertyAttribute + +**Reference Documentation:** + +**Applies to:** Class + +**Arguments:** A string that references the relevant property by name. + +Indicates the CLR property of a class that aliases the [x:Uid Directive](xuid-directive.md). + +### UsableDuringInitializationAttribute + +**Reference Documentation:** + +**Applies to:** Class + +**Arguments:** A Boolean. If used for the attribute's intended purpose, the value should be set to `true`. + +Indicates whether the type is built top-down during XAML object graph creation. This is an advanced concept, which is probably closely related to the definition of your programming model. For more information, see . + +### ValueSerializerAttribute + +**Reference Documentation:** + +**Applies to:** Class, property, method (the only XAML-valid method case is a `get` accessor that supports an attachable member). + +**Arguments:** A that specifies the value serializer support class to use when serializing all properties of the attributed type, or the specific attributed property. + + specifies a value serialization class that requires more state and context than a does. can be associated with an attachable member by applying the attribute on the static `get` accessor method for the attachable member. Value serialization is also applicable for enumerations, interfaces, and structures, but not for delegates. + +### WhitespaceSignificantCollectionAttribute + +**Reference Documentation:** + +**Applies to:** Class, specifically collection types that are expected to host mixed content, where white space around object elements might be significant for UI representation. + +**Arguments:** None. + + indicates that a collection type should be processed as white-space significant by a XAML processor, which influences the construction of the XAML node stream's value nodes within the collection. For more information, see [White-space processing in XAML](white-space-processing.md). + +### XamlDeferLoadAttribute + +**Reference Documentation:** + +**Applies to:** Class, property. + +**Arguments:** Supports two attribution forms types as strings, or types as . See . + +Indicates that a class or property has a deferred load usage for XAML (such as a template behavior), and reports the class that enables the deferring behavior and its destination/content type. + +### XamlSetMarkupExtensionAttribute + +**Reference Documentation:** + +**Applies to:** Class + +**Arguments:** Names the callback. + +Indicates that a class can use a markup extension to provide a value for one or more of its properties, and references a handler that a XAML writer should call before performing a markup extension set operation on any property of the class. + +### XamlSetTypeConverterAttribute + +**Reference Documentation:** + +**Applies to:** Class + +**Arguments:** Names the callback. + +Indicates that a class can use a type converter to provide a value for one or more of its properties, and references a handler that a XAML writer should call before performing a type converter set operation on any property of the class. + +### XmlLangPropertyAttribute + +**Reference Documentation:** + +**Applies to:** Class + +**Arguments:** A string that specifies the name of the property to alias to `xml:lang` on the attributed type. + + reports a property of the attributed type that maps to the XML `lang` directive. The property is not necessarily of type but must be assignable from a string (assignment could be accomplished by associating a type converter with the property's type or with the specific property). The property must be read/write. + +The scenario for mapping `xml:lang` is so that a runtime object model has access to XML-specified language information without specifically processing with an XMLDOM. + +The definition inherits to all derived types that are assignable to the defining type. You can override the definition on a specific derived type by applying on the specific derived type, although that is an uncommon scenario. + +## XAML-Related CLR Attributes at the Assembly Level + +The following sections describe the XAML-related attributes that are not applied to types or member definitions, but are instead applied to assemblies. These attributes are pertinent to the overall goal of defining a library that contains custom types to use in XAML. Some of the attributes do not necessarily influence the XAML node stream directly, but are passed on in the node stream for other consumers to use. Consumers for the information include design environments or serialization processes that need XAML namespace information and associated prefix information. A XAML schema context (including the .NET XAML Services default) also uses this information. + +### XmlnsCompatibleWithAttribute + +**Reference Documentation:** + +**Arguments:** + +- A string that specifies the identifier of the XAML namespace to subsume. + +- A string that specifies the identifier of the XAML namespace that can subsume the XAML namespace from the previous argument. + + specifies that a XAML namespace can be subsumed by another XAML namespace. Typically, the subsuming XAML namespace is indicated in a previously defined . This technique can be used for versioning a XAML vocabulary in a library and to make it compatible with previously defined markup against the earlier versioned vocabulary. + +### XmlnsDefinitionAttribute + +**Reference Documentation:** + +**Arguments:** + +- A string that specifies the identifier of the XAML namespace to define. + +- A string that names a CLR namespace. The CLR namespace should define public types in your assembly, and at least one of the CLR namespace types should be intended for XAML usage. + + specifies a mapping on a per-assembly basis between a XAML namespace and a CLR namespace, which is then used for type resolution by a XAML object writer or XAML schema context. + + More than one can be applied to an assembly. This might be done for any combination of the following reasons: + +- The library design contains multiple CLR namespaces for logical organization of run-time API access; however, you want all types in those namespaces to be XAML-usable by referencing the same XAML namespace. In this case, you apply several attributes using the same value but different values. This is especially useful if you are defining mappings for the XAML namespace that your framework or application intends to be the default XAML namespace in common usage. + +- The library design contains multiple CLR namespaces, and you want a deliberate XAML namespace separation between the usages of types in those CLR namespaces. + +- You define a CLR namespace in the assembly, and you want it to be accessible through more than one XAML namespace. This scenario occurs when you are supporting multiple vocabularies with the same codebase. + +- You define XAML language support in one or more CLR namespaces. In this case, the value should be `http://schemas.microsoft.com/winfx/2006/xaml`. + +### XmlnsPrefixAttribute + +**Reference Documentation:** + +**Arguments:** + +- A string that specifies the identifier of a XAML namespace. + +- A string that specifies a recommended prefix. + + specifies a recommended prefix to use for a XAML namespace. The prefix is useful when writing elements and attributes in a XAML file that is serialized by .NET XAML Services , or when a XAML-implementing library interacts with a design environment that has XAML editing features. + + More than one can be applied to an assembly. This might be done for any combination of the following reasons: + +- Your assembly defines types for more than one XAML namespace. In this case, define different prefix values for each XAML namespace. + +- You are supporting multiple vocabularies, and you use different prefixes for each vocabulary and XAML namespace. + +- You define XAML language support in the assembly and have a for `http://schemas.microsoft.com/winfx/2006/xaml`. In this case, you typically should promote the prefix `x`. + +> [!NOTE] +> .NET XAML Services also defines the XAML-related attribute . This attribute is an assembly-level attribute for project system support, and it is not relevant for XAML custom types. + +## See also + +- +- [Defining Custom Types for Use with .NET XAML Services](define-custom-types.md) diff --git a/dotnet-desktop-guide/xaml-services/collections-and-types.md b/dotnet-desktop-guide/xaml-services/collections-and-types.md new file mode 100644 index 0000000000..eff7a83479 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/collections-and-types.md @@ -0,0 +1,44 @@ +--- +title: "Collections and Collection Types for XAML" +ms.date: "03/30/2017" +ms.assetid: 58f8e7c6-9a41-4f25-8551-c042f1315baa +--- +# Collections and collection types for XAML + +This article describes how to define properties of types that are intended to support a collection, and to support the XAML syntax for instantiating collection items as element children of a parent object element or property element. + +## XAML Collection Concepts + +Conceptually, any relationship in XAML where there are multiple child items within the scope of a XAML object element or XAML property element must be implemented as a collection. That collection must be associated with a particular XAML property of the XAML type that is the parent in that relationship. The property must be a collection because a XAML processor expects to assign each item in markup to be a newly added item of the backing collection property. + +At the XAML language level, the exact requirements of collection support are not fully defined. The concept that a collection can be either a list or a dictionary(but not both) is defined at the XAML language level, but which backing types represent either lists or dictionaries is not defined by the XAML language. + +In .NET XAML Services, the concept of XAML collection support is more clearly defined in terms of .NET backing types. Specifically, the XAML support for collections is based on several .NET concepts and APIs that are used for lists and dictionaries in general .NET programming. + +1. The interface indicates a list collection. + +2. The interface indicates a dictionary collection. + +3. represents an array, and an array supports methods. + +In each of these collection concepts, a .NET XAML Services XAML processor expects to call the `Add` method on a specific instance of the collection property's type. Or, in a serialization scenario, a XAML processor produces discrete XAML-type instances for each item found in the list, dictionary, or array based on each collection's specific concept of "Items". These items are: ; ; the explicit for . + +## Generic Collections + +Generic collections can be useful for general .NET programming, and can also be used for XAML collection properties. However, the generic interfaces and are not identified by .NET XAML Services XAML processors as being equivalent to the non-generic or . Rather than implementing the interfaces, a recommended approach for generic collection property types is to derive from the classes or . These classes implement the non-generic interfaces and thus include the expected support for XAML collections in the base implementation. + +## Read-Only Collections and Initialization Logic + +In .NET programming, it is a common design pattern to make any property that holds a value of a collection as a read-only collection. This pattern permits the instance that owns the collection property to better control what happens to the collection.. Specifically, the pattern prevents accidental replacement of the entire pre-existing collection by setting the property. In this pattern, any access to the collection by callers should instead be made by calling methods or properties as supported by the collection type and/or the relevant collection interfaces such as . + +Using this pattern implies that any class that exposes a read-only collection property must first initialize that property to hold an empty collection. Typically the initialization is performed as part of the construction behavior for the class. To be useful for XAML, it is important that such logic is always referenced by the parameterless constructor, because XAML generally calls the parameterless constructor prior to processing the properties (collection properties or otherwise). + +## XAML Type System Support and Collections + +Beyond the basic mechanics of parsing XAML and populating or serializing collection properties, the XAML type system as implemented in .NET XAML Services includes several design features that pertain to collections in XAML. + +1. returns true if the XAML type is backed by a type that provides XAML collection support. + +2. and can further identify which collection mode the XAML type supports. For custom XAML processors that are based on .NET XAML Services and the XAML type system but not based on existing implementations, knowing which collection mode is used might be necessary in order to know which method to invoke for collection processing. + +3. Each of the previous property values is potentially influenced by overrides of on a XAML type. diff --git a/dotnet-desktop-guide/xaml-services/default-schema-context.md b/dotnet-desktop-guide/xaml-services/default-schema-context.md new file mode 100644 index 0000000000..4e7fbfb1a2 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/default-schema-context.md @@ -0,0 +1,95 @@ +--- +title: "Default XAML Schema Context and WPF XAML Schema Context" +ms.date: "03/30/2017" +ms.assetid: 04e06a15-09b3-4210-9bdf-9a64c2eccb83 +--- +# Default XAML Schema Context and WPF XAML Schema Context +A XAML schema context is a conceptual entity that qualifies how a XAML production that uses a particular XAML vocabulary interacts with the object writing behavior, including how type mapping resolves, how assemblies are loaded, how certain reader and writer settings are interpreted. This topic describes the features of .NET XAML Services and the associated default XAML schema context, which is based on the CLR type system. This topic also describes the XAML schema context that is used for WPF. + +## Default XAML Schema Context + +.NET XAML Services both implements and uses a default XAML schema context. The default XAML schema context behavior is not always fully visible in the API of the class. However, in many cases the behavior that the default XAML schema context influences is observable through common API of the XAML type system, such as members of or , or through APIs exposed on XAML readers and XAML writers that are using the default XAML schema context. + +You can create a that encapsulates the default behavior by calling the constructor. This explicitly creates the default XAML schema context. The same default XAML schema context is created implicitly, if you initialize a XAML reader or XAML writer using APIs that do not explicitly take a input parameter. + +The default XAML schema context relies on CLR reflection for its type mapping behavior. This includes examining the defining CLR , and related or . Also, CLR attribution on types or members is used in order to fill in the specifics for XAML type or XAML member information that uses the CLR backing type. The default XAML schema context does not require type system extension techniques such as the `Invoker` pattern, because the necessary information is available from the CLR type system. + +For assembly loading logic, the default XAML schema context relies mainly on any assembly values provided in XAML namespace mappings. Also, can hint an assembly to load, for scenarios such as loading internal types. + +## WPF XAML Schema Context + +The WPF XAML schema context is described in this topic because the WPF implementation provides an interesting illustration of the kinds of features that can be introduced by implementing a non-default XAML schema context. Also, the XAML schema context concept is not discussed very much in the WPF documentation that addresses WPF XAML; the behavior that the XAML schema context enables might only be fully understandable if integrated with a discussion of how the default XAML schema context works. The WPF XAML schema context implements the following behavior. + +**Lookup overrides:** WPF has a few content models for XAML where there are XAML content properties that function without being attributed. overrides for WPF implement this behavior. + +**Deferral for WPF expressions:** WPF features several expression classes that defer a value until a runtime context is available. Also, template expansion is a runtime behavior that relies on deferral techniques. + +**Type system lookup optimizations:** WPF has an extensive XAML vocabulary and object model, including base class member definitions that inherit to literally hundreds of WPF-defined classes. Also, WPF itself is spread across several assemblies. WPF optimizes its type lookup using lookup tables and other techniques. This provides performance improvements over the default XAML schema context and its CLR-based type lookup. In cases where types do not exist in a lookup table, the behavior uses XAML schema context techniques that are similar to the default XAML schema context. + +**XamlType and XamlMember extension:** WPF extends property concepts with dependency properties, and event concepts with routed events. To give these concepts greater visibility for XAML processing operations, WPF extends and , and adds internal properties that report dependency property and routed event characteristics. + +### Accessing the WPF XAML Schema Context + +If you are using XAML techniques that are based on the WPF or , the WPF XAML schema context is already in use on those XAML reader and XAML writer implementations. + +If you are using other XAML reader or XAML writer implementations that do not initialize with the WPF XAML schema context, you may be able to get a working WPF XAML schema context from . You can then use this value as initialization for other API that use a . For example, you could call for initialization and pass the WPF XAML schema context. Or you could use the WPF XAML schema context for XAML type system operations. This might include construction initialization of a or , or calling . + +Note that if you access certain aspects of WPF XAML from a pure XAML node stream perspectives, some of the WPF framework capabilities may not have acted yet. For example, WPF templates for controls are not yet applied. Thus if you access a property that at run time might be populated with a full visual tree, you might only see a property value that references a template. The service context provided for WPF markup extensions might also not be accurate if provided from a non-runtime situation, and can result in exceptions when attempting to write an object graph. + +## XAML and Assembly Loading + +Assembly loading for XAML and .NET XAML Services integrates with the CLR-defined concept of . A XAML schema context interprets how to either load assemblies or find types at run time or design time, based on the use of and other factors. The logic is slightly different depending on whether the XAML is loose XAML for a XAML reader, is XAML compiled into a DLL by `XamlBuildTask`, or is BAML generated by WPF's `PresentationBuildTask`. + +The XAML schema context for WPF integrates with the WPF application model, which in turn uses as well as other factors that are WPF implementation details. + +#### XAML reader input (loose XAML) + +01. The XAML schema context iterates through the of the application, looking for an already-loaded assembly that matches all aspects of the name, starting from the most recently loaded assembly. If a match is found, that assembly is used for resolution. + +02. Otherwise, one of the following techniques based on CLR API are used to load an assembly: + + - If the name is qualified in the mapping, call on the qualified name. + + - If the previous step fails, use the short name (and public key token if present) to call . + + - If the name is unqualified in the mapping, call . + +#### XamlBuildTask + +`XamlBuildTask` is used for Windows Communication Foundation (WCF) and Windows Workflow Foundation. + +Note that assembly references through `XamlBuildTask` are always fully qualified. + +1. Call on the qualified name. + +2. If the previous step fails, use the short name (and public key token if present) to call . + +#### BAML (PresentationBuildTask) + +There are two aspects to assembly-loading for BAML: loading the initial assembly that contains the BAML as a component, and loading the type-backing assemblies for any types referenced by the BAML production. + +##### Assembly load for initial markup: + +The reference to the assembly to load the markup from is always unqualified. + +1. The WPF XAML schema context iterates through the of the WPF application, looking for an already-loaded assembly that matches all aspects of the name, starting from the most recently loaded assembly. If a match is found, that assembly is used for resolution. + +2. If the previous step fails, use the short name (and public key token if present) to call . + +##### Assembly references by BAML types: + +Assembly references for types used in the BAML production are always fully qualified, as an output of the build task. + +01. The WPF XAML schema context iterates through the of the WPF application, looking for an already-loaded assembly that matches all aspects of the name, starting from the most recently loaded assembly. If a match is found, that assembly is used for resolution. + +02. Otherwise, one of the following techniques is used to load an assembly: + + - Call on the qualified name. + + - If a short name + public key token combination match the assembly that the BAML was loaded from, use that assembly. + + - Use short name + public key token to call . + +## See also + +- [Understanding XAML Node Stream Structures and Concepts](understanding-xaml-node-stream-structures-and-concepts.md) diff --git a/dotnet-desktop-guide/xaml-services/define-custom-types.md b/dotnet-desktop-guide/xaml-services/define-custom-types.md new file mode 100644 index 0000000000..f685820470 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/define-custom-types.md @@ -0,0 +1,135 @@ +--- +title: "Defining Custom Types for Use with .NET XAML Services" +ms.date: "03/30/2017" +helpviewer_keywords: + - "defining custom types [XAML Services]" +ms.assetid: c2667cbd-2f46-4a7f-9dfc-53696e35e8e4 +--- +# Define custom types for use with .NET XAML Services + +When you define custom types that are business objects or are types that do not have a dependency on specific frameworks, there are certain best practices for XAML you can follow. If you follow these practices, .NET XAML Services and its XAML readers and XAML writers can discover the XAML characteristics of your type and give it appropriate representation in a XAML node stream using the XAML type system. This topic describes best practices for type definitions, member definitions, and CLR attributing of types or members. + +## Constructor Patterns and Type Definitions for XAML + +To be instantiated as an object element in XAML, a custom class must meet the following requirements: + +- The custom class must be public and must expose a parameterless public constructor. (See following section for notes regarding structures.) + +- The custom class must not be a nested class. The extra "dot" in the full-name path makes the class-namespace division ambiguous, and interferes with other XAML features such as attached properties. +If an object can be instantiated as an object element, the created object can fill the property element form of any properties that take the object as their underlying type. + +You can still provide object values for types that do not meet these criteria, if you enable a value converter. For more information, see [Type Converters and Markup Extensions for XAML](type-converters-and-markup-extensions.md). + +### Structures + +Structures are always able to be constructed in XAML, by CLR definition. This is because a CLR compiler implicitly creates a parameterless constructor for a structure. This constructor initializes all property values to their defaults. + +In some cases, the default construction behavior for a structure is not desirable. This might be because the structure is intended to fill values and function conceptually as a union. As a union, the contained values might have mutually exclusive interpretations, and therefore, none of its properties are settable. An example of such a structure in the WPF vocabulary is . Such structures should implement a type converter so that the values can be expressed in attribute form, by using string conventions that create the different interpretations or modes of the structure values. The structure should also expose similar behavior for code construction through a non-parameterless constructor. + +### Interfaces + +Interfaces can be used as underlying types of members. The XAML type system checks the assignable list and expects that the object that is provided as the value can be assigned to the interface. There is no concept of how the interface must be presented as a XAML type as long as a relevant assignable type supports the XAML construction requirements. + +### Factory Methods + +Factory methods are a XAML 2009 feature. They modify the XAML principle that objects must have parameterless constructors. Factory methods are not documented in this article. See [x:FactoryMethod Directive](xfactorymethod-directive.md). + +## Enumerations + +Enumerations have XAML native type conversion behavior. Enumeration constant names specified in XAML are resolved against the underlying enumeration type, and return the enumeration value to a XAML object writer. + +XAML supports a flags-style usage for enumerations with applied. For more information, see [XAML Syntax In Detail](../framework/wpf/advanced/xaml-syntax-in-detail.md). ([XAML Syntax In Detail](../framework/wpf/advanced/xaml-syntax-in-detail.md) is written for the WPF audience, but most of the information in that topic is relevant for XAML that is not specific to a particular implementing framework.) + +## Member Definitions + +Types can define members for XAML usage. It's possible for types to define members that are XAML-usable even if that specific type is not XAML-usable. This is possible because of CLR inheritance. So long as some type that inherits the member supports XAML usage as a type, and the member supports XAML usage for its underlying type or has a native XAML syntax available, that member is XAML-usable. + +### Properties + +If you define properties as a public CLR property using the typical CLR `get` and `set` accessor patterns and language-appropriate keywording, the XAML type system can report the property as a member with appropriate information provided for properties, such as and . + +Specific properties can enable a text syntax by applying . For more information, see [Type Converters and Markup Extensions for XAML](type-converters-and-markup-extensions.md). + +In the absence of a text syntax or native XAML conversion and in the absence of further indirection, such as a markup extension usage, the type of a property ( in the XAML type system) must be able to return an instance to a XAML object writer by treating the target type as a CLR type. + +If using XAML 2009, [x:Reference Markup Extension](xreference-markup-extension.md) can be used to provide values if the previous considerations are not met; however, that is more of a usage issue than a type definition issue. + +### Events + +If you define events as a public CLR event, the XAML type system can report the event as a member with as `true`. Wiring the event handlers is not within the scope of .NET XAML Services capabilities; wiring is left to specific frameworks and implementations. + +### Methods + +Inline code for methods is not a default XAML capability. In most cases, you do not directly reference method members from XAML, and the role of methods in XAML is only to provide support for specific XAML patterns. [x:FactoryMethod Directive](xfactorymethod-directive.md) is an exception. + +### Fields + +CLR design guidelines discourage nonstatic fields. For static fields, you can access static field values only through [x:Static Markup Extension](xstatic-markup-extension.md); in this case you are not doing anything special in the CLR definition to expose a field for [x:Static](xstatic-markup-extension.md) usages. + +## Attachable Members + +Attachable members are exposed to XAML through an accessor method pattern on a defining type. The defining type itself does not need to be XAML-usable as an object. In fact, a common pattern is to declare a service class whose role is to own the attachable member and implement the related behaviors, but serve no other function such as a UI representation. For the following sections, the placeholder *PropertyName* represents the name of your attachable member. That name must be valid in the [XamlName Grammar](xamlname-grammar.md). + +Be cautious of name collisions between these patterns and other methods of a type. If a member exists that matches one of the patterns, it can be interpreted as an attachable member usage pathway by a XAML processor even if that was not your intention. + +#### The GetPropertyName Accessor + +The signature for the `GetPropertyName` accessor must be: + +`public static object GetPropertyName(object target)` + +- The `target` object can be specified as a more specific type in your implementation. You can use this to scope the usage of your attachable member; usages outside your intended scope will throw invalid cast exceptions that are then surfaced by a XAML parse error. The parameter name `target` is not a requirement, but is named `target` by convention in most implementations. + +- The return value can be specified as a more specific type in your implementation. + +To support a enabled text syntax for attribute usage of the attachable member, apply to the `GetPropertyName` accessor. Applying to the `get` instead of the `set` may seem non-intuitive; however, this convention can support the concept of read-only attachable members that are serializable, which is useful in designer scenarios. + +#### The SetPropertyName Accessor + +The signature for the `SetPropertyName` accessor must be: + +`public static void SetPropertyName(object target, object value)` + +- The `target` object can be specified as a more specific type in your implementation, with same logic and consequences as described in the previous section. + +- The `value` object can be specified as a more specific type in your implementation. + +Remember that the value for this method is the input coming from the XAML usage, typically in attribute form. From attribute form there must be value converter support for a text syntax, and you attribute on the `GetPropertyName`s accessor. + +### Attachable Member Stores + +The accessor methods are typically not enough to provide a means to place attachable member values into an object graph, or to retrieve values out of the object graph and serialize them properly. To provide this functionality, the `target` objects in the previous accessor signatures must be capable of storing values. The storage mechanism should be consistent with the attachable member principle that the member is attachable to targets where the attachable member is not in the members list. .NET XAML Services provides an implementation technique for attachable member stores through the APIs and . is used by the XAML writers to discover the store implementation, and should be implemented on the type that is the `target` of the accessors. The static APIs are used within the body of the accessors, and refer to the attachable member by its . + +## XAML-Related CLR Attributes + +Correctly attributing your types, members, and assemblies is important in order to report XAML type system information to .NET XAML Services. Reporting XAML type system information is relevant if either of the following situations apply: + +- You intend your types for use with XAML systems that are directly based on .NET XAML Services XAML readers and XAML writers. +- You define or use a XAML-utilizing framework that's based on those XAML readers and XAML writers. + +For a listing of each XAML-related attribute that's relevant for XAML support of your custom types, see [XAML-Related CLR Attributes for Custom Types and Libraries](clr-attributes-with-custom-types-and-libraries.md). + +## Usage + +Usage of custom types requires that the markup author must map a prefix for the assembly and CLR namespace that contain the custom type. This procedure is not documented in this topic. + +## Access Level + +XAML provides a means to load and instantiate types that have an `internal` access level. This capability is provided so that user code can define its own types, and then instantiate those classes from markup that is also part of the same user code scope. + +An example from WPF is whenever user code defines a that is intended as a way to refactor a UI behavior, but not as part of any possible extension mechanism that might be implied by declaring the supporting class with `public` access level. Such a can be declared with `internal` access if the backing code is compiled into the same assembly from which it is referenced as a XAML type. + +For an application that loads XAML under full trust and uses , loading classes with `internal` access level is always enabled. + +For an application that loads XAML under partial trust, you can control the access level characteristics by using the API. Also, deferral mechanisms (such as the WPF template system) must be able to propagate any access level permissions and preserve them for the eventual run time evaluations; this is handled internally by passing the information. + +### WPF Implementation + +WPF XAML uses a partial-trust access model where if BAML is loaded under partial trust, access is restricted to for the assembly that is the BAML source. For deferral, WPF uses as a mechanism for passing the access level information. + +In WPF XAML terminology, an *internal type* is a type that is defined by the same assembly that also includes the referencing XAML. Such a type can be mapped through a XAML namespace that deliberately omits the assembly= portion of a mapping, for example, `xmlns:local="clr-namespace:WPFApplication1"`. If BAML references an internal type and that type has `internal` access level, this generates a `GeneratedInternalTypeHelper` class for the assembly. If you want to avoid `GeneratedInternalTypeHelper`, you either must use `public` access level, or must factor the relevant class into a separate assembly and make that assembly dependent. + +## See also + +- [XAML-Related CLR Attributes for Custom Types and Libraries](clr-attributes-with-custom-types-and-libraries.md) +- [XAML Services](/dotnet/api/) diff --git a/dotnet-desktop-guide/xaml-services/escape-sequence-markup-extension.md b/dotnet-desktop-guide/xaml-services/escape-sequence-markup-extension.md new file mode 100644 index 0000000000..151cd11a87 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/escape-sequence-markup-extension.md @@ -0,0 +1,60 @@ +--- +title: "{} Escape Sequence - Markup Extension" +ms.date: "03/30/2017" +f1_keywords: + - "{}" +helpviewer_keywords: + - "XAML [XAML Services], quotation mark (\")" + - "{} escape sequence [XAML Services]" + - "XAML [XAML Services], {} escape sequence" + - "XAML [XAML Services], escape sequence" + - "quotation mark (\") [XAML Services]" + - "escape sequence [XAML Services]" +ms.assetid: 3ce3e2ad-a868-43f9-9c98-b29561cb146e +--- +# {} Escape sequence / markup extension + +Provides the XAML escape sequence for attribute values. The escape sequence allows the subsequent values in the attribute to be interpreted as a literal. + +## XAML Attribute Usage + +```xaml + +``` + +## XAML Property Element Usage + +```xaml + + + {} literalValue + + +``` + +## XAML Values + +||| +|-|-| +|*literalValue*|The literal string that follows the escape sequence. Typically this string contains an open or close brace ({ or }).| + +## Remarks + +The escape sequence ({}) is used so that an open brace ({) can be used as a literal character in XAML. + +XAML readers typically use the open brace ({) to denote the entry point of a markup extension; however, they first check the next character to determine whether it is a closing brace (}). Only when the two braces ({}) are adjacent, are they considered an escape sequence. + +If the escape sequence is encountered, the XAML reader should process the remainder of the string as a string. However, if the escape sequence is applied to a member that has a type converter, the string might undergo type conversion when it is interpreted by a XAML writer. + +The escape sequence is not a markup extension and is not backed by a class. However, it is a convention that XAML readers (including custom XAML readers) should respect. + +A quotation mark (") cannot be used as an escape sequence in this manner. If you need to set a quotation mark as a property value for a noncontent property, use property element syntax and place the quotation mark as a string inside the property element, or use an XML character entity. For a content property, the quotation mark can be the entire content. + +The escape sequence ({}) is frequently required when specifying an XML type that must include a namespace qualifier in a location where a XAML markup extension might appear. This location includes the start of a XAML attribute value, and in a markup extension immediately after an equal sign (=). The following example shows escape sequences for an XML namespace that appears at the start of a XAML attribute value. + +[!code-xaml[XLINQExample#StackPanelResources](~/samples/snippets/csharp/VS_Snippets_Wpf/XLinqExample/CSharp/Window1.xaml#stackpanelresources)] + +## See also + +- [Type Converters and Markup Extensions for XAML](type-converters-and-markup-extensions.md) +- [XML Character Entities and XAML](xml-character-entities.md) diff --git a/dotnet-desktop-guide/xaml-services/generics.md b/dotnet-desktop-guide/xaml-services/generics.md new file mode 100644 index 0000000000..bd647750a7 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/generics.md @@ -0,0 +1,48 @@ +--- +title: "Generics in XAML" +ms.date: "03/30/2017" +helpviewer_keywords: + - "generics [XAML Services]" +ms.assetid: 835bfed7-585c-4216-ae67-b674edab8b92 +--- +# Generics in XAML + +.NET XAML Services as implemented in provides support for using generic CLR types. This support includes specifying the constraints of generics as a type argument and enforcing the constraint by calling the appropriate `Add` method for generic collection cases. This topic describes aspects of using and referencing generic types in XAML. + +## x:TypeArguments + +`x:TypeArguments` is a directive defined by the XAML language. When it is used as a member of a XAML type that is backed by a generic type, `x:TypeArguments` passes constraining type arguments of the generic to the backing constructor. For reference syntax that pertains to .NET XAML Services use of `x:TypeArguments`, which includes syntax examples, see [x:TypeArguments Directive](xtypearguments-directive.md). + +Because `x:TypeArguments` takes a string, and has type converter backing, it is typically declared in XAML usage as an attribute. + +In the XAML node stream, the information declared by `x:TypeArguments` can be obtained from at a `StartObject` position in the node stream. The return value of is a list of values. Determination of whether a XAML type represents a generic type can be made by calling . + +## Rules and Syntax Conventions for Generics in XAML + +In XAML, a generic type must always be represented as a constrained generic. An unconstrained generic is never present in the XAML type system or a XAML node stream and cannot be represented in XAML markup. A generic can be referenced within XAML attribute syntax for cases where it is a nested type constraint of a generic being referenced by `x:TypeArguments`, or for cases where `x:Type` supplies a CLR type reference for a generic type. Referencing generics is supported through the class defined by .NET XAML Services. + +The XAML attribute syntax form enabled by alters the typical MSIL / CLR syntax convention that uses angle brackets for types and constraints of generics, and instead substitutes parentheses for the constraint container. For an example, see [x:TypeArguments Directive](xtypearguments-directive.md). + +## Generics and XAML 2009 Features + +If you use XAML 2009 instead of mapping the CLR base types to obtain XAML types for common language primitives, you can use [XAML 2009 built-in types](types-for-primitives.md) as information items in `x:TypeArguments`. For example, you could declare the following (prefix mappings not shown, but `x` is the XAML language XAML namespace for XAML 2009): + +```xaml + +``` + +## Generics Support in WPF + +For XAML 2006 usage when specifically targeting WPF, [x:Class](xclass-directive.md) must also be provided on the same element as `x:TypeArguments`, and that element must be the root element in a XAML document. The root element must map to a generic type with at least one type argument. An example is . + +Possible workarounds to support generic usages include defining a custom markup extension that can return generic types, or providing a wrapping class definition that derives from a generic type but flattens the generic constraint in its own class definition. + +In WPF you can use XAML 2009 features together with `x:TypeArguments`, but only for loose XAML (XAML that is not markup-compiled). Markup-compiled XAML for WPF and the BAML form of XAML do not currently support the XAML 2009 keywords and features. + +Custom workflows in Windows Workflow Foundation for .NET Framework 3.5 do not support generic XAML usage. + +## See also + +- [x:TypeArguments Directive](xtypearguments-directive.md) +- [x:Class Directive](xclass-directive.md) +- [Built-in Types for Common XAML Language Primitives](types-for-primitives.md) diff --git a/dotnet-desktop-guide/xaml-services/index.md b/dotnet-desktop-guide/xaml-services/index.md new file mode 100644 index 0000000000..ff81dd998e --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/index.md @@ -0,0 +1,106 @@ +--- +title: "XAML Services" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML [XAML Services], System.Xaml concepts" + - "XAML Services in WPF [XAML Services]" + - "System.Xaml [XAML Services], conceptual documentation" +ms.assetid: 0e11f386-808c-4eae-9ba6-029ad7ba2211 +--- +# XAML Services + +This topic describes the capabilities of a technology set known as .NET XAML Services. The majority of the services and APIs described are located in the assembly `System.Xaml`. Services include readers and writers, schema classes and schema support, factories, attributing of classes, XAML language intrinsic support, and other XAML language features. + +## About This Documentation + +Conceptual documentation for .NET XAML Services assumes that you have previous experience with the XAML language and how it might apply to a specific framework, for example Windows Presentation Foundation (WPF) or Windows Workflow Foundation, or a specific technology feature area, for example the build customization features in . This documentation does not attempt to explain the basics of XAML as a markup language, XAML syntax terminology, or other introductory material. Instead, this documentation focuses on specifically using .NET XAML Services that are enabled in the System.Xaml assembly library. Most of these APIs are for scenarios of XAML language integration and extensibility. This might include any of the following scenarios: + +- Extending the capabilities of the base XAML readers or XAML writers (processing the XAML node stream directly; deriving your own XAML reader or XAML writer). + +- Defining XAML-usable custom types that do not have specific framework dependencies, and attributing the types to convey their XAML type system characteristics to .NET XAML Services. + +- Hosting XAML readers or XAML writers as a component of an application, such as a visual designer or interactive editor for XAML markup sources. + +- Writing XAML value converters (markup extensions; type converters for custom types). + +- Defining a custom XAML schema context (using alternate assembly-loading techniques for backing type sources; using known-types lookup techniques instead of always reflecting assemblies; using loaded assembly concepts that do not use the common language runtime (CLR) `AppDomain` and its associated security model). + +- Extending the base XAML type system. + +- Using the `Lookup` or `Invoker` techniques to influence the XAML type system and how type backings are evaluated. + +If you are looking for introductory material on XAML as a language, you might try [XAML Overview (WPF)](../net/wpf/fundamentals/xaml.md). That topic discusses XAML for an audience that is new both to Windows Presentation Foundation (WPF) and also to using XAML markup and XAML language features. Another useful document is the introductory material in the [XAML language specification](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +## .NET XAML Services and `System.Xaml` in the .NET Architecture + +.NET XAML Services and the `System.Xaml` assembly define much of what is needed for supporting XAML language features. This includes base classes for XAML readers and XAML writers. The most important feature added to .NET XAML Services that was not present in any of the framework-specific XAML implementations is a type system representation for XAML. The type system representation presents XAML in an object-oriented way that centers on XAML capabilities without taking dependencies on specific capabilities of frameworks. + +The XAML type system is not limited by the markup form or run-time specifics of the XAML origin; nor is it limited by any specific backing type system. The XAML type system includes object representations for types, members, XAML schema contexts, XML-level concepts, and other XAML language concepts or XAML intrinsics. Using or extending the XAML type system makes it possible to derive from classes like XAML readers and XAML writers, and extend the functionality of XAML representations into specific features enabled by a framework, a technology, or an application that consumes or emits XAML. The concept of a XAML schema context enables practical object graph write operations from the combination of a XAML object writer implementation, a technology's backing type system as communicated through assembly information in the context, and the XAML node source. For more information on the XAML schema concept. see [Default XAML Schema Context and WPF XAML Schema Context](default-schema-context.md). + +## XAML Node Streams, XAML Readers, and XAML Writers + +To understand the role that .NET XAML Services plays in the relationship between the XAML language and specific technologies that use XAML as a language, it is helpful to understand the concept of a XAML node stream and how that concept shapes the API and terminology. The XAML node stream is a conceptual intermediate between a XAML language representation and the object graph that the XAML represents or defines. + +- A XAML reader is an entity that processes XAML in some form, and produces a XAML node stream. In the API, a XAML reader is represented by the base class . + +- A XAML writer is an entity that processes a XAML node stream and produces something else. In the API, a XAML writer is represented by the base class . + + The two most common scenarios involving XAML are loading XAML to instantiate an object graph, and saving an object graph from an application or tool and producing a XAML representation (typically in markup form saved as text file). Loading XAML and creating an object graph is often referred to in this documentation as the load path. Saving or serializing an existing object graph to XAML is often referred to in this documentation as the save path. + + The most common type of load path can be described as follows: + +- Start with a XAML representation, in UTF-encoded XML format and saved as a text file. + +- Load that XAML into . is a subclass. + +- The result is a XAML node stream. You can access individual nodes of the XAML node stream using / API. The most typical operation here is to advance through the XAML node stream, processing each node using a "current record" metaphor. + +- Pass the resulting nodes from the XAML node stream to a API. is a subclass. + +- The writes an object graph, one object at a time, in accordance to progress through the source XAML node stream. Object writing is done with the assistance of a XAML schema context and an implementation that can access the assemblies and types of a backing type system and framework. + +- Call at the end of the XAML node stream to obtain the root object of the object graph. + + The most common type of save path can be described as follows: + +- Start with the object graph of an entire application run time, the UI content and state of a run time, or a smaller segment of an overall application's object representation at run time. + +- From a logical start object, such as an application root or document root, load the objects into . is a subclass. + +- The result is a XAML node stream. You can access individual nodes of the XAML node stream using and API. The most typical operation here is to advance through the XAML node stream, processing each node using a "current record" metaphor. + +- Pass the resulting nodes from the XAML node stream to a API. is a subclass. + +- The writes XAML in an XML UTF encoding. You can save this as a text file, as a stream, or in other forms. + +- Call to obtain the final output. + +For more information about XAML node stream concepts, see [Understanding XAML Node Stream Structures and Concepts](understanding-xaml-node-stream-structures-and-concepts.md). + +### The XamlServices Class + +It is not always necessary to deal with a XAML node stream. If you want a basic load path or a basic save path, you can use APIs in the class. + +- Various signatures of implement a load path. You can either load a file or stream, or can load an , or that wrap your XAML input by loading with that reader's APIs. + +- Various signatures of save an object graph and produce output as a stream, file, or / instance. + +- converts XAML by linking a load path and a save path as a single operation. A different schema context or different backing type system could be used for and , which is what influences how the resulting XAML is transformed. + +For more information about how to use , see [XAMLServices Class and Basic XAML Reading or Writing](basic-reading-writing.md). + +## XAML Type System + +The XAML type system provides the APIs that are required to work with a given individual node of a XAML node stream. + + is the representation for an object - what you are processing between a start object node and end object node. + + is the representation for a member of an object - what you are processing between a start member node and end member node. + +APIs such as and and report the relationships between a and . + +The default behavior of the XAML type system as implemented by .NET XAML Services is based on the common language runtime (CLR), and static analysis of CLR types in assemblies by using reflection. Therefore, for a specific CLR type, the default implementation of the XAML type system can expose the XAML schema of that type and its members and report it in terms of the XAML type system. In the default XAML type system, the concept of assignability of types is mapped onto CLR inheritance, and the concepts of instances, value types, and so on, are also mapped to the supporting behaviors and features of the CLR. + +## Reference for XAML Language Features + +To support XAML, .NET XAML Services provides specific implementation of XAML language concepts as defined for the XAML language XAML namespace. These are documented as specific reference pages. The language features are documented from the perspective of how these language features behave when they are processed by a XAML reader or XAML writer that is defined by .NET XAML Services. For more information, see [XAML Namespace (x:) Language Features](namespace-language-features.md). diff --git a/dotnet-desktop-guide/xaml-services/markup-extensions-overview.md b/dotnet-desktop-guide/xaml-services/markup-extensions-overview.md new file mode 100644 index 0000000000..1451ed7a18 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/markup-extensions-overview.md @@ -0,0 +1,161 @@ +--- +title: "Markup Extensions for XAML Overview" +ms.date: "03/30/2017" +helpviewer_keywords: + - "markup extensions [XAML Services], custom" + - "XAML [XAML Services], markup extensions" +ms.assetid: 261b2b11-2dc0-462f-8c66-55b8c9c6e436 +--- +# Overview of markup extensions for XAML + +Markup extensions are a XAML technique for obtaining a value that's not a primitive or a specific XAML type. For attribute usage, markup extensions use the known character sequence of an opening curly brace `{` to enter the markup extension scope, and a closing curly brace `}` to exit. When using .NET XAML Services, you can use some of the predefined XAML language markup extensions from the System.Xaml assembly. You can also subclass from the class, defined in System.Xaml, and define your own markup extensions. Or you can use markup extensions defined by a particular framework if you are already referencing that framework. + +When a markup extension usage is accessed, the XAML object writer can provide services to a custom class through a service connection point in the override. The services can be used to obtain context about the usage, specific capabilities of the object writer, XAML schema context, and so on. + +## XAML-defined markup extensions + +Several markup extensions are implemented by .NET XAML Services for XAML language support. These markup extensions correspond to parts of the specification of XAML as a language. These are typically identifiable by the `x:` prefix in the syntax as seen in common usage. .NET XAML Services implementations for these XAML language elements all derive from the base class. + +> [!NOTE] +> The `x:` prefix is used for the typical XAML namespace mapping of the XAML language namespace, in the root element of a XAML production. For example, the Visual Studio project and page templates for various specific frameworks initiate a XAML file using this `x:` mapping. You could choose a different prefix token in your own XAML namespace mapping, but this documentation will assume the default `x:` mapping as a means of identifying those entities that are a defined part of the XAML language XAML namespace, as opposed to a specific framework's default XAML namespace or other arbitrary CLR or XML namespaces. + +### x:Type + +`x:Type` supplies the object for the named type. This functionality is used most frequently in deferral mechanisms that use underlying CLR type and type derivation as a grouping moniker or identifier. WPF styles and templates, and their usage of `TargetType` properties, are a specific example. For more information, see [x:Type Markup Extension](xtype-markup-extension.md). + +### x:Static + +`x:Static` produces static values from value-type code entities that are not directly the type of a property's value, but can be evaluated to that type. This is useful for specifying values that already exist as well-known constants in a type definition. For more information, see [x:Static Markup Extension](xstatic-markup-extension.md). + +### x:Null + +`x:Null` specifies `null` as a value for a XAML member. Depending on the design of specific types or on larger framework concepts, `null` is not always a default value for a property, or the implied value of an empty string attribute. For more information, see [x:Null Markup Extension](xnull-markup-extension.md). + +### x:Array + +`x:Array` supports creation of general arrays in XAML syntax in cases where the collection support that is provided by base elements and control models is deliberately not used. For more information, see [x:Array Markup Extension](xarray-markup-extension.md). In XAML 2009 specifically, arrays are accessed as language primitives instead of as an extension. For more information, see [XAML 2009 Language Features](xaml-2009-language-features.md). + +### x:Reference + +`x:Reference` is part of XAML 2009, an extension of the original (2006) language set. `x:Reference` represents a reference to another existing object in an object graph. That object is identified by its `x:Name`. For more information, see [x:Reference Markup Extension](xreference-markup-extension.md). + +### Other x: Constructs + +Other `x:` constructs to support XAML language features exist, but these are not implemented as markup extensions. For more information, see [XAML Namespace (x:) Language Features](namespace-language-features.md). + +## The MarkupExtension Base Class + +To define a custom markup extension that can interact with the default implementations of XAML readers and XAML writers in System.Xaml, you derive a class from the abstract class. That class has one method to override, which is . You might also need to define additional constructors to support arguments to the markup extension usage, and matching settable properties. + +Through , a custom markup extension has access to a service context that reports the environment where the markup extension is invoked by a XAML processor. In the load path, this is typically a . In the save path this is typically a . Each report the service context as an internal XAML service provider context class that implements a service provider pattern. For more information about the available services and what they represent, see [Type Converters and Markup Extensions for XAML](type-converters-and-markup-extensions.md). + +Your markup extension class must use a public access level; XAML processors must always be able to instantiate the markup extension's support class in order to use its services. + +## Defining the Support Type for a Custom Markup Extension + +When you use .NET XAML Services or frameworks that build on .NET XAML Services, you have two choices for how to name the markup extension support type. The type name is relevant to how XAML object writers attempt to access and invoke a markup extension support type when they encounter a markup extension usage in XAML. Use one of the following naming strategies: + +- Name the type name to be an exact match to the XAML markup usage token. For example, to support a `{Collate ...}` extension usage, name the support type `Collate`. +- Name the type name to be the usage string token plus the suffix `Extension`. For example, to support a `{Collate ...}` extension usage, name the support type `CollateExtension`. + +The order of lookup is to look for the `Extension`-suffixed class name first and then look for the class name without the `Extension` suffix. + +From the markup usage perspective, including the `Extension` suffix as part of the usage is valid. However, this behaves as if `Extension` is truly part of the class name, and XAML object writers would fail to resolve a markup extension support class for that usage if the support class did not have the `Extension` suffix. + +### The parameterless constructor + +For all markup extension support types, you should expose a public parameterless constructor. A parameterless constructor is required for any case where a XAML object writer instantiates the markup extension from an object element usage. Supporting object element usage is a fair expectation for a markup extension, particularly for serialization. However, you can implement a markup extension without a public constructor if you only intend to support attribute usages of the markup extension. + +If your markup extension usage has no arguments, the parameterless constructor is required to support usage. + +## Constructor Patterns and Positional Arguments for a Custom Markup Extension + +For a markup extension with intended argument usage, the public constructors must correspond to the modes of the intended usage. In other words, if your markup extension is designed to require one positional argument as a valid usage, you should support a public constructor with one input parameter that takes the positional argument. + +For example, suppose the `Collate` markup extension is intended to support only a mode where there is one positional argument that represents its mode, specified as a `CollationMode` enumeration constant. In this case, there should be a constructor with the following form: + +```csharp +public Collate(CollationMode collationMode) {...} +``` + +At a basic level, the arguments passed to a markup extension are a string because they are being forwarded from the markup's attribute values. You can make all of your arguments strings and work with input at that level. However, you do have access to certain processing that occurs before the markup extension arguments are passed to the support class. + +The processing works conceptually as if the markup extension is an object to be created, and then its member values are set. Each specified property to set is evaluated similar to how a specified member can be set on a created object when XAML is parsed. There are two important differences: + +- As noted previously, a markup extension support type does not need to have a parameterless constructor in order to be instantiated in XAML. Its object construction is deferred until its possible arguments in the text syntax are tokenized and evaluated as either positional or named arguments, and the appropriate constructor is called at that time. +- Markup extensions usages can be nested. The innermost markup extension is evaluated first. Therefore, you can assume such a usage and declare one of the construction parameters to be a type that requires a value converter (such as a markup extension) to produce. + +A reliance on such processing was shown in the previous example. .NET XAML Services XAML object writer processes enumeration constant names into enumerated values at a native level. + +Processing text syntax of a markup extension positional parameter can also rely on a type converter that is associated with the type that is in the construction argument. + +The arguments are called positional arguments because the order in which the tokens in the usage is encountered corresponds to the positional order of the constructor parameter to which they are assigned. For example, consider the following constructor signature: + +```csharp +public Collate(CollationMode collationMode, object collateThis) {...} +``` + +A XAML processor expects two positional arguments for this markup extension. If there was a usage `{Collate AlphaUp,{x:Reference circularFile}}`, the `AlphaUp` token is sent to the first parameter and evaluated as a `CollationMode` enumeration named constant. The result of the inner `x:Reference` is sent to the second parameter and evaluated as an object. + +In the XAML specified rules for markup extension syntax and processing, the comma is the delimiter between arguments, whether those arguments are positional arguments or named arguments. + +### Duplicate arity of positional arguments + +If a XAML object writer encounters a markup extension usage with positional arguments, and there are multiple constructor arguments that take that number of arguments (a duplicate arity), that is not necessarily an error. The behavior depends on a customizable XAML schema context setting, . If is `true`, a XAML object writer should not throw an exception only for reasons of duplicate arity. Behavior beyond that point is not strictly defined. The basic design assumption is that the schema context has type information available for the specific parameters and can attempt explicit casts that match the duplicate candidates to see which signature might be the best match. An exception might still be thrown if no signatures can pass the tests that are imposed by that particular schema context that is running on a XAML object writer. + +By default, is `false` in the CLR-based for .NET XAML Services. Thus, the default throws exceptions if it encounters a markup extension usage where there is duplicate arity in the backing type's constructors. + +## Named arguments for a custom markup extension + +Markup extensions as specified by XAML can also use a named arguments form for usage. At the first level of tokenization, the text syntax is divided into arguments. The presence of an equals sign (=) within any argument identifies an argument as a named argument. Such an argument is also tokenized into a name/value pair. The name in this case names a public settable property of the markup extension's support type. If you intend to support named argument usage, you should provide these public settable properties. The properties can be inherited properties as long as they remain public. + +## Accessing Service Provider Context from a Markup Extension Implementation + +The services available are the same for any value converter. The difference is in how each value converter receives the service context. Accessing services and the services available are documented in the topic [Type Converters and Markup Extensions for XAML](type-converters-and-markup-extensions.md). + +## Property element usage of a markup extension + +The scenarios for markup extension usages are often designed around using the markup extension in attribute usage. However, it is also potentially possible to define the backing class to support property element usage. + +To support property element usage of your markup extension, define a public parameterless constructor. This should be an instance constructor not a static constructor. This is required because a XAML processor must generally invoke the parameterless constructor on any object element it processes from markup, and this includes markup extension classes as object elements. For advanced scenarios, you can define non-default construction paths for classes. (For more information, see [x:FactoryMethod Directive](xfactorymethod-directive.md).) However, you should not use these patterns for markup extension purposes because this makes discovery of the usage pattern much more difficult, both for designers and for users of raw markup. + +## Attributing for a custom markup extension + +To support both design environments and certain XAML object writer scenarios, you should attribute a markup extension support type with several CLR attributes. These attributes report the intended markup extension usage. + + reports the information for the object type that returns. By its pure signature, returns . But various consumers might want more precise return type information. This includes: + +- Designers and IDEs, who might be able to provide type-aware support for markup extension usages. +- Advanced implementations of `SetMarkupExtension` handlers on target classes, which might rely on reflection to determine a markup extension's return type instead of branching on specific known implementations by name. + +## Serialization of markup extension usages + +When a XAML object writer processes a markup extension usage and calls , the context for it previously being a markup extension usage persists in the XAML node stream but not in the object graph. In the object graph, only the value is preserved. If you have design scenarios or other reasons for persisting the original markup extension usage into the serialized output, you must design your own infrastructure for tracking the markup extension usages from the load path XAML node stream. You can implement behavior to recreate the elements of the node stream from the load path and play them back to XAML writers for serialization in the save path, substituting for the value in the appropriate position of the node stream. + +## Markup extensions in the XAML node stream + +If you are working with a XAML node stream on the load path, a markup extension usage appears in the node stream as an object. + +If the markup extension usage uses positional arguments, it is represented as a start object with an initialization value. As a rough text representation, the node stream resembles the following: + +`StartObject` ( is the markup extension's definition type, not its return type) + +`StartMember` (name of the is `_InitializationText`) + +`Value` (value is the positional arguments as a string including the intervening delimiters) + +`EndMember` + +`EndObject` + +A markup extension usage with named arguments is represented as an object with members of the relevant names, each set with text string values. + +Actually invoking the `ProvideValue` implementation of a markup extension requires the XAML schema context because that requires type-mapping and creating a markup extension support type instance. This is one reason why markup extension usages are preserved this way in the default .NET XAML Services node streams - the reader part of a load path often does not have the necessary XAML schema context available. + +If you are working with a XAML node stream on the save path, there generally is nothing present in an object graph representation that can inform you that the object to serialize was originally provided by a markup extension usage and a `ProvideValue` result. Scenarios that need to persist markup extension usages for round-tripping while also capturing other changes in the object graph must devise their own techniques for preserving the knowledge of a markup extension usage from the original XAML input. For example, to restore the markup extension usages, you may need to work with the node stream on the save path in order to restore markup extension usages, or perform some type of merge between the original XAML and the round-tripped XAML. Some XAML-implementing frameworks such as WPF use intermediate types (expressions) to help represent cases where markup extension usages provided the values. + +## See also + +- +- [Type Converters and Markup Extensions for XAML](type-converters-and-markup-extensions.md) +- [Markup Extensions and WPF XAML](../framework/wpf/advanced/markup-extensions-and-wpf-xaml.md) diff --git a/dotnet-desktop-guide/xaml-services/namespace-language-features.md b/dotnet-desktop-guide/xaml-services/namespace-language-features.md new file mode 100644 index 0000000000..7549a38818 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/namespace-language-features.md @@ -0,0 +1,36 @@ +--- +title: "XAML Namespace (x:) Language Features" +ms.date: "03/30/2017" +f1_keywords: + - "AutoGeneratedOrientationPage" +helpviewer_keywords: + - "XAML namespace [XAML Services]" + - "XAML [XAML Services], namespaces" +ms.assetid: e1f47225-9996-4fbf-ab86-62d2e955f3fc +--- +# XAML Namespace (x:) Language Features + +## In This Section + +[x:Array Markup Extension](xarray-markup-extension.md) +[x:Class Directive](xclass-directive.md) +[x:ClassModifier Directive](xclassmodifier-directive.md) +[x:Code Intrinsic XAML Type](xcode-intrinsic-xaml-type.md) +[x:FieldModifier Directive](xfieldmodifier-directive.md) +[x:Key Directive](xkey-directive.md) +[x:Member Directive](xmember-directive.md) +[x:Members Directive](xmembers-directive.md) +[x:Name Directive](xname-directive.md) +[x:Null Markup Extension](xnull-markup-extension.md) +[x:Shared Attribute](xshared-attribute.md) +[x:Property Directive](xproperty-directive.md) +[x:Static Markup Extension](xstatic-markup-extension.md) +[x:Subclass Directive](xsubclass-directive.md) +[x:Type Markup Extension](xtype-markup-extension.md) +[x:TypeArguments Directive](xtypearguments-directive.md) +[x:Uid Directive](xuid-directive.md) +[x:XData Intrinsic XAML Type](xdata-intrinsic-xaml-type.md) +[XamlName Grammar](xamlname-grammar.md) +[{} Escape Sequence - Markup Extension](escape-sequence-markup-extension.md) +[xml:lang Handling in XAML](xml-language-handling.md) +[xml:space Handling in XAML](xml-space-handling.md) diff --git a/dotnet-desktop-guide/xaml-services/namespaces.md b/dotnet-desktop-guide/xaml-services/namespaces.md new file mode 100644 index 0000000000..da3bb0f9cf --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/namespaces.md @@ -0,0 +1,62 @@ +--- +title: "XAML Namespaces for .NET XAML Services" +ms.date: "03/30/2017" +ms.assetid: e4f15f13-c420-4c1e-aeab-9b6f50212047 +--- +# XAML Namespaces for .NET XAML Services +A XAML namespace is a concept that expands on the definition of an XML namespace. Similar to an XML namespace, you can define a XAML namespace using an `xmlns` attribute in markup. XAML namespaces are also represented in the XAML node stream and other XAML Services APIs. This topic defines the XAML namespace concept, and describes how XAML namespaces can be defined and are used by XAML schema contexts and other aspects of .NET XAML Services. + +## XML Namespace and XAML Namespace + A XAML namespace is a specialized XML namespace, just as XAML is a specialized form of XML and uses the basic XML form for its markup. In markup, you declare a XAML namespace and its mapping through an `xmlns` attribute applied to an element. The `xmlns` declaration can be made to the same element that the XAML namespace is declared in. A XAML namespace declaration made to an element is valid for that element, all attributes of that element, and all children of that element. Attributes can use a XAML namespace that is not the same as the element that contains the attribute, so long as the attribute name itself references the prefix as part of its attribute name in markup. + + The distinction of a XAML namespace versus an XML namespace is that an XML namespace might be used to reference a schema or simply to differentiate entities. For XAML, the types and members as used in XAML must ultimately be resolved to backing types, and XML schema concepts do not apply well to this capability. The XAML namespace contains information that the XAML schema context must have available in order to perform this type mapping. + +## XAML Namespace Components + The XAML namespace definition has two components: a prefix, and an identifier. Each of these components is present when a XAML namespace is declared in markup, or defined in the XAML type system. + + The prefix can be any string as allowed by the [W3C Namespaces in XML 1.0 specification](https://www.w3.org/TR/REC-xml-names/). By convention, the prefixes are typically short strings, because the prefix is repeated many times in a typical markup file. Certain XAML namespaces that are intended to be used in multiple XAML implementations use particular conventional prefixes. For example, the XAML language XAML namespace is typically mapped using the prefix `x`. You can define a default XAML namespace, where the prefix is not given in the definition but is represented as an empty string if defined or queried by.NET XAML Services API. Typically, the default XAML namespace is deliberately chosen in order to promote a maximized amount of prefix-omitting markup by a XAML-implementing technology and its scenarios and vocabularies. + + The identifier can be any string as allowed by the [W3C Namespaces in XML 1.0 specification](https://www.w3.org/TR/REC-xml-names/). By convention, identifiers for either XML namespaces or XAML namespaces are often given in URI form, typically as a protocol-qualified absolute URI. Often, version information that defines a particular XAML vocabulary is implied as part of the path string. XAML namespaces add an additional identifier convention beyond the XML URI convention. For XAML namespaces, the identifier communicates information that is needed by a XAML schema context in order to resolve the types that are specified as elements under that XAML namespace, or to resolve attributes to members. + + For purposes of communicating information to a XAML schema context, the identifier for a XAML namespace might still be in URI form. However, in this case the URI is also declared as a matching identifier in a particular assembly or list of assemblies. This is done in assemblies by attributing the assembly with . This method of identifying the XAML namespace and supporting a CLR-based type resolution behavior in the attributed assembly is supported by the default XAML schema context in .NET XAML Services. More generally, this convention can be used for cases where the XAML schema context incorporates the CLR or is based on the default XAML schema context, which is necessary in order to read CLR attributes from CLR assemblies. + + XAML namespaces also can be identified by a convention that communicates a CLR namespace and a type-defining assembly. This convention is used in cases where no attribution exists in the assemblies that contain types. This convention is potentially more complex than the URI convention, and also has the potential for ambiguity and duplication, because there are multiple ways of referring to an assembly. + + The most basic form of an identifier that uses the CLR namespace and assembly convention is as follows: + + `clr-namespace:clrnsName; assembly=assemblyShortName` + + `clr-namespace:` and `; assembly=` are literal components of the syntax. + + *clrnsName* is the string name that identifies a CLR namespace. This string name includes any internal dot characters (.) that provide hints about the CLR namespace and its relation to other CLR namespaces. + + *assemblyShortName* is the string name of an assembly that defines types that are useful in XAML. The types to be accessed through the declared XAML namespace are expected to be defined by the assembly and to be declared within the CLR namespace specified by *clrnsName*. This string name typically parallels the information as reported by . + + A more complete definition of the CLR namespace and assembly convention is as follows: + + `clr-namespace:clrnsName; assembly=assemblyName` + + *assemblyName* represents any string that is legal as an input. This string can include culture, public key, or version information (definitions of these concepts are defined in the reference topic for ). COFF format and evidence (as used by other overloads of ) are not relevant for XAML assembly loading purposes; all load information must be presented as a string. + + Specifying a public key for the assembly is a useful technique for XAML security, or for removing possible ambiguity that can exist if assemblies are loaded by simple name, or pre-exist in a cache or application domain. For more information, see [XAML Security Considerations](security-considerations.md). + +## XAML Namespace Declarations in the XAML Services API + In the XAML Services API, a XAML namespace declaration is represented by a object. If you are declaring a XAML namespace in code, you call the constructor. The `ns` and `prefix` parameters are specified as strings, and the input to provide for these parameters corresponds to the definition of XAML namespace identifier and XAML namespace prefix as provided previously in this topic. + + If you are examining XAML namespace information as part of a XAML node stream or through other access to the XAML type system, reports the XAML namespace identifier, and reports the XAML namespace prefix. + + In a XAML node stream, the XAML namespace information can appear as a XAML node that precedes the entity to which it applies. This includes cases where the XAML namespace information precedes the `StartObject` of the XAML root element. For more information, see [Understanding XAML Node Stream Structures and Concepts](understanding-xaml-node-stream-structures-and-concepts.md). + + For many scenarios that use .NET XAML Services API, at least one XAML namespace declaration is expected to exist, and the declaration must either contain or refer to information that is required by a XAML schema context. The XAML namespaces must either specify assemblies to be loaded, or assist in resolving specific types within namespaces and assemblies that are already loaded or known by the XAML schema context. + + In order to generate a XAML node stream, XAML type information must be available, through the XAML schema context. The XAML type information cannot be determined without first determining the relevant XAML namespace for each node to create. At this point, no instances of types are created yet, but the XAML schema context may need to look up information from the defining assembly and backing type. For example, in order to process the markup ``, the XAML schema context must be able to determine the name and type of the `ContentProperty` of `Party`, and thus also must know the XAML namespace information for `Party` and `PartyFavor`. In the case of the default XAML schema context, static reflection reports much of the XAML type system information that is needed to generate XAML type nodes in the node stream. + + In order to generate an object graph from a XAML node stream, XAML namespace declarations must exist for each XAML prefix used in the original markup and recorded in the XAML node stream. At this point, instances are being created, and true type-mapping behavior occurs. + + If you need to prepopulate XAML namespace information, in cases where the XAML namespace you intend the XAML schema context to use is not defined in the markup, one technique you can use is to declare XML namespace declarations in the for an . Then use that as input for a XAML reader constructor, or . + + Two other APIs that are relevant for XAML namespace handling in .NET XAML Services are the attributes and . These attributes apply to assemblies. is used by a XAML schema context to interpret any XAML namespace declaration that includes a URI. is used by tools that emit XAML so that a particular XAML namespace can be serialized with a predictable prefix. For more information, see [XAML-Related CLR Attributes for Custom Types and Libraries](clr-attributes-with-custom-types-and-libraries.md). + +## See also + +- [Understanding XAML Node Stream Structures and Concepts](understanding-xaml-node-stream-structures-and-concepts.md) diff --git a/dotnet-desktop-guide/xaml-services/security-considerations.md b/dotnet-desktop-guide/xaml-services/security-considerations.md new file mode 100644 index 0000000000..c0fc34a359 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/security-considerations.md @@ -0,0 +1,45 @@ +--- +title: "XAML Security Considerations" +ms.date: "03/30/2017" +helpviewer_keywords: + - "security [XAML Services], .NET XAML services" + - "XAML security [XAML Services]" +ms.assetid: 544296d4-f38e-4498-af49-c9f4dad28964 +--- +# XAML security considerations + +This article describes best practices for security in applications when you use XAML and .NET XAML Services API. + +## Untrusted XAML in Applications + +In the most general sense, untrusted XAML is any XAML source that your application did not specifically include or emit. + +XAML that is compiled into or stored as a `resx`-type resource within a trusted and signed assembly is not inherently untrusted. You can trust the XAML as much as you trust the assembly as a whole. In most cases, you are only concerned with the trust aspects of loose XAML, which is a XAML source that you load from a stream or other I/O. Loose XAML is not a specific component or feature of an application model with a deployment and packaging infrastructure. However, an assembly might implement a behavior that involves loading loose XAML. + +For untrusted XAML, you should treat it generally the same as if it were untrusted code. Use sandboxing or other metaphors to prevent possibly untrusted XAML from accessing your trusted code. + +The nature of XAML capabilities gives the XAML the right to construct objects and set their properties. These capabilities also include accessing type converters, mapping and accessing assemblies in the application domain, using markup extensions, `x:Code` blocks, and so on. + +In addition to its language-level capabilities, XAML is used for UI definition in many technologies. Loading untrusted XAML might mean loading a malicious spoofing UI. + +## Sharing Context Between Readers and Writers + +.NET XAML Services architecture for XAML readers and XAML writers often requires sharing a XAML reader to a XAML writer, or a shared XAML schema context. Sharing objects or contexts might be required if you are writing XAML node loop logic, or providing a custom save path. Don't share XAML reader instances, nondefault XAML schema context, or settings for XAML reader/writer classes between trusted and untrusted code. + +Most scenarios and operations involving XAML object writing for a CLR-based type backing can just use default XAML schema context. The default XAML schema context does not explicitly include settings that could compromise full trust. It is thus safe to share context between trusted and untrusted XAML reader/writer components. However, if you do this, it is still a best practice to keep such readers and writers in separate scopes, with one of them specifically intended/sandboxed for partial trust. + +## XAML Namespaces and Assembly Trust + +The basic unqualified syntax and definition for how XAML interprets a custom XAML namespace mapping to an assembly does not distinguish between a trusted and untrusted assembly as loaded into the application domain. Thus, it is technically possible for an untrusted assembly to spoof a trusted assembly's intended XAML namespace mapping and capture a XAML source's declared object and property information. If you have security requirements to avoid this situation, your intended XAML namespace mapping should be made using one of the following techniques: + +- Use a fully qualified assembly name with strong name in any XAML namespace mapping made by your application's XAML. + +- Restrict assembly mapping to a fixed set of reference assemblies, by constructing a specific for your XAML readers and XAML object writers. See . + +## XAML Type Mapping and Type System Access + +XAML supports its own type system, which in many ways is a peer to how CLR implements the basic CLR type system. However, for certain aspects of type awareness where you are making trust decisions about a type based on its type information, you should defer to the type information in the CLR backing types. This is because some of the specific reporting capabilities of the XAML type system are left open as virtual methods and are therefore, not fully under the control of the original .NET XAML Services implementations. These extensibility points exist because the XAML type system is extensible, to match the extensibility of XAML itself and its possible alternative type-mapping strategies versus the default CLR-backed implementation and default XAML schema context. For more information, see the specific notes on several of the properties of and . + +## See also + +- diff --git a/dotnet-desktop-guide/xaml-services/service-contexts-with-type-converters-and-markup-extensions.md b/dotnet-desktop-guide/xaml-services/service-contexts-with-type-converters-and-markup-extensions.md new file mode 100644 index 0000000000..64ff6fe5de --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/service-contexts-with-type-converters-and-markup-extensions.md @@ -0,0 +1,200 @@ +--- +title: "Service Contexts Available to Type Converters and Markup Extensions" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML [XAML Services], type converter services how-to" +ms.assetid: b4dad00f-03da-4579-a4e9-d8d72d2ccbce +--- +# Service Contexts Available to Type Converters and Markup Extensions +Authors of the types that support type converter and markup extension usages must often have contextual information about where a usage is located in the markup, or in surrounding object graph structure. Information might be needed so that the provided object is instantiated correctly or so that object references to existing objects in the object graph can be made. When using .NET XAML Services, the context that might be required is exposed as a series of service interfaces. Type converter or markup extension support code can query for a service by using a service provider context that is available and passed through from or related types. The XAML schema context is directly available through one such service. This topic describes how to access service contexts from a value converter implementation, and lists typically available services and their roles. + +## Obtaining Services + +As an implementer of a value converter, you often need access to some type of context in which the value converter is applied. This context might include information such as the active XAML schema context, access to the type-mapping system that the XAML schema context and XAML object writer provide, and so on. The services available for a markup extension or type converter implementation are communicated through the context parameters that are part of the signature of each virtual method. In every case, you have implemented in the context, and can call to request a service. + +## Services for a Markup Extension + + has only one virtual method, . The input `serviceProvider` parameter is how the services are communicated to implementations when the markup extension is called by a XAML processor. The following pseudocode illustrates how a markup extension implementation might query for services in its : + +```csharp +public override object ProvideValue(IServiceProvider serviceProvider) +{ +... + // Get the IXamlTypeResolver from the service provider + if (serviceProvider == null) + { + throw new ArgumentNullException("serviceProvider"); + } + IXamlTypeResolver xamlTypeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver; + if (xamlTypeResolver == null) + { + throw new ArgumentException("IXamlTypeResolver")); + } +... +} +``` + +## Services for a Type Converter + + has four virtual methods that use a service context and that support XAML usages. Each of these methods passes an input `context` parameter. This parameter is of type , but that interface inherits , and therefore, there is a method available to type converter implementations. + +The following pseudocode illustrates how a type converter implementation for XAML usages might query for services in one of its overrides, in this case : + +```csharp +public override object ConvertFrom(ITypeDescriptorContext typeDescriptorContext, + CultureInfo cultureInfo, + object source) +{ + IRootObjectProvider rootProvider = typeDescriptorContext.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider; + if (rootProvider != null && source is String) + { + //return something, else ... + } + throw GetConvertFromException(source); +} +``` + +## Services for a Value Serializer + +For value serializer context, you use a service provider type that is specific to the class, . That context is passed to overrides of the four virtual methods. Call from the context to obtain services. + +## Using the XAML Service Provider Contexts + +The service provider for access to XAML services available to markup extensions or type converters is implemented as an internal class, with exposure only through the interface and how it is passed into the relevant context. Whenever a XAML processing operation in the default .NET XAML Services implementations of load path or save path invokes the relevant markup extension or type converter methods that require a service context, this internal object is passed. Depending on the circumstance, the system service context provides either `MarkupExtensionContext` or `TextSyntaxContext`, but the specifics of both of these classes are internal. Your interaction with these classes is limited to requesting services from them, through . + +## Available Services from the .NET XAML Service Context + +.NET XAML Services defines services for markup extensions, type converters, value serializers, and potentially other usages. The following sections describe each of these services and provide guidance about how the service might be used in an implementation. + +### IServiceProvider + +**Reference documentation**: + +**Relevant to:** Basic operation of a service-based infrastructure in .NET so that you can call . + +### ITypeDescriptorContext + +**Reference documentation**: + +Derives from . This class represents context in the standard signatures; is a class that has existed since .NET Framework 1.0. It predates XAML and the XAML scenario for string-value type conversion. In .NET XAML Services context, methods of are implemented explicitly. The explicit implementation's behavior indicates to callers that the API is not relevant for XAML type systems, or for reading or writing objects from XAML. , , and generally return `null` from .NET XAML Services contexts. + +### IValueSerializerContext + +**Reference documentation**: + +Derives from and also relies on explicit implementations to suppress false implications about the XAML type system. Supports the static lookup helper methods on . + +### IXamlTypeResolver + +**Reference documentation**: + +**Defined by:** namespace, System.Xaml assembly + +**Relevant to:** Load path scenarios, and interaction with XAML schema context + +**Service API:** + +Can influence the XAML-to-CLR type mapping that is necessary when the XAML writer constructs a CLR object in an object graph. processes a potentially prefix-qualified string that corresponds to a XAML type name (), and returns a CLR . Resolving types is typically heavily dependent on XAML schema context. Only the XAML schema context is aware of considerations such as which assemblies are loaded, and which of these assemblies can or should be accessed for type resolution. + +### IUriContext + +**Reference documentation**: + +**Defined by:** namespace, System.Xaml assembly + +**Relevant to:** Load path and save path handling of member values that are URIs or `x:Uri` values. + +**Service API:** + +This service reports a globally available URI root, if any. The URI root can be used to resolve relative URIs to absolute URIs or vice versa. This scenario is mainly relevant to application services that are exposed by a particular framework, or capabilities of a frequently used root element class in a framework. The base URI can be established as a XAML reader setting, which is then passed through to the XAML object writer and reported by this service. + +### IAmbientProvider + +**Reference documentation**: + +**Defined by:** namespace, System.Xaml assembly + +**Relevant to:** Load path handling and type lookup deferrals or optimizations. + +**Service APIs:** , three others. + +The ambience concept in XAML is a technique for marking a particular member of a type as ambient. Alternatively, a type can be ambient so that all property values that hold an instance of the type should be considered ambient properties. Markup extensions or type converters that are further along the XAML node stream and that are descendants in the object graph can access the ambient property or type instance at load time; or they can use knowledge of the ambient structure at save time. This can affect the degree of qualification that is needed to resolve types for other services, such as for or for `x:Type`. See also . + +### IXamlSchemaContextProvider + +**Reference documentation**: + +**Defined by:** namespace, System.Xaml assembly + +**Relevant to:** Load path, and any operation that must resolve a XAML type to a backing type. + +**Service API:** + +XAML schema context is necessary for any defer load operations, because the same schema context must act on the deferred area in order to integrate the deferred content. For more information about the role of the XAML schema context, see [XAML Services](/dotnet/api/). + +### IRootObjectProvider + +**Reference documentation**: + +**Defined by:** namespace, System.Xaml assembly + +**Relevant to:** Load path. + +**Service API:** + +The service is relevant to application services that are exposed by a particular framework or by capabilities of a frequently used root element class in a framework. One scenario for obtaining the root object is connecting code-behind and event wiring. For example, the WPF implementation of `x:Class` is used for markup compile and wiring of any event handler attribute that is found at any other position in the XAML markup. The connection point of markup and code-behind defined partial classes for markup compile is at the root element. + +### IXamlNamespaceResolver + +**Reference documentation**: + +**Defined by:** namespace, System.Xaml assembly + +**Relevant to:** Load path, save path. + +**Service API:** for load path, for save path. + + is a service that can return a XAML namespace identifier / URI based on its prefix as mapped in the originating XAML markup. + +### IProvideValueTarget + +**Reference documentation**: + +**Defined by:** namespace, System.Xaml assembly + +**Relevant to:** Load path and save path. + +**Service APIs:** , . + + enables a type converter or markup extension to obtain context about where it is acting at load time. Implementations might use this context to invalidate a usage. For example, WPF has logic inside some of its markup extensions such as . The logic checks the to make sure that the extension is only used to set dependency properties (or a short list of other non-dependency properties). + +### IXamlNameResolver + +**Reference documentation**: + +**Defined by:** namespace, System.Xaml assembly + +**Relevant to:** Load path object graph definition, resolving objects identified by `x:Name`, `x:Reference`, or framework-specific techniques. + +**Service APIs:** ; other APIs for more advanced scenarios such as dealing with forward references. + +.NET XAML Services implementation of `x:Reference` handling relies on this service. Specific frameworks or tools that support the framework use this service for `x:Name` handling or equivalent ( attributed) property handling. + +### IDestinationTypeProvider + +**Reference documentation**: + +**Defined by:** namespace, System.Xaml assembly + +**Relevant to:** Load path resolution of indirect CLR type information. + +**Service API:** + +For more information, see . + +## See also + +- +- +- [Markup Extensions for XAML Overview](markup-extensions-overview.md) +- [Type Converters for XAML Overview](type-converters-overview.md) diff --git a/dotnet-desktop-guide/xaml-services/toc.yml b/dotnet-desktop-guide/xaml-services/toc.yml new file mode 100644 index 0000000000..8d1aba30bd --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/toc.yml @@ -0,0 +1,93 @@ +- name: XAML Language Reference + href: index.md + items: + - name: "XAML Namespace (x:) Language Features" + href: namespace-language-features.md + items: + - name: XAML 2009 (not WPF) Language Features + href: xaml-2009-language-features.md + items: + - name: Built-in Types for Common XAML Language Primitives + href: types-for-primitives.md + - name: "x:Arguments Directive" + href: xarguments-directive.md + - name: "x:FactoryMethod Directive" + href: xfactorymethod-directive.md + - name: "x:Reference Markup Extension" + href: xreference-markup-extension.md + - name: "x:Array Markup Extension" + href: xarray-markup-extension.md + - name: "x:Class Directive" + href: xclass-directive.md + - name: "x:ClassModifier Directive" + href: xclassmodifier-directive.md + - name: "x:Code Intrinsic XAML Type" + href: xcode-intrinsic-xaml-type.md + - name: "x:FieldModifier Directive" + href: xfieldmodifier-directive.md + - name: "x:Key Directive" + href: xkey-directive.md + - name: "x:Member Directive" + href: xmember-directive.md + - name: "x:Members Directive" + href: xmembers-directive.md + - name: "x:Name Directive" + href: xname-directive.md + - name: "x:Null Markup Extension" + href: xnull-markup-extension.md + - name: "x:Property Directive" + href: xproperty-directive.md + - name: "x:Shared Attribute" + href: xshared-attribute.md + - name: "x:Static Markup Extension" + href: xstatic-markup-extension.md + - name: "x:Subclass Directive" + href: xsubclass-directive.md + - name: "x:Type Markup Extension" + href: xtype-markup-extension.md + - name: "x:TypeArguments Directive" + href: xtypearguments-directive.md + - name: "x:Uid Directive" + href: xuid-directive.md + - name: "x:XData Intrinsic XAML Type" + href: xdata-intrinsic-xaml-type.md + - name: XamlName Grammar + href: xamlname-grammar.md + - name: "{} Escape Sequence / Markup Extension" + href: escape-sequence-markup-extension.md + - name: "xml:lang Handling in XAML" + href: xml-language-handling.md + - name: "xml:space Handling in XAML" + href: xml-space-handling.md + - name: Understanding XAML Node Stream Structures and Concepts + href: understanding-xaml-node-stream-structures-and-concepts.md + - name: XAMLServices Class and Basic XAML Reading or Writing + href: basic-reading-writing.md + - name: Type Converters and Markup Extensions for XAML + href: type-converters-and-markup-extensions.md + items: + - name: Markup Extensions for XAML Overview + href: markup-extensions-overview.md + - name: Type Converters for XAML Overview + href: type-converters-overview.md + - name: Service Contexts Available to Type Converters and Markup Extensions + href: service-contexts-with-type-converters-and-markup-extensions.md + - name: Generics in XAML + href: generics.md + - name: Defining Custom Types for Use with .NET XAML Services + href: define-custom-types.md + items: + - name: XAML-Related CLR Attributes for Custom Types and Libraries + href: clr-attributes-with-custom-types-and-libraries.md + - name: Collections and Collection Types for XAML + href: collections-and-types.md + - name: XAML Namespaces + href: namespaces.md + - name: Default XAML Schema Context and WPF XAML Schema Context + href: default-schema-context.md + - name: XAML Security Considerations + href: security-considerations.md + - name: White-space processing in XAML + href: white-space-processing.md + - name: XML Character Entities and XAML + href: xml-character-entities.md diff --git a/dotnet-desktop-guide/xaml-services/type-converters-and-markup-extensions.md b/dotnet-desktop-guide/xaml-services/type-converters-and-markup-extensions.md new file mode 100644 index 0000000000..960533f12e --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/type-converters-and-markup-extensions.md @@ -0,0 +1,66 @@ +--- +title: "Type Converters and Markup Extensions for XAML" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML [XAML Services], type converter services" + - "XAML [XAML Services], value converters" + - "XAML [XAML Services], markup extension services" + - "value converters for XAML [XAML Services]" + - "XAML [XAML Services], service context" +ms.assetid: db07a952-05ce-4aa4-b6f9-aac7397d0326 +--- +# Type Converters and Markup Extensions for XAML + +Type converters and markup extensions are two techniques that XAML type systems and XAML writers use to generate object graph components. Although they share some characteristics, type converters and markup extensions are represented differently in a XAML node stream. In this documentation set, type converters, markup extensions, and similar constructs are sometimes collectively referred to as value converters. + +## Value Converters + +In XAML, value converters are used for various scenarios. The following list shows the different types of value converters in XAML: + +- Type converter + +- Markup extension + +- Value serializer + +- Related class or support class that provides the logic for a XAML text syntax + +## Type Converters + +In .NET XAML Services definition, type converters are classes that derive from the CLR class. is a class that was in the .NET before XAML existed. Its original purpose was to support property windows and similar text-based editing metaphors for IDE properties. The introduction of XAML to .NET uses to convert a text syntax (as found in an attribute value or a XAML value node) into an object. can also be used to serialize an object value to text syntax. was also used in previous framework-specific XAML implementations in Windows Presentation Foundation (WPF) and Windows Communication Foundation (WCF). For more information about the in XAML, see [Type Converters for XAML Overview](type-converters-overview.md). + +## Markup Extensions + +In .NET XAML Services implementation, markup extensions are classes that derive from the class. Markup extensions are a concept that in this form is originated by the XAML language. You can think of a markup extension as being something like an extensible escape sequence that calls into a service class to provide its logic. In terms of markup, XAML processors universally recognize a markup extension by a text sequence that starts with an opening brace ({) in a text string. + +Markup extensions differ from type converters. Type converters are typically associated with types or members. They are invoked when an object graph creation or a serialization encounters text syntax that is associated with those entities. + +Markup extensions are associated with a single supporting service class, but can be applied for any member value. (However, you can implement your markup extension to deliberately restrict its use to certain members or destination types, by using service context.) Markup extensions can override a type converter association. Or you can use them to specify an attribute value for members that would not otherwise support a text syntax. + +For more information about the markup extension implementation pattern for XAML, see [Markup Extensions for XAML Overview](markup-extensions-overview.md). + +## Value Serializers + +A is a specialized type converter that is optimized for converting an object to a string. A for XAML might not implement the `ConvertFrom` method at all. A implementation obtains services in a manner that is like a implementation. The virtual methods provide an input `context` parameter. The `context` parameter is of type , which inherits from the interface and has a method. + +In the XAML type system and for XAML writer implementations that use XAML node loop processing for serialization, a value converter that is associated with a type or member is reported by its own property. The meaning to XAML writers that perform serialization is that if a and exist, the type converter should be used for the load path and the value serializer should be used for the save path. If exists but is `null`, the type converter is also used for the save path. + +## Other Value Converters + +A value converter is extensible beyond the specific patterns of a type converter or a markup extension. However, this customization would also require the redefinition of the XAML type system as provided by .NET XAML Services. The existing XAML type system has representations and reporting systems for type converters, markup extensions, and value serializers, but not for custom forms of value conversion. If you want to create custom value converters, use the type. + +## Type Converters and Markup Extensions in Combination + +Markup extensions and type converters are used for different situations in XAML. Although context is available for markup extension usages, type conversion behavior of properties where a markup extension provides a value is generally is not checked in the markup extension implementations. In other words, even if a markup extension returns a text string as its `ProvideValue` output, type conversion behavior on that string as applied to a specific property or property value type is not invoked. Generally, the purpose of a markup extension is to process a string and return an object without any type converter involved. + +## Service Context for a Value Converter + +When you implement a value converter, you often need access to a context in which the value converter is applied. This context is known as the service context. The service context might include information such as the active XAML schema context, access to the type-mapping system that the XAML schema context and XAML object writer provide, and so on. For more information about the service contexts available for a value converter and how to access the services that a service context might provide, see [Service Contexts Available to Type Converters and Markup Extensions](service-contexts-with-type-converters-and-markup-extensions.md). + +## See also + +- +- +- [Markup Extensions for XAML Overview](markup-extensions-overview.md) +- [Type Converters for XAML Overview](type-converters-overview.md) +- [Service Contexts Available to Type Converters and Markup Extensions](service-contexts-with-type-converters-and-markup-extensions.md) diff --git a/dotnet-desktop-guide/xaml-services/type-converters-overview.md b/dotnet-desktop-guide/xaml-services/type-converters-overview.md new file mode 100644 index 0000000000..40539e94fb --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/type-converters-overview.md @@ -0,0 +1,118 @@ +--- +title: "Type Converters for XAML Overview" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML [XAML Services], type converters" + - "XAML [XAML Services], TypeConverter" + - "type conversion for XAML [XAML Services]" +ms.assetid: 51a65860-efcb-4fe0-95a0-1c679cde66b7 +--- +# Overview of type converters for XAML + +Type converters supply logic for an object writer that converts from a string in XAML markup into particular objects in an object graph. In .NET XAML Services, the type converter must be a class that derives from . Some converters also support the XAML save path and can be used to serialize an object into a string form in serialization markup. This topic describes how and when type converters in XAML are invoked, and provides implementation advice for the method overrides of . + +## Type Conversion Concepts + +The following sections explain basic concepts about how XAML uses strings, and how object writers in .NET XAML Services use type converters to process some of the string values that are encountered in a XAML source. + +### XAML and String Values + +When you set an attribute value in a XAML file, the initial type of that value is a string in a general sense, and a string attribute value in an XML sense. Even other primitives such as are initially strings to a XAML processor. + +In most cases, a XAML processor needs two pieces of information to process an attribute value. The first piece of information is the value type of the property that is being set. Any string that defines an attribute value and that is processed in XAML must ultimately be converted or resolved to a value of that type. If the value is a primitive that is understood by the XAML parser (such as a numeric value), a direct conversion of the string is attempted. If the value for the attribute references an enumeration, the supplied string is checked for a name match to a named constant in that enumeration. If the value is not a parser-understood primitive or a constant name from an enumeration, the applicable type must be able to provide a value or reference that is based on a converted string. + +> [!NOTE] +> XAML language directives do not use type converters. + +### Type Converters and Markup Extensions + +Markup extension usages must be handled by a XAML processor before it checks for property type and other considerations. For example, if a property being set as an attribute normally has a type conversion, but in a particular case is set by a markup extension usage, then the markup extension behavior processes first. One common situation where a markup extension is necessary is to make a reference to an object that already exists. For this scenario, a stateless type converter can only generate a new instance, which might not be desirable. For more information about markup extensions, see [Markup Extensions for XAML Overview](markup-extensions-overview.md). + +### Native Type Converters + +In the Windows Presentation Foundation (WPF) and .NET XAML services implementations, there are certain CLR types that have native type conversion handling. However, those CLR types are not conventionally thought of as primitives. An example of such a type is . One reason for this is how the .NET Framework architecture works: the type is defined in mscorlib, the most basic library in .NET. is not permitted to be attributed with an attribute that comes from another assembly that introduces a dependency ( is from System). Therefore, the usual type converter discovery mechanism by attributing cannot be supported. Instead, the XAML parser has a list of types that need native processing, and it processes these types similar to how the true primitives are processed. In the case of , this processing involves a call to . + +## Implementing a Type Converter + +The following sections discuss the API of the class. + +### TypeConverter + +Under .NET XAML Services, all type converters that are used for XAML purposes are classes that derive from the base class . The class existed in versions of the .NET Framework before XAML existed; one of the original scenarios was to provide string conversion for property editors in visual designers. + +For XAML, the role of is expanded. For XAML purposes, is the base class for providing support for certain to-string and from-string conversions. From-string enables parsing a string attribute value from XAML. To-string might enable processing a run-time value of a particular object property back into an attribute in XAML for serialization. + + defines four members that are relevant for converting to-string and from-string for XAML processing purposes: + +- + +- + +- + +- + +Of these members, the most important method is , which converts the input string to the required object type. The method can be implemented to convert a wider range of types into the intended destination type of the converter. Therefore, it can serve purposes that extend beyond XAML, such as supporting run-time conversions. However, for XAML use, only the code path that can process a input is important. + +The second-most important method is . If an application is converted to a markup representation (for example, if it is saved to XAML as a file), is involved in the larger scenario of a XAML text writer to produce a markup representation. In this case, the important code path for XAML is when the caller passes a `destinationType` of . + + and are support methods that are used when a service queries the capabilities of the implementation. You must implement these methods to return `true` for type-specific cases that the equivalent conversion methods of your converter support. For XAML purposes, this generally means the type. + +### Culture Information and Type Converters for XAML + +Each implementation can uniquely interpret what is a valid string for a conversion, and it can also use or ignore the type description that is passed as parameters. An important consideration for culture and XAML type conversion is the following: although using localizable strings as attribute values is supported by XAML, you cannot use these localizable strings as type converter input with specific culture requirements. This limitation is because type converters for XAML attribute values involve a necessarily fixed-language XAML-processing behavior that uses `en-US` culture. For more information about the design reasons for this restriction, see the XAML language specification ([\[MS-XAML\]](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10))) or [WPF Globalization and Localization Overview](../framework/wpf/advanced/wpf-globalization-and-localization-overview.md). + +As an example where culture can be an issue, some cultures use a comma instead of a period as the decimal point delimiter for numbers in string form. This use collides with the behavior that many existing type converters have, which is to use a comma as a delimiter. Passing a culture through `xml:lang` in the surrounding XAML does not solve the issue. + +### Implementing ConvertFrom + +To be usable as a implementation that supports XAML, the method for that converter must accept a string as the `value` parameter. If the string is in a valid format and can be converted by the implementation, the returned object must support a cast to the type that is expected by the property. Otherwise, the implementation must return `null`. + +Each implementation can uniquely interpret what constitutes a valid string for a conversion, and it can also use or ignore the type description or culture contexts that are passed as parameters. However, the WPF XAML processing might not pass values to the type description context in all cases and also might not pass culture based on `xml:lang`. + +> [!NOTE] +> Do not use the braces ({}), specifically the opening brace ({), as an element of your string format. These characters are reserved as the entry and exit for a markup extension sequence. + +It is appropriate to throw an exception when your type converter must have access to a XAML service from .NET XAML Services object writer, but the call that is made against the context does not return that service. + +### Implementing ConvertTo + + is potentially used for serialization support. Serialization support through for your custom type and its type converter is not an absolute requirement. However, if you are implementing a control, or using serialization of as part of the features or design of your class, you should implement . + +To be usable as a implementation that supports XAML, the method for that converter must accept an instance of the type (or a value) that is supported as the `value` parameter. When the `destinationType` parameter is of type , the returned object must be able to be cast as . The returned string must represent a serialized value of `value`. Ideally, the serialization format that you choose should be able to generate the same value as if that string were passed to the implementation of the same converter, without significant loss of information. + +If the value cannot be serialized or the converter does not support serialization, the implementation must return `null` and can throw an exception. However, if you do throw exceptions, you should report the inability to use that conversion as part of your implementation so that the best practice of checking with first to avoid exceptions is supported. + +If the `destinationType` parameter is not of type , you can choose your own converter handling. Typically, you revert to base implementation handling, which in the base raises a specific exception. + +It is appropriate to throw an exception when your type converter must have access to a XAML service from .NET XAML Services object writer, but the call that is made against the context does not return that service. + +### Implementing CanConvertFrom + +Your implementation should return `true` for `sourceType` of type and otherwise, defer to the base implementation. Do not throw exceptions from . + +### Implementing CanConvertTo + +Your implementation should return `true` for `destinationType` of type , and otherwise defer to the base implementation. Do not throw exceptions from . + +## Applying the TypeConverterAttribute + +For your custom type converter to be used as the acting type converter for a custom class by .NET XAML Services, you must apply the to your class definition. The that you specify through the attribute must be the type name of your custom type converter. If you apply this attribute, when a XAML processor handles values where the property type uses your custom class type, it can input strings and return object instances. + +You can also provide a type converter on a per-property basis. Instead of applying a to the class definition, apply it to a property definition (the main definition, not the `get`/`set` implementations within it). The type of the property must match the type that is processed by your custom type converter. With this attribute applied, when a XAML processor handles values of that property, it can process input strings and return object instances. The per-property type converter technique is useful if you choose to use a property type from Microsoft .NET Framework or from some other library where you cannot control the class definition and cannot apply a there. + +To supply a type conversion behavior for a custom attached member, apply to the `Get` accessor method of the implementation pattern for the attached member. + +## Accessing Service Provider Context from a Markup Extension Implementation + +The available services are the same for any value converter. The difference is in how each value converter receives the service context. Accessing services and the services available are documented in the topic [Type Converters and Markup Extensions for XAML](type-converters-and-markup-extensions.md). + +## Type Converters in the XAML Node Stream + +If you are working with a XAML node stream, the action or end result of a type converter is not yet executed. In a load path, the attribute string that eventually needs to be type-converted in order to load remains as a text value within a start member and end member. The type converter that is eventually needed for this operation can be determined by using the property. However, obtaining a valid value from relies on having a XAML schema context, which can access such information through the underlying member, or the type of the object value that the member uses. Invoking the type conversion behavior also requires the XAML schema context because that requires type-mapping and creating a converter instance. + +## See also + +- +- [Type Converters and Markup Extensions for XAML](type-converters-and-markup-extensions.md) +- [XAML Overview (WPF)](../net/wpf/fundamentals/xaml.md) diff --git a/dotnet-desktop-guide/xaml-services/types-for-primitives.md b/dotnet-desktop-guide/xaml-services/types-for-primitives.md new file mode 100644 index 0000000000..6dc692024d --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/types-for-primitives.md @@ -0,0 +1,145 @@ +--- +title: "Built-in Types for Common XAML Language Primitives" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML language primitives [XAML Services]" + - "XAML [XAML Services], built-in types" + - "x:String [XAML Services]" + - "x:TimeSpan [XAML Services]" + - "x:Byte [XAML Services]" + - "x:Double [XAML Services]" + - "XAML [XAML Services], types" + - "x:Uri [XAML Services]" + - "XAML built-in types [XAML Services]" + - "x:Int64 [XAML Services]" + - "x:Single [XAML Services]" + - "x:Int32 [XAML Services]" +ms.assetid: 11de2f08-5b95-4989-b5ec-5178eb968184 +--- +# Built-in types for common XAML language primitives + +XAML 2009 introduces XAML language-level support for several data types that are frequently used primitives in the common language runtime (CLR) and in other programming languages. XAML 2009 adds support for these primitives: `x:Object`, `x:Boolean`, `x:Char`, `x:String`, `x:Decimal`, `x:Single`, `x:Double`, `x:Int16`, `x:Int32`, `x:Int64`, `x:TimeSpan`, `x:Uri`, `x:Byte`, and `x:Array` + +## Previous Techniques for Language Primitives in XAML Markup + + In XAML for previous WPF versions, you could reference the CLR language primitives by mapping the assembly and namespace that contained a CLR primitive definition class for the .NET Framework. Most of these are in the mscorlib assembly and namespace. For example, to use , you could declare the following mapping (with an example usage shown thereafter): + +```xaml + + + 42 + + +``` + +## XAML 2009 Language Primitives + +By convention, the language primitives for XAML and all other XAML language elements are shown, including the `x:` prefix. This is how XAML language elements are typically used in real-world markup. This convention is followed in the conceptual documentation for XAML in WPF and also in the XAML specification. + +### x:Object + +For CLR backing, the `x:Object` primitive corresponds to . + +This primitive is not typically used in application markup, but might be useful for some scenarios such as checking assignability in a XAML type system. + +### x:Boolean + +For CLR backing, the `x:Boolean` primitive corresponds to . + +XAML parses values for `x:Boolean` as case insensitive. Note that `x:Bool` is not an accepted alternative. For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.17 and 5.4.11](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +### x:Char + +For CLR backing, the `x:Char` primitive corresponds to . + +String and char types have interaction with the overall encoding of the file at the XML level. For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.7 and 5.4.1](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +### x:String + +For CLR backing, the `x:String` primitive corresponds to . + +String and char types have interaction with the overall encoding of the file at the XML level. For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.6](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +### x:Decimal + +For CLR backing, the `x:Decimal` primitive corresponds to . + +XAML parsing is inherently done under `en-US` culture. Under `en-US` culture, the correct separator for the components of a decimal is always a period (`.`) regardless of culture settings of the development environment, or of the eventual client target where the XAML is loaded at run time. + +For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.14 and 5.4.8](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +### x:Single + +For CLR backing, the `x:Single` primitive corresponds to . + +In addition to the numeric values, text syntax for `x:Single` also permits the tokens `Infinity`, `-Infinity`, and `NaN`. These tokens are treated as case sensitive. + +`x:Single` can support values in scientific notation form, if the first character in text syntax is `e` or `E`. + +For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.8 and 5.4.2](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +### x:Double + +For CLR backing, the `x:Double` primitive corresponds to . + +In addition to the numeric values, text syntax for `x:Double` permits the tokens `Infinity`, `-Infinity`, and `NaN`. These tokens are treated as case sensitive. + +`x:Double` can support values in scientific notation form. Use the character `e` or `E` to introduce the exponent portion. + +For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.9 and 5.4.3](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +### x:Int16 + +For CLR backing, the `x:Int16` primitive corresponds to and `x:Int16` is treated as signed. In XAML, the absence of a plus (`+`) sign in text syntax is implied as a positive signed value. + +For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.11 and 5.4.5](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +### x:Int32 + +For CLR backing, the `x:Int32` primitive corresponds to . `x:Int32` is treated as signed. In XAML, the absence of a plus (`+`) sign in text syntax is implied as a positive signed value. + +For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.12 and 5.4.6](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +### x:Int64 + +For CLR backing, the `x:Int64` primitive corresponds to . `x:Int64` is treated as signed. In XAML, the absence of a plus (`+`) sign in text syntax is implied as a positive signed value. + +For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.13 and 5.4.7](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +### x:TimeSpan + +For CLR backing, the `x:TimeSpan` primitive corresponds to . + +XAML parsing for time-date format is inherently done under `en-US` culture. + +For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.16 and 5.4.10](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +### x:Uri + +For CLR backing, the `x:Uri` primitive corresponds to . + +Checking for protocols is not part of the XAML definition for `x:Uri`. + +For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.15 and 5.4.9](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +### x:Byte + +For CLR backing, the `x:Byte` primitive corresponds to . A / `x:Byte` is treated as unsigned. + +For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.10 and 5.4.4](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +### x:Array + +For CLR backing, the `x:Array` primitive corresponds to . + +You can define an array in XAML 2006 by using a markup extension syntax; however, the XAML 2009 syntax is a language-defined primitive that does not require accessing a markup extension. For more information about XAML 2006 support, see [x:Array Markup Extension](xarray-markup-extension.md). + +For the XAML language specification definition, see [\[MS-XAML\] Sections 5.2.18](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +## WPF Support + +In WPF, you can use XAML 2009 features but only for XAML that is not markup-compiled. Markup-compiled XAML for WPF and the BAML form of XAML do not currently support the XAML 2009 keywords and features. + +A scenario where you can use XAML 2009 features together with WPF is if you author loose XAML and you then load that XAML into a WPF runtime and object graph with . The WPF and its can process XAML 2009 language keywords and features into a valid object graph representation. diff --git a/dotnet-desktop-guide/xaml-services/understanding-xaml-node-stream-structures-and-concepts.md b/dotnet-desktop-guide/xaml-services/understanding-xaml-node-stream-structures-and-concepts.md new file mode 100644 index 0000000000..eb508b8962 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/understanding-xaml-node-stream-structures-and-concepts.md @@ -0,0 +1,224 @@ +--- +title: "Understanding XAML Node Stream Structures and Concepts" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML node streams [XAML Services]" + - "nodes [XAML Services], XAML node stream" + - "XAML [XAML Services], XAML node streams" +ms.assetid: 7c11abec-1075-474c-9d9b-778e5dab21c3 +--- +# XAML node stream structures and concepts + +XAML readers and XAML writers as implemented in .NET XAML Services are based on the design concept of a XAML node stream. The XAML node stream is a conceptualization of a set of XAML nodes. In this conceptualization, a XAML processor walks through the structure of the node relationships in the XAML one at a time. At any time, only one current record or current position exists in an open XAML node stream, and many aspects of the API report only the information available from that position. The current node in a XAML node stream can be described as being an object, a member, or a value. By treating XAML as a XAML node stream, XAML readers can communicate with XAML writers and enable a program to view, interact with, or alter the contents of a XAML node stream during either a load path or a save path operation that involves XAML. XAML reader and writer API design and the XAML node stream concept are similar to previous related reader and writer designs and concepts, such as the XML Document Object Model (DOM) and the and classes. This topic discusses XAML node stream concepts and describes how you can write routines that interact with XAML representations at the XAML node level. + +## Loading XAML into a XAML Reader + +The base class does not declare a particular technique for loading the initial XAML into a XAML reader. Instead, a derived class declares and implements the loading technique, including the general characteristics and constraints of its input source for XAML. For example, a reads an object graph, starting from the input source of a single object that represents the root or base. The then produces a XAML node stream from the object graph. + +The most prominent .NET XAML Services–defined subclass is . loads the initial XAML, either by loading a text file directly through a stream or file path, or indirectly through a related reader class such as . The can be thought of as containing the entirety of the XAML input source after it has loaded. However, the base API is designed so that the reader is interacting with a single node of the XAML. When first loaded, the first single node you encounter is the root of the XAML, and its start object. + +### The XAML Node Stream Concept + +If you are more familiar with a DOM, tree metaphor, or query-based approach towards accessing XML-based technologies, a helpful way to conceptualize a XAML node stream is as follows. Imagine that the loaded XAML is a DOM or a tree where every possible node is expanded all the way, and then presented linearly. As you advance through the nodes, you might be traversing "in" or "out" of levels that would be relevant to a DOM, but the XAML node stream does not explicitly keep track because these level concepts are not relevant to a node stream. The node stream has a "current" position, but unless you have stored other parts of the stream yourself as references, every aspect of the node stream other than the current node position is out of view. + +The XAML node stream concept has the notable advantage that if you go through the entire node stream, you are assured that you have processed the entire XAML representation; you do not need to worry that a query, a DOM operation, or some other nonlinear approach to processing information has missed some part of the complete XAML representation. For this reason, the XAML node stream representation is ideal both for connecting XAML readers and XAML writers, and for providing a system where you can insert your own process that acts between the read and write phases of a XAML processing operation. In many cases, the ordering of nodes in the XAML node stream is deliberately optimized or reordered by XAML readers versus how the order might appear in the source text, binary, or object graph. This behavior is intended to enforce a XAML processing architecture whereby XAML writers are never in a position where they have to go "back" in the node stream. Ideally, all XAML write operations should be able to act based on schema context plus the current position of the node stream. + +## A Basic Reading Node Loop + +A basic reading node loop for examining a XAML node stream consists of the following concepts. For purposes of node loops as discussed in this topic, assume that you are reading a text-based, human-readable XAML file using . The links in this section refer to the particular XAML node loop API implemented by . + +- Make sure that you are not at the end of the XAML node stream (check , or use the return value). If you are at the end of the stream, there is no current node and you should exit. + +- Check what type of node the XAML node stream currently exposes by calling . + +- If you have an associated XAML object writer that is connected directly, you generally call at this point. + +- Based on which is reported as the current node or current record, call one of the following to obtain information about the node contents: + + - For a of or , call to obtain information about a member. The member might be a , and thus might not necessarily be a conventional type-defined member of the preceding object. For example, `x:Name` applied to an object appears as a XAML member where is true and the of the member is `Name`, with other properties indicating that this directive is under the XAML language XAML namespace. + + - For a of or , call to obtain information about an object. + + - For a of , call . A node is a value only if it is the simplest expression of a value for a member, or the initialization text for an object (however, you should be aware of type conversion behavior as documented in an upcoming section of this topic). + + - For a of , call to obtain namespace information for a namespace node. + +- Call to advance the XAML reader to the next node in the XAML node stream, and repeat the steps again. + +The XAML node stream provided by .NET XAML Services XAML readers always provides a full, deep traversal of all possible nodes. Typical flow-control techniques for a XAML node loop include defining a body within `while (reader.Read())`, and switching on at each node point in the node loop. + +If the node stream is at end of file, the current node is null. + +The simplest loop that uses a reader and writer resembles the following example. + +```csharp +XamlXmlReader xxr = new XamlXmlReader(new StringReader(xamlStringToLoad)); +//where xamlStringToLoad is a string of well formed XAML +XamlObjectWriter xow = new XamlObjectWriter(xxr.SchemaContext); +while (xxr.Read()) { + xow.WriteNode(xxr); +} +``` + +This basic example of a load path XAML node loop transparently connects the XAML reader and XAML writer, doing nothing different than if you had used . But this basic structure is then expanded to apply to your reading or writing scenario. Some possible scenarios are as follows: + +- Switch on . Perform different actions depending on which node type is being read. + +- Do not call in all cases. Only call in some cases. + +- Within the logic for a particular node type, analyze the specifics of that node and act on them. For example, you could only write objects that come from a particular XAML namespace, and then drop or defer any objects not from that XAML namespace. Or you could drop or otherwise reprocess any XAML directives that your XAML system does not support as part of your member processing. + +- Define a custom that overrides `Write*` methods, possibly performing type mapping that bypasses XAML schema context. + +- Construct the to use a nondefault XAML schema context, so that customized differences in XAML behavior are used both by the reader and the writer. + +### Accessing XAML Beyond the Node Loop Concept + +There are potentially other ways to work with a XAML representation other than as a XAML node loop. For example, there could exist a XAML reader that can read an indexed node, or in particular accesses nodes directly by `x:Name`, by `x:Uid`, or through other identifiers. .NET XAML Services does not provide a full implementation, but provides a suggested pattern through services and support types. For more information, see and . + +## Working with the Current Node + +Most scenarios that use a XAML node loop do not only read the nodes. Most scenarios process current nodes and pass each node one at a time to an implementation of . + +In the typical load path scenario, a produces a XAML node stream; the XAML nodes are processed according to your logic and XAML schema context; and the nodes are passed to a . You then integrate the resulting object graph into your application or framework. + +In a typical save path scenario, a reads the object graph, individual XAML nodes are processed, and a outputs the serialized result as a XAML text file. The key is that both paths and scenarios involve working with exactly one XAML node at a time, and the XAML nodes are available for treatment in a standardized way that is defined by the XAML type system and the.NET XAML Services APIs. + +### Frames and Scope + +A XAML node loop walks through a XAML node stream in a linear way. The node stream traverses into objects, into members that contain other objects, and so on. It is often useful to keep track of scope within the XAML node stream by implementing a frame and stack concept. This is particularly true if you are actively adjusting the node stream while you are in it. The frame and stack support that you implement as part of your node loop logic could count `StartObject` (or `GetObject`) and `EndObject` scopes as you descend into a XAML node structure if the structure is thought of from a DOM perspective. + +## Traversing and Entering Object Nodes + +The first node in a node stream when it is opened by a XAML reader is the start-object node of the root object. By definition, this object is always a single object node and has no peers. In any real-world XAML example, the root object is defined to have one or more properties that hold more objects, and these properties have member nodes. The member nodes then have one or more object nodes, or might also terminate in a value node instead. The root object typically defines XAML namescopes, which are syntactically assigned as attributes in the XAML text markup but map to a `Namescope` node type in the XAML node stream representation. + +Consider the following XAML example (this is arbitrary XAML, not backed by existing types in .NET). Assume that in this object model, `FavorCollection` is `List` of `Favor`, `Balloon` and `NoiseMaker` are assignable to `Favor`, the `Balloon.Color` property is backed by a `Color` object similar to how WPF defines colors as known color names, and `Color` supports a type converter for attribute syntax. + +|XAML markup|Resulting XAML node stream| +|-----------------|--------------------------------| +|``|`StartObject` node for `Party`| +|``|`StartMember` node for `Party.Favors`| +||`StartObject` node for implicit `FavorCollection`| +||`StartMember` node for implicit `FavorCollection` items property.| +|`
`Value` node for the attribute value string `"Red"`

`EndMember` for `Color`| +|`HasHelium="True"`|`StartMember` node for `HasHelium`

`Value` node for the attribute value string `"True"`

`EndMember` for `HasHelium`| +|`>`|`EndObject` for `Balloon`| +|`Loudest`|`StartObject` node for `NoiseMaker`

`StartMember` node for `_Initialization`

`Value` node for the initialization value string `"Loudest"`

`EndMember` node for `_Initialization`

`EndObject` for `NoiseMaker`| +||`EndMember` node for implicit `FavorCollection` items property.| +||`EndObject` node for implicit `FavorCollection`| +|`
`|`EndMember` for `Favors`| +|``|`EndObject` for `Party`| + +In the XAML node stream, you can rely on the following behavior: + +- If a `Namespace` node exists, it is added to the stream immediately before the `StartObject` that declared the XAML namespace with `xmlns`. Look at the previous table with the XAML and example node stream again. Notice how the `StartObject` and `Namespace` nodes seem to be transposed versus their declaration positions in text markup. This is representative of the behavior where the namespace nodes always appear ahead of the node they apply to in the node stream. The purpose of this design is that the namespace information is vital to object writers and must be known before the object writer attempts to perform type mapping or otherwise process the object. Placing the XAML namespace information ahead of its application scope in the stream makes it simpler to always process the node stream in its presented order. + +- Because of the above consideration, it is one or more `Namespace` nodes that you read first in most real-world markup cases when traversing nodes from the start, not the `StartObject` of the root. + +- A `StartObject` node can be followed by `StartMember`, `Value`, or an immediate `EndObject`. It is never followed immediately by another `StartObject`. + +- A `StartMember` can be followed by a `StartObject`, `Value`, or an immediate `EndMember`. It can be followed by `GetObject`, for members where the value is supposed to come from an existing value of the parent object rather than a `StartObject` that would instantiate a new value. It can also be followed by a `Namespace` node, which applies to an upcoming `StartObject`. It is never followed immediately by another `StartMember`. + +- A `Value` node represents the value itself; there is no "EndValue". It can be followed only by an `EndMember`. + + - XAML initialization text of the object as might be used by construction does not result in an Object-Value structure. Instead, a dedicated member node for a member named `_Initialization` is created. and that member node contains the initialization value string. If it exists, `_Initialization` is always the first `StartMember`. `_Initialization` may be qualified in some XAML services representations with the XAML language XAML namescope, to clarify that `_Initialization` is not a defined property in backing types. + + - A Member-Value combination represents an attribute setting of the value. There might eventually be a value converter involved in processing this value, and the value is a plain string. However, that is not evaluated until a XAML object writer processes this node stream. The XAML object writer possesses the necessary XAML schema context, type system mapping, and other support needed for value conversions. + +- An `EndMember` node can be followed by a `StartMember` node for a subsequent member, or by an `EndObject` node for the member owner. + +- An `EndObject` node can be followed by an `EndMember` node. It can also be followed by a `StartObject` node for cases where the objects are peers in a collection's items. Or it can be followed by a `Namespace` node, which applies to an upcoming `StartObject`. + + - For the unique case of closing the entire node stream, the `EndObject` of the root is not followed by anything; the reader is now end-of-file, and returns `false`. + +## Value Converters and the XAML Node Stream + +A value converter is a general term for a markup extension, a type converter (including value serializers) or another dedicated class that is reported as a value converter through the XAML type system. In the XAML node stream, a type converter usage and a markup extension usage have very different representations. + +### Type Converters in the XAML Node Stream + +An attribute set that eventually results in a type converter usage is reported in the XAML node stream as a value of a member. The XAML node stream does not attempt to produce a type converter instance object and pass the value to it. Using a type converter's conversion implementation requires invoking the XAML schema context and using it for type-mapping. Even determining which type converter class should be used to process the value requires the XAML schema context indirectly. When you use the default XAML schema context, that information is available from the XAML type system. If you need the type converter class information at the XAML node stream level before connection to a XAML writer, you can obtain it from the information of the member being set. But otherwise, type converter input should be preserved in the XAML node stream as a plain value until the remainder of operations that require the type-mapping system and XAML schema context are performed, for example the object creation by a XAML object writer. + +For example, consider the following class definition outline and XAML usage for it: + +```csharp +public class BoardSizeConverter : TypeConverter { + //converts from string to an int[2] by splitting on an "x" char +} +public class GameBoard { + [TypeConverter(typeof(BoardSizeConverter))] + public int[] BoardSize; //2x2 array, initialization not shown +} +``` + +```xaml + +``` + +A text representation of the XAML node stream for this usage could be expressed as the following: + +`StartObject` with representing `GameBoard` + +`StartMember` with representing `BoardSize` + +`Value` node, with text string "`8x8`" + +`EndMember` matches `BoardSize` + +`EndObject` matches `GameBoard` + +Notice that there is no type converter instance in this node stream. But you can get type converter information by calling on the for `BoardSize`. If you have a valid XAML schema context, you can also invoke the converter methods by obtaining an instance from . + +### Markup Extensions in the XAML Node Stream + +A markup extension usage is reported in the XAML node stream as an object node within a member, where the object represents a markup extension instance. Thus a markup extension usage is presented more explicitly in the node stream representation than a type converter usage is, and carries more information. information could not have told you anything about the markup extension, because the usage is situational and varies in each possible markup case; it is not dedicated and implicit per type or member as is the case with type converters. + +The node stream representation of markup extensions as object nodes is the case even if the markup extension usage was made in attribute form in the XAML text markup (which is often the case). Markup extension usages that used an explicit object element form are treated the same way. + +Within a markup extension object node, there may be members of that markup extension. The XAML node stream representation preserves the usage of that markup extension, whether that be a positional parameter usage or a usage with explicit named parameters. + +For a positional parameter usage, the XAML node stream contains a XAML language-defined property `_PositionalParameters` that records the usage. This property is a generic with constraint. The constraint is object and not string because conceivably a positional parameter usage could contain nested markup extension usages within it. To access the positional parameters from the usage, you could iterate through the list and use the indexers for individual list values. + +For a named parameter usage, each named parameter is represented as a member node of that name in the node stream. The member values are not necessarily strings, because there could be a nested markup extension usage. + +`ProvideValue` from the markup extension is not yet invoked. However, it is invoked if you connect a XAML reader and XAML writer so that `WriteEndObject` is invoked on the markup extension node when you examine it in the node stream. For this reason, you generally need the same XAML schema context available as would be used in order to form the object graph on the load path. Otherwise, `ProvideValue` from any markup extension can throw exceptions here, because it does not have expected services available. + +## XAML and XML Language-Defined Members in the XAML Node Stream + +Certain members are introduced to a XAML node stream because of interpretations and conventions of a XAML reader, instead of through an explicit lookup or construction. Often, these members are XAML directives. In some cases, it is the act of reading the XAML that introduces the directive into the XAML node stream. In other words, the original input XAML text did not explicitly specify the member directive, but the XAML reader inserts the directive in order to satisfy a structural XAML convention and report information in the XAML node stream before that information is lost. + +The following list notes all cases where a XAML reader is expected to introduce a directive XAML member node, and how that member node is identified in .NET XAML Services implementations. + +- **Initialization text for an object node:** The name of this member node is `_Initialization`, it represents a XAML directive, and it is defined in the XAML language XAML namespace. You can get a static entity for it from . + +- **Positional parameters for a markup extension:** The name of this member node is `_PositionalParameters`, and it is defined in the XAML language XAML namespace. It always contains a generic list of objects, each of which is a positional parameter pre-separated by splitting on the `,` delimiter character as supplied in the input XAML. You can get a static entity for the positional parameters directive from . + +- **Unknown content:** The name of this member node is `_UnknownContent`. Strictly speaking, it is a , and it is defined in the XAML language XAML namespace. This directive is used as a sentinel for cases where a XAML object element contains content in the source XAML but no content property can be determined under the currently available XAML schema context. You can detect this case in a XAML node stream by checking for members named `_UnknownContent`. If no other action is taken in a load path XAML node stream, the default throws on attempted `WriteEndObject` when it encounters the `_UnknownContent` member on any object. The default does not throw, and treats the member as implicit. You can get a static entity for `_UnknownContent` from . + +- **Collection property of a collection:** Although the backing CLR type of a collection class that is used for XAML usually has a dedicated named property that holds the collection items, that property is not known to a XAML type system prior to backing type resolution. Instead, the XAML node stream introduces an `Items` placeholder as a member of the collection XAML type. In .NET XAML Services implementation, the name of this directive or member in the node stream is `_Items`. A constant for this directive can be obtained from . + + Note that a XAML node stream might contain an Items property with items that turn out to not be parsable based on the backing type resolution and XAML schema context. For example, + +- **XML-defined members:** The XML-defined `xml:base`, `xml:lang` and `xml:space` members are reported as XAML directives named `base`, `lang`, and `space` in .NET XAML Services implementations. The namespace for these is the XML namespace `http://www.w3.org/XML/1998/namespace`. Constants for each of these can be obtained from . + +## Node Order + +In some cases, changes the order of XAML nodes in the XAML node stream, versus the order the nodes appear if viewed in the markup or if processed as XML. This is done in order to order the nodes such that a can process the node stream in a forward-only manner. In .NET XAML Services, the XAML reader reorders nodes rather than leaving this task to the XAML writer, as a performance optimization for XAML object writer consumers of the node stream. + +Certain directives are intended specifically to provide more information for the creation of an object from an object element. These directives are: `Initialization`, `PositionalParameters`, `TypeArguments`, `FactoryMethod`, `Arguments`. .NET XAML Services XAML readers attempt to place these directives as the first members in the node stream following an object's `StartObject`, for reasons that are explained in the next section. + +### XamlObjectWriter Behavior and Node Order + +`StartObject` to a is not necessarily a signal to the XAML object writer to immediately construct the object instance. XAML includes several language features that make it possible to initialize an object with additional input, and to not rely entirely on invoking a parameterless constructor to produce the initial object, and only then setting properties. These features include: ; initialization text; [x:TypeArguments](xtypearguments-directive.md); positional parameters of a markup extension; factory methods and associated [x:Arguments](xarguments-directive.md) nodes (XAML 2009). Each of these cases delays the actual object construction, and because the node stream is reordered, the XAML object writer can rely on a behavior of actually constructing the instance whenever a start member is encountered that is not specifically a construction directive for that object type. + +### GetObject + +`GetObject` represents a XAML node where rather than constructing a new object, a XAML object writer should instead get the value of the object's containing property. A typical case where a `GetObject` node is encountered in a XAML node stream is for a collection object or a dictionary object, when the containing property is deliberately read-only in the backing type's object model. In this scenario, the collection or dictionary often is created and initialized (usually empty) by the initialization logic of an owning type. + +## See also + +- +- [XAML Services](index.md) +- [XAML Namespaces](namespaces.md) diff --git a/dotnet-desktop-guide/xaml-services/white-space-processing.md b/dotnet-desktop-guide/xaml-services/white-space-processing.md new file mode 100644 index 0000000000..45341660a4 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/white-space-processing.md @@ -0,0 +1,77 @@ +--- +title: "White-space processing in XAML" +ms.date: "03/30/2017" +helpviewer_keywords: + - "East Asian characters [XAML Services]" + - "XAML [XAML Services], white-space processing" + - "white-space processing in XAML [XAML Services]" + - "characters [XAML Services], East Asian" +ms.assetid: cc9cc377-7544-4fd0-b65b-117b90bb0b23 +--- +# White-space processing in XAML + +The language rules for XAML state that significant white space must be processed by a [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] processor implementation. This article documents these XAML language rules. It also documents additional white-space handling that is defined by the [!INCLUDE[TLA#tla_winclient](../includes/tlasharptla-winclient-md.md)] implementation of the XAML processor and the XAML writer for serialization. + +## White-space definition + +Consistent with XML, white-space characters in [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] are space, linefeed, and tab. These correspond to the Unicode values 0020, 000A, and 0009 respectively. + +## White-space normalization + +By default the following white-space normalization occurs when a [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] processor processes a [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] file: + +1. Linefeed characters between East Asian characters are removed. See the "East Asian Characters" section later in this topic for a definition of this term. + +2. All white-space characters (space, linefeed, tab) are converted into spaces. + +3. All consecutive spaces are deleted and replaced by one space. + +4. A space immediately following the start tag is deleted. + +5. A space immediately before the end tag is deleted. + +"Default" corresponds to the state denoted by the default value of the [xml:space](xml-space-handling.md) attribute. + +## White space in inner text, and string primitives + +The previous normalization rules apply to inner text that is found within XAML elements. After normalization, a XAML processor converts any inner text into an appropriate type as follows: + +- If the type of the property is not a collection but is not directly an type, the XAML processor attempts to convert to that type by using its type converter. A failed conversion here causes a compile-time error. + +- If the type of the property is a collection and the inner text is contiguous (no intervening element tags), the inner text is parsed as a single . If the collection type cannot accept , this also causes a compile-time error. + +- If the type of the property is , the inner text is parsed as a single . If there are intervening element tags, this causes a compile-time error because the type implies a single object ( or otherwise). + +- If the type of the property is a collection, and the inner text is not contiguous, the first substring is converted into a and added as a collection item, the intervening element is added as a collection item, and finally the trailing substring (if any) is added to the collection as a third item. + +## Preserving white space + +There are several techniques for preserving white space in the source [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] for eventual presentation that are not affected by [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] processor white-space normalization. + +**xml:space="preserve"**: Specify this attribute at the level of the element where white-space preservation is desired. This preserves all white space, which includes the spaces that might be added by code-editing applications to "pretty-print" align elements as a visually intuitive nesting. However, whether those spaces render is determined by the content model for the containing element. Avoid specifying `xml:space="preserve"` at the root level because most object models do not consider white space as significant regardless of how you set the attribute. Setting `xml:space` globally may have performance consequences on XAML processing (particularly serialization) in some implementations. It is a better practice to only set the attribute specifically at the level of elements that render white space within strings, or are white-space significant collections. + +**Entities and non-breaking spaces**: [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] supports placing any Unicode entity within a text object model. You can use dedicated entities such as nonbreaking space (&\#160; in UTF-8 encoding). You can also use rich text controls that support nonbreaking space characters. You should be cautious if you are using entities to simulate layout characteristics such as indention, because the run-time output of the entities will vary based on a greater number of factors than would the capabilities for producing indention results in a typical layout system, such as proper use of panels and margins. For instance, entities are mapped to fonts and can change size in response to user font selection. + +## East Asian characters + +"East Asian characters" is defined as a set of Unicode character ranges U+20000 to U+2FFFD and U+30000 to U+3FFFD. This subset is also sometimes referred to as "CJK ideographs". For more information, see . + +## White space and text content models + +In practice, preserving white space is only of concern for a subset of all possible content models. That subset is composed of content models that can take a singleton type in some form, a dedicated collection, or a mixture of and other types in an or collection. + +### White space and text content models in WPF + +For illustration purposes, the remainder of this section references particular types that are defined by WPF. The white-space handling features that are described in this article are pertinent to both .NET XAML Services and WPF. To see this behavior in action, you might experiment with some WPF XAML markup, view the results in an object graph, and then serialize back to markup again. + +Even for content models that can take strings, the default behavior within these content models is that any white space that remains is not treated as significant. For example, takes an , but the white space (such as linefeeds between each ) is not preserved and not rendered. If you attempt to use linefeeds as separators between strings for items, it does not work at all; the strings that are separated by the linefeeds are treated as one string and one item. + +Those collections that do treat white space as significant are typically part of the flow document model. The primary collection that supports white-space preservation behavior is . This collection class is declared with the ; when this attribute is found, the [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] processor will treat white space within the collection as significant. The combination of `xml:space="preserve"` and white space within a denoted collection is that all white space is preserved and rendered. The combination of `xml:space="default"` and white space within a causes the initial white-space normalization described earlier, which leaves one space in certain positions, and those spaces are preserved and rendered. Which behavior is desirable is up to you, and you should use `xml:space` selectively to enable the behavior that you want. + +Also, certain inline elements that connote a line break in a flow document model should deliberately not introduce an extra space even in a white-space significant collection. For example, the element has the same purpose as the \
tag in HTML, and for readability in markup, typically a is separated from any subsequent text by an authored linefeed. That linefeed should not be normalized to become a leading space in the subsequent line. To enable that behavior, the class definition for the element applies the , which is then interpreted by the [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] processor to mean that white space surrounding is always trimmed. + +## See also + +- [XAML overview (WPF)](../net/wpf/fundamentals/xaml.md) +- [XML character entities and XAML](xml-character-entities.md) +- [xml:space handling in XAML](xml-space-handling.md) diff --git a/dotnet-desktop-guide/xaml-services/xaml-2009-language-features.md b/dotnet-desktop-guide/xaml-services/xaml-2009-language-features.md new file mode 100644 index 0000000000..04cf266f4d --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xaml-2009-language-features.md @@ -0,0 +1,34 @@ +--- +title: "XAML 2009 Language Features" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML 2009 [XAML Services]" + - "XAML [XAML Services], XAML 2009" +ms.assetid: f6bb18d8-c86a-4549-8862-323e6b32a8dd +--- +# XAML 2009 Language Features +XAML 2009 is the shorthand term for new XAML language features that extend the existing XAML language specification. XAML 2009 introduces several new directives and constructs. These include the [x:Arguments Directive](xarguments-directive.md); the [x:FactoryMethod Directive](xfactorymethod-directive.md); the [x:Reference Markup Extension](xreference-markup-extension.md); the [x:TypeArguments Directive](xtypearguments-directive.md); and built-in types for common language primitives (for example `x:Char`). + +## XAML 2009 Support in WPF and Visual Studio + +In WPF, you can use XAML 2009 features, but only for XAML that is not WPF markup-compiled. Markup-compiled XAML and the BAML form of XAML do not currently support the XAML 2009 language keywords and features. + +Note that existing techniques for loading loose XAML in WPF also have possible security and access restrictions to CLR types and the type system that are more restrictive than for markup-compiled XAML. For more information, see [Security (WPF)](../framework/wpf/security-wpf.md) or [WPF Security Strategy - Platform Security](../framework/wpf/wpf-security-strategy-platform-security.md). + +XAML 2009 also introduces additional features that either modify the previous XAML 2006 constructs or that modify the basic markup forms. + +### x:Key as an Object Element + +XAML 2009 can support `x:Key` as an object (a property element that has object element value); however, XAML 2006 only supported `x:Key` as an attribute. See the "XAML 2009" section of [x:Key Directive](xkey-directive.md). + +### xmlns on Property Elements + +XAML 2009 can support XAML namespace (xmlns) definitions on property elements; however, XAML 2006 only supports xmlns definitions on object elements. + +### Event Attributes + +For attributes that are backed by events, XAML 2006 presumes that markup compilation is involved and submits the events to markup compilation. XAML 2009 supports a markup form that resembles a markup extension, which defers the event wiring until run-time parsing and loading of the XAML. However, WPF applications and XAML scenarios for WPF UI generally do not use this capability. WPF and its XAML 2006 implementation uses the combination of event handler wiring for routed events defined at the level and its markup compiler step for much of its event attribute processing. The markup compiler also preprocesses any event attributes found in XAML where the build actions declare that the markup compiler is used. + +## See also + +- [XAML Overview (WPF)](../net/wpf/fundamentals/xaml.md) diff --git a/dotnet-desktop-guide/xaml-services/xamlname-grammar.md b/dotnet-desktop-guide/xaml-services/xamlname-grammar.md new file mode 100644 index 0000000000..611a4ebb5c --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xamlname-grammar.md @@ -0,0 +1,55 @@ +--- +title: "XamlName Grammar" +ms.date: "03/30/2017" +helpviewer_keywords: + - "DottedXamlName grammar [XAML Services]" + - "grammar [XAML Services], DottedXamlName" + - "grammar [XAML Services], XamlName" + - "names in XAML [XAML Services]" + - "XamlName grammar [XAML Services]" +ms.assetid: 11e4cada-41d2-494d-9531-0d3df4dfcbe3 +--- +# XamlName Grammar + +XamlName Grammar is a specific grammar that is defined in the XAML language specification [MS-XAML], which is reproduced here for convenience. + +## From the XAML Specification + +The [MS-XAML] specification defines the grammar XamlName to identify the set of legal symbolic identifiers used for types and properties. + +String values that are of type XamlName must conform to the following grammar: + +```xaml +XamlName ::= NameStartChar ( NameChar )* +NameStartChar ::= LetterCharacter | '_' +NameChar ::= NameStartChar | DecimalDigit | CombiningCharacter +LetterCharacter ::= UnicodeLu | UnicodeLl | UnicodeLo | UnicodeLt | UnicodeNl +DecimalDigit ::= UnicodeNd +CombiningCharacter ::= UnicodeMn | UnicodeMc +``` + +Which assumes the following general category values as defined in the Unicode Character Database + +| Unicode category | Description | +|--------------------|-------------------------------| +| Lu | Letter, Uppercase | +| Ll | Letter, Lowercase | +| Lt | Letter, Titlecase | +| Lm | Letter, Modifier | +| Lo | Letter, Other | +| Mn | Mark, Non-Spacing | +| Mc | Mark, Spacing Combining | +| Nd | Number, Decimal | +| Nl | Number, Letter | + +XAML defines a second grammar, DottedXamlName, that is used for property and event qualified references, and also for attached members. For more information, see and [XAML Overview (WPF)](../net/wpf/fundamentals/xaml.md). + +String values that are of type DottedXamlName must conform to the following grammar: + +```xaml +DottedXamlName ::= XamlName '.' XamlName +``` + +## Remarks + +For the complete specification, see [\[MS-XAML\]](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). diff --git a/dotnet-desktop-guide/xaml-services/xarguments-directive.md b/dotnet-desktop-guide/xaml-services/xarguments-directive.md new file mode 100644 index 0000000000..42781c6a2c --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xarguments-directive.md @@ -0,0 +1,110 @@ +--- +title: "x:Arguments Directive" +ms.date: "03/30/2017" +helpviewer_keywords: + - "x:Arguments directive [XAML Services]" + - "Arguments directive in XAML [XAML Services]" + - "XAML [XAML Services], x:Arguments directive" +ms.assetid: 87cc10b0-b610-4025-b6b0-ab27ca27c92e +--- +# x:Arguments Directive + +Packages construction arguments for a non-parameterless constructor object element declaration in XAML, or for a factory method object declaration. + +## XAML Element Usage (Nonparameterless constructor) + +```xaml + + + oneOrMoreObjectElements + + +``` + +## XAML Element Usage (factory method) + +```xaml + + + oneOrMoreObjectElements + + +``` + +## XAML Values + +||| +|-|-| +|`oneOrMoreObjectElements`|One or more object elements that specify arguments to be passed to the backing non-parameterless constructor or factory method.

Typical usage is to use initialization text within the object elements to specify the actual argument values. See Examples section.

The order of the elements is significant. The XAML types in order must match the types and type order of the backing constructor or factory method overload.| +|`methodName`|The name of the factory method that should process any `x:Arguments` arguments.| + +## Dependencies + +`x:FactoryMethod` can modify the scope and behavior where `x:Arguments` applies. + +If no `x:FactoryMethod` is specified, `x:Arguments` applies to alternate (non-default) signatures of the backing constructors. + +If `x:FactoryMethod` is specified, `x:Arguments` applies to an overload of the named method. + +## Remarks + +XAML 2006 can support non-default initialization through initialization text. However, the practical application of an initialization text construction technique is limited. Initialization text is treated as a single text string; therefore, it only adds capability for a single parameter initialization unless a type converter is defined for the construction behavior that can parse custom information items and custom delimiters from the string. Also, the text string to object logic is potentially a given XAML parser's native default type converter for handling primitives other than a true string. + +The `x:Arguments` XAML usage is not property element usage in the typical sense, because the directive markup does not reference the containing object element's type. It is more akin to other directives such as `x:Code` where the element demarks a range in which the markup should be interpreted as other than the default for child contents. In this case, the XAML type of each object element communicates information about the argument types, which is used by XAML parsers to determine which specific constructor factory method signature an `x:Arguments` usage is attempting to reference. + +`x:Arguments` for an object element being constructed must precede any other property elements, content, inner text, or initialization strings of the object element. The object elements within `x:Arguments` can include attributes and initialization strings, as permitted by that XAML type and its backing constructor or factory method. For either the object or the arguments, you can specify custom XAML types or XAML types that are otherwise outside the default XAML namespace by referencing established prefix mappings. + +XAML processors use the following guidelines to determine how the arguments specified in `x:Arguments` should be used to construct an object. If `x:FactoryMethod` is specified, information is compared to the specified `x:FactoryMethod` (note that the value of `x:FactoryMethod` is the method name, and the named method can have overloads. If `x:FactoryMethod` is not specified, information is compared to the set of all public constructor overloads of the object. XAML processing logic then compares the number of parameters and selects the overload with matching arity. If there is more than one match, the XAML processor should compare the types of the parameters based on the XAML types of the provided object elements. If there is still more than one match, the XAML processor behavior is undefined. If a `x:FactoryMethod` is specified but the method cannot be resolved, a XAML processor should throw an exception. + +A XAML attribute usage `string` is technically possible. However, this provides no capabilities beyond what could be done otherwise through initialization text and type converters, and using this syntax is not the design intention of the XAML 2009 factory method features. + +## Examples + +The following example shows a non-parameterless constructor signature, then the XAML usage of `x:Arguments` that accesses that signature. + +```csharp +public class Food { + private string _name; + private Int32 _calories; + public Food(string name, Int32 calories) { + _name=name; + _calories=calories; + } +} +``` + +```xaml + + + Apple + 150 + + +``` + +The following example shows a target factory method signature, then the XAML usage of `x:Arguments` that accesses that signature. + +```csharp +public Food TryLookupFood(string name) +{ +switch (name) { + case "Apple": return new Food("Apple",150); + case "Chocolate": return new Food("Chocolate",200); + case "Cheese": return new Food("Cheese", 450); + default: {return new Food(name,0); +} +} +``` + +```xaml + + + Apple + + +``` + +## See also + +- [Defining Custom Types for Use with .NET XAML Services](define-custom-types.md) +- [XAML Overview (WPF)](../net/wpf/fundamentals/xaml.md) diff --git a/dotnet-desktop-guide/xaml-services/xarray-markup-extension.md b/dotnet-desktop-guide/xaml-services/xarray-markup-extension.md new file mode 100644 index 0000000000..de9c7bd02e --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xarray-markup-extension.md @@ -0,0 +1,69 @@ +--- +title: "x:Array Markup Extension" +ms.date: "03/30/2017" +f1_keywords: + - "x:Array" + - "xArray" +helpviewer_keywords: + - "x:Array [XAML Services]" + - "XAML [XAML Services], x:Array markup extension" +ms.assetid: c5358e14-d24c-44c7-b5eb-6062a4fd981c +--- +# x:Array Markup Extension + +Provides general support for arrays of objects in XAML through a markup extension. This corresponds to the `x:ArrayExtension` XAML type in [MS-XAML]. + +## XAML Object Element Usage + +```xaml + + arrayContents + +``` + +## XAML Values + +||| +|-|-| +|`typeName`|The name of the type that your `x:Array` will contain. `typeName` may be (and often is) prefixed for a XAML namespace that contains the XAML type definitions.| +|`arrayContents`|The items content that is assigned to the intrinsic `ArrayExtension.Items` property. Typically, these items are specified as one or more object elements contained within the `x:Array` opening and closing tags. Objects specified here are expected to be assignable to the XAML type specified in `typeName`.| + +## Remarks + +`Type` is a required attribute for all `x:Array` object elements. A `Type` parameter value does not need to use an `x:Type` markup extension; the short name of the type is a XAML type, which can be specified as a string. + +In .NET XAML Services implementation, the relationship between the input XAML type and the output CLR of the created array is influenced by service context for markup extensions. The output is the of the input XAML type, after looking up the necessary based on XAML schema context and the service the context provides. + +When processed, the array contents are assigned to the `ArrayExtension.Items` intrinsic property. In the implementation, this is represented by . + +In .NET XAML Services implementation, the handling for this markup extension is defined by the class. is not sealed, and could be used as the basis for a markup extension implementation for a custom array type. + +`x:Array` is more intended for general language extensibility in XAML. But `x:Array` can also be useful for specifying XAML values of certain properties that take XAML-supported collections as their structured property content. For example, you could specify the contents of an property with an `x:Array` usage. + +`x:Array` is a markup extension. Markup extensions are typically implemented when there is a requirement to escape attribute values to be other than literal values or handler names, and the requirement is more global than just putting type converters on certain types or properties. `x:Array` is partially an exception to that rule because instead of providing alternative attribute value handling, `x:Array` provides alternative handling of its inner text content. This behavior enables types that might not be supported by an existing content model to be grouped into an array and referenced later in code-behind by accessing the named array; you can call methods to get individual array items. + +All markup extensions in XAML use the braces ({,}`)` in their attribute syntax, which is the convention by which a XAML processor recognizes that a markup extension must process the attribute value. For more information about markup extensions in general, see [Type Converters and Markup Extensions for XAML](type-converters-and-markup-extensions.md). + +In XAML 2009, `x:Array` is defined as a language primitive instead of a markup extension. For more information, see [Built-in Types for Common XAML Language Primitives](types-for-primitives.md). + +## WPF Usage Notes + +Typically, the object elements that populate an `x:Array` are not elements that exist in the [!INCLUDE[TLA2#tla_winclient](../includes/tla2sharptla-winclient-md.md)] XAML namespace, and require a prefix mapping to a non-default XAML namespace. + +For example, the following is a simple array of two strings, with the `sys` prefix (and also `x`) defined at the level of the array. + +```xaml + + Hello + World + +``` + +For custom types that are used as array elements, the class must also support the requirements for being instantiated in XAML as object elements. For more information, see [XAML and Custom Classes for WPF](../framework/wpf/advanced/xaml-and-custom-classes-for-wpf.md). + +## See also + +- [Markup Extensions and WPF XAML](../framework/wpf/advanced/markup-extensions-and-wpf-xaml.md) +- [Types Migrated from WPF to System.Xaml](../framework/wpf/advanced/types-migrated-from-wpf-to-system.md) diff --git a/dotnet-desktop-guide/xaml-services/xclass-directive.md b/dotnet-desktop-guide/xaml-services/xclass-directive.md new file mode 100644 index 0000000000..cb63088585 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xclass-directive.md @@ -0,0 +1,66 @@ +--- +title: "x:Class Directive" +ms.date: "03/30/2017" +f1_keywords: + - "x:Class" + - "xClass" + - "Class" +helpviewer_keywords: + - "Class attribute in XAML [XAML Services]" + - "XAML [XAML Services], x:Class attribute" + - "x:Class attribute [XAML Services]" +ms.assetid: bc4a3d8e-76e2-423e-a5d1-159a023e82ec +--- +# x:Class Directive +Configures XAML markup compilation to join partial classes between markup and code-behind. The code partial class is defined in a separate code file in a Common Language Specification (CLS) language, whereas the markup partial class is typically created by code generation during XAML compilation. + +## XAML Attribute Usage + +```xaml + + ... + +``` + +## XAML Values + +||| +|-|-| +|`namespace`|Optional. Specifies a CLR namespace that contains the partial class identified by `classname`. If `namespace` is specified, a dot (.) separates `namespace` and `classname`. See Remarks.| +|`classname`|Required. Specifies the CLR name of the partial class that connects the loaded XAML and your code-behind for that XAML.| + +## Dependencies + +`x:Class` can only be specified on the root element of a XAML production. `x:Class` is invalid on any object that has a parent in the XAML production. For more information, see [\[MS-XAML\] Section 4.3.1.6](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +## Remarks + +The `namespace` value may contain additional dots to organize related namespaces into name hierarchies, which is a common technique in .NET programming. Only the last dot in a string of `x:Class` values is interpreted to separate `namespace` and `classname.` The class that is used as `x:Class` cannot be a nested class. Nested classes are not allowed because determining the meaning of dots for `x:Class` strings is ambiguous if nested classes are permitted. + +In existing programming models that use `x:Class`, `x:Class` is optional in the sense that it is entirely valid to have a XAML page that has no code-behind. However, that capability interacts with the build actions as implemented by frameworks that use XAML. `x:Class` capability is also influenced by the roles that various classifications of XAML-specified content have in an application model and in the corresponding build actions. If your XAML declares event-handling attribute values or instantiates custom elements where the defining classes are in the code-behind class, you have to provide the `x:Class` directive reference (or [x:Subclass](xsubclass-directive.md)) to the appropriate class for code-behind. + +The value of the `x:Class` directive must be a string that specifies the fully qualified name of a class but without any assembly information (equivalent to the ). For simple applications, you can omit CLR namespace information if the code-behind is also structured in that manner (code definition starts at the class level). + +The code-behind file for a page or application definition must be within a code file that is included as part of the project that produces a compiled application and involves markup compilation. You must follow name rules for CLR classes. For more information, see [Framework Design Guidelines](/dotnet/api/). By default, the code-behind class must be `public`; however, you can define it at a different access level by using the [x:ClassModifier Directive](xclassmodifier-directive.md). + +This interpretation of the `x:Class` attribute applies only to a CLR-based XAML implementation, in particular to .NET XAML Services. Other XAML implementations that are not based on CLR and that do not use .NET XAML Services might use a different resolution formula for connecting XAML markup and backing run-time code. For more information about more general interpretations of `x:Class`, see [\[MS-XAML\]](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +At a certain level of architecture, the meaning of `x:Class` is undefined in .NET XAML Services. This is because .NET XAML Services does not specify the programming model by which XAML markup and backing code are connected. Additional uses of the `x:Class` directive might be implemented by specific frameworks that use programming models or application models to define how to connect XAML markup and CLR-based code-behind. Each framework can have its own build actions that enable some of the behavior or specific components that must be included in the build environment. Within a framework, build actions can also vary depending on the specific CLR language that is used for the code-behind. + +## x:Class in the WPF Programming Model + +In WPF applications and the WPF application model, `x:Class` can be declared as an attribute for any element that is the root of a XAML file and is being compiled (where the XAML is included in a WPF application project with `Page` build action), or for the root in the application definition of a compiled WPF application. Declaring `x:Class` on an element other than a page root or application root, or on a WPF XAML file that is not compiled, causes a compile-time error under the .NET Framework 3.0 and .NET Framework 3.5 WPF XAML compiler. For information about other aspects of `x:Class` handling in WPF, see [Code-Behind and XAML in WPF](../framework/wpf/advanced/code-behind-and-xaml-in-wpf.md). + +## x:Class for Windows Workflow Foundation +For Windows Workflow Foundation, `x:Class` names the class of a custom activity composed entirely in XAML, or names the partial class of the XAML page for an activity designer with code-behind. + +## Silverlight Usage Notes + +`x:Class` for Silverlight is documented separately. For more information, see [XAML Namespace (x:) Language Features (Silverlight)](https://docs.microsoft.com/previous-versions/windows/silverlight/dotnet-windows-silverlight/cc188995(v=vs.95)). + +## See also + +- [x:Subclass Directive](xsubclass-directive.md) +- [XAML and Custom Classes for WPF](../framework/wpf/advanced/xaml-and-custom-classes-for-wpf.md) +- [x:ClassModifier Directive](xclassmodifier-directive.md) +- [Types Migrated from WPF to System.Xaml](../framework/wpf/advanced/types-migrated-from-wpf-to-system.md) diff --git a/dotnet-desktop-guide/xaml-services/xclassmodifier-directive.md b/dotnet-desktop-guide/xaml-services/xclassmodifier-directive.md new file mode 100644 index 0000000000..c5b7ab4732 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xclassmodifier-directive.md @@ -0,0 +1,59 @@ +--- +title: "x:ClassModifier Directive" +ms.date: "03/30/2017" +f1_keywords: + - "xClassModifier" + - "x:ClassModifier" + - "ClassModifier" +helpviewer_keywords: + - "XAML [XAML Services], x:ClassModifier attribute" + - "x:ClassModifier attribute [XAML Services]" + - "ClassModifier attribute in XAML [XAML Services]" +ms.assetid: ef30ab78-d334-4668-917d-c9f66c3b6aea +--- +# x:ClassModifier Directive +Modifies XAML compilation behavior when `x:Class` is also provided. Specifically, instead of creating a partial `class` that has a `Public` access level (the default), the provided `x:Class` is created with a `NotPublic` access level. This behavior affects the access level for the class in the generated assemblies. + +## XAML Attribute Usage + +```xaml + + ... + +``` + +## XAML Values + +||| +|-|-| +|*NotPublic*|The exact string to pass to specify versus varies, depending on the code-behind programming language that you use. See Remarks.| + +## Dependencies + +[x:Class](xclass-directive.md) must also be provided on the same element, and that element must be the root element in a page. For more information, see [\[MS-XAML\] Section 4.3.1.8](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +## Remarks + +The value of `x:ClassModifier` in .NET XAML Services usage varies by programming language. The string to use depends on how each language implements its and the type converters it returns to define the meanings for and , and whether that language is case sensitive. + +- For C#, the string to pass to designate is `internal`. + +- For Microsoft Visual Basic .NET, the string to pass to designate is `Friend`. + +- For C++/CLI, no targets exist that support compiling XAML; therefore, the value to pass is unspecified. + +You can also specify (`public` in C#, `Public` in Visual Basic); however, specifying is infrequently done because is already the default behavior. + +Other values with equivalent user code access-level restrictions, such as `private` in C#, are not relevant for `x:ClassModifier` because nested class references are not supported in XAML, and therefore, the modifier has the same effect. + +## Security Notes + +The access level as declared in `x:ClassModifier` is still subject to interpretation by particular frameworks and their capabilities. WPF includes capabilities to load and instantiate types where `x:ClassModifier` is `internal`, if that class is referenced from a WPF resource through a pack URI reference. As a consequence of this case and potentially others like it implemented by other frameworks, do not rely exclusively on `x:ClassModifier` to block all possible instantiation attempts. + +## See also + +- [x:Class Directive](xclass-directive.md) +- [Code-Behind and XAML in WPF](../framework/wpf/advanced/code-behind-and-xaml-in-wpf.md) +- [x:FieldModifier Directive](xfieldmodifier-directive.md) +- [Security (WPF)](../framework/wpf/security-wpf.md) +- [Types Migrated from WPF to System.Xaml](../framework/wpf/advanced/types-migrated-from-wpf-to-system.md) diff --git a/dotnet-desktop-guide/xaml-services/xcode-intrinsic-xaml-type.md b/dotnet-desktop-guide/xaml-services/xcode-intrinsic-xaml-type.md new file mode 100644 index 0000000000..3ba624d100 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xcode-intrinsic-xaml-type.md @@ -0,0 +1,51 @@ +--- +title: "x:Code Intrinsic XAML Type" +ms.date: "03/30/2017" +f1_keywords: + - "Code" + - "x:Code" + - "xCode" +helpviewer_keywords: + - "Code directive in XAML [XAML Services]" + - "x:Code XAML directive element [XAML Services]" + - "XAML [XAML Services], x:Code directive element" +ms.assetid: 87986b13-1a2e-4830-ae36-15f9dc5629e8 +--- +# x:Code Intrinsic XAML Type +Allows placement of code within a XAML production. Such code can either be compiled by any XAML processor implementation that compiles XAML, or left in the XAML production for later uses such as interpretation by a runtime. + +## XAML Object Element Usage + +```xaml + + // code instructions, usually enclosed by CDATA... + +``` + +## Remarks + +The code within the `x:Code` XAML directive element is still interpreted within the general XML namespace and the XAML namespaces provided. Therefore, it is usually necessary to enclose the code used for `x:Code` inside a `CDATA` segment. + +`x:Code` is not permitted for all possible deployment mechanisms of a XAML production. In specific frameworks (for example WPF) the code must be compiled. In other frameworks, `x:Code` usage might be generally disallowed. + +For frameworks that permit managed `x:Code` content, the correct language compiler to use for `x:Code` content is determined by settings and targets of the containing project that is used to compile the application. + +## WPF Usage Notes + +Code declared within `x:Code` for WPF has several notable limitations: + +- The `x:Code` directive element must be an immediate child element of the root element of the XAML production. + +- [x:Class Directive](xclass-directive.md) must be provided on the parent root element. + +- The code placed within `x:Code` will be treated by compilation to be within the scope of the partial class that is already being created for that XAML page. Therefore all code you define must be members or variables of that partial class. + +- You cannot define additional classes, other than by nesting a class inside the partial class (nesting is allowed, but it is not typical because nested classes cannot be referenced in XAML). CLR namespaces other than the namespace that is used for the existing partial class cannot be defined or added to. + +- References to code entities outside the partial class CLR namespace must all be fully qualified. If members being declared are overrides to the partial class overridable members, this must be specified with the language-specific override keyword. If members declared in `x:Code` scope conflict with members of the partial class created out of the XAML, in such a way that the compiler reports the conflict, the XAML file cannot compile or load. + +## See also + +- [x:Class Directive](xclass-directive.md) +- [Code-Behind and XAML in WPF](../framework/wpf/advanced/code-behind-and-xaml-in-wpf.md) +- [XAML Overview (WPF)](../net/wpf/fundamentals/xaml.md) diff --git a/dotnet-desktop-guide/xaml-services/xdata-intrinsic-xaml-type.md b/dotnet-desktop-guide/xaml-services/xdata-intrinsic-xaml-type.md new file mode 100644 index 0000000000..1a54626960 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xdata-intrinsic-xaml-type.md @@ -0,0 +1,52 @@ +--- +title: "x:XData Intrinsic XAML Type" +ms.date: "03/30/2017" +f1_keywords: + - "x:XData" + - "XData" + - "xXData" +helpviewer_keywords: + - "XAML [XAML Services], x:XData directive element" + - "XData in XAML [XAML Services]" + - "x:XData XAML directive element [XAML Services]" +ms.assetid: 7ce209c2-621b-4977-b643-565f7e663534 +--- +# x:XData Intrinsic XAML Type +Enables placement of XML data islands within a XAML production. XML elements within `x:XData` should not be treated by XAML processors as if they are a part of the acting default XAML namespace or any other XAML namespace. `x:XData` can contain arbitrary well-formed XML. + +## XAML Object Element Usage + +```xaml + + + [elementData] + + +``` + +## XAML Values + +||| +|-|-| +|`elementDataRoot`|The single root element of the enclosed data island. For most eventual consumers, XML that does not have a single root is considered invalid. In particular, a single root is required if the `x:XData` is intended as an XML data source for WPF or many other technologies that use XML sources for data binding.| +|`[elementData]`|Optional. XML that represents the XML data. Any number of elements can be contained as element data and nested elements can be contained in other elements; however, the general rules of XML apply.| + +## Remarks + +The XML elements within an `x:XData` object can re-declare all possible namespaces and prefixes of the containing XMLDOM within the data. + +Programmatic access to XML data and the `x:XData` intrinsic XAML type is possible in .NET XAML Services through the class. + +## WPF Usage Notes + +The `x:XData` object is primarily used as a child object of an , or alternatively, as the child object of the property (in XAML, this is typically expressed in property element syntax). + +The data should typically redefine the base XML namespace within the data island to be a new default XML namespace (set to an empty string). This is easiest for simple data islands because the expressions that are used to reference and bind to the data can avoid inclusion of prefixes. More complex data islands might define multiple prefixes for the data and use a specific prefix for the XML namespace at the root. In this case, all expression references should include the appropriate namespace-mapped prefix. For more information, see [Data Binding Overview](../net/wpf/data/data-binding-overview.md). + +Technically, `x:XData` can be used as the content of any property of type . However, is the only prominent implementation. + +## See also + +- +- [Data Binding Overview](../net/wpf/data/data-binding-overview.md) +- [Binding Markup Extension](../framework/wpf/advanced/binding-markup-extension.md) diff --git a/dotnet-desktop-guide/xaml-services/xfactorymethod-directive.md b/dotnet-desktop-guide/xaml-services/xfactorymethod-directive.md new file mode 100644 index 0000000000..615527330e --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xfactorymethod-directive.md @@ -0,0 +1,55 @@ +--- +title: "x:FactoryMethod Directive" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML. x:FactoryMethod directive [XAML Services]" + - "FactoryMethod directive in XAML [XAML Services]" + - "x:FactoryMethod directive [XAML Services]" +ms.assetid: 829bcbdf-5318-4afb-9a03-c310e0d2f23d +--- +# x:FactoryMethod Directive +Specifies a method other than a constructor that a XAML processor should use to initialize an object after resolving its backing type. + +## XAML Attribute Usage, no x:Arguments + +```xaml + + ... + +``` + +## XAML Attribute Usage, x:Arguments as Element(s) + +```xaml + + + oneOrMoreObjectElements + + +``` + +## XAML Values + +||| +|-|-| +|`methodname`|The string method name of a method that XAML processors call to initialize the instance specified as `object`. See Remarks.| +|`oneOrMoreObjectElements`|One or more object elements for objects that specify factory method parameters. Order is significant; it signifies the order in which arguments should be passed to the factory method.| + +## Remarks + If `methodname` is an instance method, it cannot be qualified. + + Static methods as factory methods are supported. If `methodname` is a static method, `methodname` is provided as a `typeName.methodName` combination, where `typeName` names the class that defines the static factory method. `typeName` can be prefix-qualified if referring to a type in a mapped xmlns. `typeName` can be a different type than `typeof(object)`. + + The factory method must be a declared public method of the type that backs the relevant object element. + + The factory method must return an instance that is assignable to the relevant object. Factory methods should never return null. + + `x:Arguments` operates on a principle of best match for signatures of factory methods. Matching evaluates the parameter count first. If there is more than one possible match for a parameter count, parameter type is then evaluated and best match is determined. If there is still ambiguity after this phase of evaluation, XAML processor behavior is undefined. + + The `x:FactoryMethod` element usage is not property element usage in the typical sense, because the directive markup does not reference the containing object element's type. It is expected that element usage is less common than attribute usage. `x:Arguments` (either attribute or element usage) can be used along with `x:FactoryMethod` element usage, but this is not specifically shown in the Usage sections. + + `x:FactoryMethod` as an element must precede any other property elements, must precede any `x:Arguments` also provided as elements, and must precede any content/inner text/initialization text. + +## See also + +- [x:Arguments Directive](xarguments-directive.md) diff --git a/dotnet-desktop-guide/xaml-services/xfieldmodifier-directive.md b/dotnet-desktop-guide/xaml-services/xfieldmodifier-directive.md new file mode 100644 index 0000000000..0b859d4bc7 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xfieldmodifier-directive.md @@ -0,0 +1,55 @@ +--- +title: "x:FieldModifier Directive" +ms.date: "03/30/2017" +helpviewer_keywords: + - "FieldModifier attribute in XAML [XAML Services]" + - "x:FieldModifier attribute [XAML Services]" + - "XAML [XAML Services], x:FieldModifier attribute" +ms.assetid: ed427cd4-2f35-4d24-bd2f-0fa7b71ec248 +--- +# x:FieldModifier Directive +Modifies XAML compilation behavior so that fields for named object references are defined with access instead of the default behavior. + +## XAML Attribute Usage + +```xaml + +``` + +## XAML Values + +||| +|-|-| +|*Public*|The exact string you pass to specify versus varies, depending on the code-behind programming language that is used. See Remarks.| + +## Dependencies + + If a XAML production uses `x:FieldModifier` anywhere, the root element of that XAML production must declare an [x:Class Directive](xclass-directive.md). + +## Remarks + +`x:FieldModifier` is not relevant for declaring the general access level of a class or its members. It is relevant only for XAML-processing behavior when a particular XAML object that is part of a XAML production is processed, and becomes an object that is potentially accessible in the object graph of an application. By default, the field reference for such an object is kept private, which prevents control consumers from modifying the object graph directly. Instead, control consumers are expected to modify the object graph by using standard patterns that are enabled by programming models, such as by obtaining the layout root, the child element collections, the dedicated public properties, and so on. + +The value for the `x:FieldModifier` attribute varies by programming language, and its purpose can vary in specific frameworks. The string to use depends on how each language implements its and the type converters it returns to define the meanings for and , and whether that language is case sensitive. + +- For C#, the string to pass to designate is `public`. + +- For Microsoft Visual Basic .NET, the string to pass to designate is `Public`. + +- For C++/CLI, no targets for XAML currently exist; therefore, the string to pass is undefined. + +You can also specify (`internal` in C#, `Friend` in Visual Basic) but specifying is unusual because `NotPublic` as the behavior is already the default. + + is the default behavior because it is infrequent that code outside the assembly that compiled the XAML needs access to a XAML-created element. WPF security architecture together with XAML compilation behavior will not declare fields that store element instances as public, unless you specifically set the `x:FieldModifier` to allow public access. + +`x:FieldModifier` is only relevant for elements with an [x:Name Directive](xname-directive.md) because that name is used to reference the field after it is public. + +By default, the partial class for the root element is public; however, you can make it nonpublic by using the [x:ClassModifier Directive](xclassmodifier-directive.md). The [x:ClassModifier Directive](xclassmodifier-directive.md) also affects the access level of the instance of the root element class. You can put both `x:Name` and `x:FieldModifier` on the root element, but this only makes a public field copy of the root element, with the true root element class access level still controlled by [x:ClassModifier Directive](xclassmodifier-directive.md). + +## See also + +- [XAML and Custom Classes for WPF](../framework/wpf/advanced/xaml-and-custom-classes-for-wpf.md) +- [Code-Behind and XAML in WPF](../framework/wpf/advanced/code-behind-and-xaml-in-wpf.md) +- [x:Name Directive](xname-directive.md) +- [Building a WPF Application (WPF)](../framework/wpf/app-development/building-a-wpf-application-wpf.md) +- [x:ClassModifier Directive](xclassmodifier-directive.md) diff --git a/dotnet-desktop-guide/xaml-services/xkey-directive.md b/dotnet-desktop-guide/xaml-services/xkey-directive.md new file mode 100644 index 0000000000..e257c31643 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xkey-directive.md @@ -0,0 +1,111 @@ +--- +title: "x:Key Directive" +ms.date: "03/30/2017" +f1_keywords: + - "xKey" + - "Key" + - "x:Key" +helpviewer_keywords: + - "x:Key attribute [XAML Services]" + - "Key attribute in XAML [XAML Services]" + - "XAML [XAML Services], x:Key attribute" +ms.assetid: 1985cd45-f197-42d5-b75e-886add64b248 +--- +# x:Key Directive +Uniquely identifies elements that are created and referenced in a XAML-defined dictionary. Adding an `x:Key` value to a XAML object element is the most common way to identify a resource in a resource dictionary, for example in a WPF . + +## XAML Attribute Usage + +```xaml + +-or- + +``` + +## XAML Attribute Usage (WPF-specific) + +```xaml + + + +-or- + + + +``` + +## XAML Values + +||| +|-|-| +|`stringKeyValue`|A text string to use as a key. The text string must conform to the [XamlName Grammar](xamlname-grammar.md).| +|`markupExtensionUsage`|Within the markup extension delimiters {}, a markup extension usage that provides an object to use as a key. See Remarks.| + +## Remarks + `x:Key` supports the XAML resource dictionary concept. XAML as a language doesn't define a resource dictionary implementation, that is left to specific UI frameworks. To learn more about how XAML resource dictionaries are implemented in WPF, see [XAML Resources](../net/wpf/fundamentals/xaml-resources-define.md). + + In XAML 2006 and WPF, `x:Key` must be provided as an attribute. You can still use nonstring keys, but this requires a markup extension usage in order to provide the nonstring value in attribute form. If you are using XAML 2009, `x:Key` can be specified as an element, to explicitly support dictionaries keyed by object types other than strings without requiring a markup extension intermediate. See the "XAML 2009" section in this topic. The remainder of the Remarks section applies specifically to the XAML 2006 implementation. + + The attribute value of `x:Key` can be any string defined in the [XamlName Grammar](xamlname-grammar.md) or can be an object evaluated through a markup extension. See "WPF Usage Notes" for an example from WPF. + + Child elements of a parent element that is an implementation must typically include an `x:Key` attribute that specifies a unique key value within that dictionary. Frameworks might implement aliased key properties to substitute for `x:Key` on particular types; types that define such properties should be attributed with . + + The code equivalent of specifying `x:Key` is the key that is used for the underlying . For example, an `x:Key` that is applied in markup for a resource in WPF is equivalent to the value of the `key` parameter of when you add the resource to a WPF in code. + +## WPF Usage Notes + Child objects of a parent object that is an implementation, such as the WPF , must typically include an `x:Key` attribute, and the key value must be unique within that dictionary. There are two notable exceptions: + +- Some WPF types declare an implicit key for dictionary usage. For example, a with a , or a with a , can be in a and use the implicit key. + +- WPF supports a merged resource dictionary concept. Keys can be shared between the merged dictionaries, and the shared key behavior can be accessed using . For more information, see [Merged Resource Dictionaries](../framework/wpf/advanced/merged-resource-dictionaries.md). + + In the overall WPF XAML implementation and application model, key uniqueness is not checked by the XAML markup compiler. Instead, missing or nonunique `x:Key` values cause load-time XAML parser errors. However, Visual Studio handling of dictionaries for WPF can often note such errors in the design phase. + + Note that in the syntax shown, the object is implicit in how the WPF XAML processor produces a collection to populate a collection. A is not typically provided explicitly as an element in markup, although it can be in some cases if wanted for clarity (it would be a collection object element between the property element and the items within that populate the dictionary). For information about why a collection object is almost always an implicit element in markup, see [XAML Syntax In Detail](../framework/wpf/advanced/xaml-syntax-in-detail.md). + + In the WPF XAML implementation, the handling for resource dictionary keys is defined by the abstract class. However the WPF XAML processor produces different underlying extension types for keys based on their usages. For example, the key for a or any derived class is handled separately, and produces a distinct object. + + Keys and names use different directives and language elements (`x:Key` versus `x:Name`) in the basic XAML definition. Keys and names are also used in different situations by the WPF definition and application of these concepts. For details, see [WPF XAML Namescopes](../framework/wpf/advanced/wpf-xaml-namescopes.md). + + As stated previously, the value of a key can be supplied through a markup extension and can be other than a string value. An example WPF scenario is that the value of `x:Key` may be a [ComponentResourceKey](../framework/wpf/advanced/componentresourcekey-markup-extension.md). Certain controls expose a style key of that type for a custom style resource that influences part of the appearance and behavior of that control without totally replacing the style. An example of such a key is . + + The WPF merged dictionary feature introduces additional considerations for key uniqueness and key lookup behavior. For more information, see [Merged Resource Dictionaries](../framework/wpf/advanced/merged-resource-dictionaries.md). + +## XAML 2009 + XAML 2009 relaxes the restriction that `x:Key` always be provided in attribute form. + + In WPF, you can use XAML 2009 features, but only for XAML that is not markup-compiled. Markup-compiled XAML for WPF and the BAML form of XAML do not currently support the XAML 2009 keywords and features. + + Under XAML 2009, you can specify `x:Key` elements through the following usage: + +### XAML Element Usage (XAML 2009 only) + +```xaml + + +keyObject + +... + +``` + +### XAML Values + +||| +|-|-| +|`keyObject`|Object element for the object that is used as the key for a given `object` in a specialized dictionary.| + +- The container/parent for this kind of use is not shown here. `object` is expected to be a child of an object element that represents a specialized dictionary implementation. `keyObject` is expected to be an object instance (or a value of a value type) that is appropriate as the key for that particular specialized dictionary implementation. + +- WPF does not implement dictionaries that require this usage. Object keys is more a general feature of the XAML language, possibly useful for certain custom dictionary scenarios where creating the dictionary in XAML is desirable. For WPF features such as implicit styles that use non-string keys for resources, other techniques for establishing or specifying the keys exist, so using an object key is not necessary. + +- `keyObject` could also be a markup extension usage in object element form, rather than a direct object instance. + +## Silverlight Usage Notes + `x:Key` for Silverlight is documented separately. For more information, see [XAML Namespace (x:) Language Features (Silverlight)](https://docs.microsoft.com/previous-versions/windows/silverlight/dotnet-windows-silverlight/cc188995(v=vs.95)). + +## See also + +- [XAML Resources](../net/wpf/fundamentals/xaml-resources-define.md) +- [Resources and Code](../framework/wpf/advanced/resources-and-code.md) +- [StaticResource Markup Extension](../framework/wpf/advanced/staticresource-markup-extension.md) diff --git a/dotnet-desktop-guide/xaml-services/xmember-directive.md b/dotnet-desktop-guide/xaml-services/xmember-directive.md new file mode 100644 index 0000000000..6c395f6e4b --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xmember-directive.md @@ -0,0 +1,37 @@ +--- +title: "x:Member Directive" +ms.date: "03/30/2017" +ms.assetid: 4d8394ef-644c-4331-b6c5-be855d392980 +--- +# x:Member Directive +Declares a XAML member in markup. + +## XAML Object Element Usage + +```xaml + + + + additionalMembers + + +``` + +## XAML Values + +||| +|-|-| +|`className`|Name of the backing class or partial class for the XAML production.| +|`memberName`|Member name of the property being defined.| + +## Remarks + +In .NET XAML Services implementation, . `x:Member` does not have a direct type backing, but is supported by the class. In a XAML node stream, an `x:Member` element is represented as a member named `Member`, from the XAML language XAML namespace. The member `Member` holds attributes as declared by markup. + +The meaning of `Name` and `Type` are not assigned at .NET XAML Services level. They are stored in the initial XAML node stream as string values, to be interpreted later under the rules that might be imposed by specific frameworks. The meaning might align to a XAML name and XAML type meaning, or might only be valid in a backing type system, depending on the implementation. + +To support a practical usage of `x:Members` as a means to specify member definitions in markup, the members must be associated with a class that can be modified. The intended model is that `x:Members` exists as a member of a type that specifies an `x:Class`. However, the mechanism for associating types and members or for producing dynamic member definitions is not supported at .NET XAML Services level. This is left to individual frameworks that have application models that support member definitions from XAML. Typically, MSBUILD build actions that markup-compile the XAML and either integrate it with code-behind or produce pure from-XAML assemblies are needed to support that feature. + +## x:Property for Windows Workflow Foundation + +For Windows Workflow Foundation, `x:Property` defines the members of a custom activity composed entirely in XAML, or XAML –defined dynamic members for an activity designer with code-behind. `x:Class` must also be specified on the root element of the XAML production. This is not a requirement at .NET XAML Services level, but becomes a requirement when the XAML production is loaded by the MSBUILD build actions that support custom activities and Windows Workflow Foundation XAML in general. Windows Workflow Foundation does not use the pure XAML type name as its intended value for the `x:Property` `Type` attribute, and instead uses a convention that is not documented here. For more information, see [DynamicActivity Creation](https://docs.microsoft.com/previous-versions/dotnet/netframework-4.0/dd807392(v=vs.100)). diff --git a/dotnet-desktop-guide/xaml-services/xmembers-directive.md b/dotnet-desktop-guide/xaml-services/xmembers-directive.md new file mode 100644 index 0000000000..d323e63c39 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xmembers-directive.md @@ -0,0 +1,34 @@ +--- +title: "x:Members Directive" +ms.date: "03/30/2017" +ms.assetid: 155b393d-3b49-4c5a-8c9e-b3d9893af4e4 +--- +# x:Members Directive +Holds a set of members that are defined in markup, which apply to the x:Class of the parent element. + +## XAML Attribute Usage + +```xaml + + + oneOrMoreMembers + +``` + +## XAML Values + +||| +|-|-| +|`className`|Name of the backing class or partial class for the XAML production. See Remarks.| +|`oneOrMoreMembers`|One or more object elements that represent member definitions. Typically, these are `x:Property` object elements. See Remarks.| + +## Remarks + +In .NET XAML Services implementation, there is no backing class or underlying member implementation for `x:Members`. `x:Members` is a special XAML member that can exist as a member on any type. In a XAML node stream, `x:Members` is represented as a member named `Members`, from the XAML language XAML namespace. The member `Members` contains a read-only generic list of `Member` objects. In typical markup the individual members are specified as `x:Property` property elements. `x:Property` is a more precise type specifically for properties of types and is assignable to `x:Member`. For more information, see [x:Property Directive](xproperty-directive.md). + +To support a practical usage of `x:Members` as a means to specify member definitions in markup, the members must be associated with a class that can be modified. The intended model is that `x:Members` exists as a member of a type that specifies an `x:Class`. However, the mechanism for associating types and members or for producing dynamic member definitions is not supported at .NET XAML Services level. This is left to individual frameworks that have application models that support member definitions from XAML. Typically, MSBUILD build actions that markup-compile the XAML and either integrate it with code-behind or produce pure from-XAML assemblies are needed to support that feature. + +## x:Members for Windows Workflow Foundation + +For Windows Workflow Foundation, `x:Members` contains the members of a custom activity composed entirely in XAML, or XAML –defined dynamic members for an activity designer with code-behind. `x:Class` must also be specified on the root element of the XAML production. This is not a requirement at .NET XAML Services level, but becomes a requirement when the XAML production is loaded by the MSBUILD build actions that support custom activities and Windows Workflow Foundation XAML in general. `x:Members` must be the first child element in markup of the object element that declares the `x:Class`. diff --git a/dotnet-desktop-guide/xaml-services/xml-character-entities.md b/dotnet-desktop-guide/xaml-services/xml-character-entities.md new file mode 100644 index 0000000000..bae618c967 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xml-character-entities.md @@ -0,0 +1,65 @@ +--- +title: "XML Character Entities and XAML" +ms.date: "03/30/2017" +f1_keywords: + - "&" + - "&" + - ">" + - "<" +helpviewer_keywords: + - "XAML [XAML Services], special characters" + - "ampersand (&) [XAML Services]" + - "special characters [XAML Services]" + - "apostrophe (') [XAML Services]" + - "greater-than (>) character [XAML Services]" + - "XAML [XAML Services], quotation mark (\")" + - "XAML [XAML Services], apostrophe (')" + - "& (ampersand) [XAML Services]" + - "XAML [XAML Services], & (ampersand)" + - "XAML [XAML Services], escape sequence" + - "quotation mark (\") [XAML Services]" + - "less-than (<) character [XAML Services]" +ms.assetid: 6896d0ce-74f7-420a-9ab4-de9bbf390e8d +--- +# XML Character Entities and XAML + +XAML uses character entities defined in XML for special characters. This topic describes some specific character entities and general considerations for other XML concepts in XAML. + +## Character Entities and Escaping Issues That Are Unique to XAML + +XAML markup typically uses the same character entities and escape sequences that are defined in XML. + +The main exception is that braces ({ and }) have significance in XAML because these characters inform a XAML processor that a character sequence enclosed by braces must be interpreted as a markup extension. For more information about markup extensions, see [Markup Extensions for XAML Overview](markup-extensions-overview.md). + +However, you can still display the braces as literal characters by using an escape sequence that is particular to XAML instead of XML. For more information, see [{} Escape Sequence - Markup Extension](escape-sequence-markup-extension.md). + +Note that a backslash (\\) does not require an escape sequence when it is handled as a string. + +## XML Character Entities + +As mentioned previously, most character entities and escape sequences that are typically used to write XAML markup are defined by XML. This topic does not provide the complete list of these entities; a detailed reference for the entities can be found in external documentation, such as in XML specifications. However, for convenience, this topic lists some of the specific XML character entities that are typically used in XAML markup. + +|Character|Entity|Notes| +|---------------|------------|-----------| +|& (ampersand)|\&|Must be used both for attribute values and for content of an element.| +|> (greater-than character)|\>|Must be used for an attribute value, but > is acceptable as the content of an element as long as < does not precede it.| +|< (less-than character)|\<|Must be used for an attribute value, but \< is acceptable as the content of an element as long as > does not follow it.| +|" (straight quotation mark)|\"|Must be used for an attribute value, but a straight quotation mark (") is acceptable as the content of an element. Note that attribute values may be enclosed either by a single straight quotation mark (') or by a straight quotation mark ("); whichever character appears first defines the attribute value enclosure, and the alternative quote can then be used as a literal within the value.| +|' (single straight quotation mark)|\'|Must be used for an attribute value, but a single straight quotation mark (') is acceptable as the content of an element. Note that attribute values may be enclosed either by a single straight quotation mark (') or by a straight quotation mark ("); whichever character appears first defines the attribute value enclosure, and the alternative quote can then be used as a literal within the value.| +|(numeric character mappings)|&#*[integer]*; or &#x*[hex]*;|XAML supports numeric character mappings into the encoding that is active.| +|(nonbreaking space)|&\#160; (assuming UTF-8 encoding)|For flow document elements, or elements that take text such as the WPF , nonbreaking spaces are not normalized out of the markup, even for `xml:space="default"`. (For more information, see [White-space processing in XAML](white-space-processing.md).)| + +## XML Comment Format + +XAML uses the XML comment format: the start of the comment is `,` and the sequence `--` must not occur within the comment. + +## XML Processing Instructions + +XAML handles XML processing instructions according to XML specifications, which state that the instructions must be passed through. XAML processing in .NET XAML Services does not use any processing instructions. Other existing frameworks that use XAML also do not use processing instructions from XAML. + +## See also + +- [XAML Overview (WPF)](../net/wpf/fundamentals/xaml.md) +- [Markup Extensions and WPF XAML](../framework/wpf/advanced/markup-extensions-and-wpf-xaml.md) +- [XamlName Grammar](xamlname-grammar.md) +- [White-space processing in XAML](white-space-processing.md) diff --git a/dotnet-desktop-guide/xaml-services/xml-language-handling.md b/dotnet-desktop-guide/xaml-services/xml-language-handling.md new file mode 100644 index 0000000000..315387b86c --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xml-language-handling.md @@ -0,0 +1,45 @@ +--- +title: "xml:lang Handling in XAML" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML [XAML Services], xml:lang attribute" + - "xml:lang attribute [XAML Services]" + - "RFC 3066 standard [XAML Services]" + - "standards [XAML Services], RFC 3066" +ms.assetid: 7aac0078-a1c5-41f8-b8b0-975510d9dca0 +--- +# xml:lang Handling in XAML + +The `xml:lang` attribute is an XML-defined attribute that declares the language and culture information for an element in XML. This same meaning of the attribute persists in XAML; however, some additional considerations apply. + +## XAML Attribute Usage + +```xaml + +``` + +## XAML Values + +||| +|-|-| +|*rfc3066lang*|A string that is derived from the [RFC 3066](https://www.ietf.org/rfc/rfc3066.txt) standard and identifies either a language or a language-region. When it is the latter, the language and region are separated by a single hyphen. See for more information about the values and format.| + +## Remarks + +The definition for the `xml:lang` attribute in [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] is derived from `xml:lang` as defined as a "special attribute" by the World Wide Web Consortium (W3C) for XML. Language and culture information is potentially processed in different ways by elements, depending on their implementations; however, there is no default [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] processing of the `xml:lang` attribute. + +The default value of the `xml:lang` attribute is an empty string at the attribute level. + +The `xml:lang` attribute effects and the value of the attribute are generally perpetuated to child elements, when interpreted by systems that act on `xml:lang` values. + +When interpreted by XAML writers of .NET XAML Services, an `xml:lang` value can create or objects in the underlying object representation; however, that behavior depends on whether the value specified for `xml:lang` is a valid construction for those classes. + +Frameworks can create associations between framework-defined properties and the meaning of `xml:lang` in XML by applying to the property. + +## WPF Usage Nodes + +For elements that are derived classes of or , you can use the equivalent dependency property instead of the `xml:lang` attribute. By default, the property uses "en-US" if it is not otherwise set, either through the property or through processing the `xml:lang` attribute. + +## See also + +- [Globalization for WPF](../framework/wpf/advanced/globalization-for-wpf.md) diff --git a/dotnet-desktop-guide/xaml-services/xml-space-handling.md b/dotnet-desktop-guide/xaml-services/xml-space-handling.md new file mode 100644 index 0000000000..72eb904d0c --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xml-space-handling.md @@ -0,0 +1,42 @@ +--- +title: "xml:space Handling in XAML" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML [XAML Services], xml:space attribute" + - "XAML [XAML Services], white-space processing" + - "xml:space attribute [XAML Services]" + - "white-space processing [XAML Services]" +ms.assetid: 5e1814f0-5b30-43d5-8c88-dede335a89d7 +--- +# xml:space Handling in XAML + +The `xml:space` attribute is an XML-defined attribute that declares the significant white-space processing behavior within an object element. This behavior is relevant for all content (inner text) contained within the element where `xml:space` is declared, and also scopes to child elements. + +## XAML Attribute Usage + +```xaml + +``` + + \- or - + +```xaml + +``` + +## Remarks + +The definition for the `xml:space` attribute in XAML including its two possible values is derived from `xml:space` as defined as a "special attribute" by W3C specifications for XML. + +The default value of the `xml:space` attribute is the literal value `"default"`. For the value `"default"`, or if `xml:space` is not indicated at all, the behavior of significant white-space parsing is the default handling, as defined in the topic [White-space processing in XAML](white-space-processing.md). + +To preserve white space within object element content, specify `xml:space="preserve"` on that object element. + +Under most interpretations, the `xml:space` attribute effects and the value of the attribute are scoped to child elements. + +For a complete discussion of white-space processing in XAML, see [White-space processing in XAML](white-space-processing.md). + +## See also + +- [White-space processing in XAML](white-space-processing.md) +- [XAML Overview (WPF)](../net/wpf/fundamentals/xaml.md) diff --git a/dotnet-desktop-guide/xaml-services/xname-directive.md b/dotnet-desktop-guide/xaml-services/xname-directive.md new file mode 100644 index 0000000000..cc0c975ee9 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xname-directive.md @@ -0,0 +1,72 @@ +--- +title: "x:Name Directive" +ms.date: "03/30/2017" +f1_keywords: + - "x:Name" + - "xName" + - "Name" +helpviewer_keywords: + - "x:Name attribute [XAML Services]" + - "XAML [XAML Services], x:Name attribute" + - "Name attribute in XAML [XAML Services]" +ms.assetid: b7e61222-e8cf-48d2-acd0-6df3b7685d48 +--- +# x:Name Directive + +Uniquely identifies XAML-defined elements in a XAML namescope. XAML namescopes and their uniqueness models can be applied to the instantiated objects, when frameworks provide APIs or implement behaviors that access the XAML-created object graph at run time. + +## XAML Attribute Usage + +```xaml + +``` + +## XAML Values + +||| +|-|-| +|`XAMLNameValue`|A string that conforms to the restrictions of the [XamlName Grammar](xamlname-grammar.md).| + +## Remarks + +After `x:Name` is applied to a framework's backing programming model, the name is equivalent to the variable that holds an object reference or an instance as returned by a constructor. + +The value of an `x:Name` directive usage must be unique within a XAML namescope. By default when used by .NET XAML Services API, the primary XAML namescope is defined at the XAML root element of a single XAML production, and encompasses the elements that are contained in that XAML production. Additional discrete XAML namescopes that might occur within a single XAML production can be defined by frameworks to address specific scenarios. For example, in WPF, new XAML namescopes are defined and created by any template that is also defined on that XAML production. For more information about XAML namescopes (written for WPF but relevant for many XAML namescope concepts), see [WPF XAML Namescopes](../framework/wpf/advanced/wpf-xaml-namescopes.md). + +In general, `x:Name` should not be applied in situations that also use `x:Key`. XAML implementations by specific existing frameworks have introduced substitution concepts between `x:Key` and `x:Name`, but that is not a recommended practice. .NET XAML Services does not support such substitution concepts when handling name/key information such as or . + +Rules for permittance of `x:Name` as well as the name uniqueness enforcement are potentially defined by specific implementing frameworks. However, to be usable with .NET XAML Services, the framework definitions of XAML namescope uniqueness should be consistent with the definition of information in this documentation, and should use the same rules regarding where the information is applied. For example, the [!INCLUDE[TLA#tla_winclient](../includes/tlasharptla-winclient-md.md)] implementation divides various markup elements into separate ranges, such as resource dictionaries, the logical tree created by the page-level XAML, templates, and other deferred content, and then enforces XAML name uniqueness within each of those XAML namescopes. + +For custom types that use .NET XAML Services XAML object writers, a property that maps to `x:Name` on a type can be established or changed. You define this behavior by referencing the name of the property to map with the in the type definition code. is a type-level attribute. + +Using.NET XAML Services, the backing logic for XAML namescope support can be defined in a framework-neutral way by implementing the interface. + +## WPF Usage Notes + +Under the standard build configuration for a [!INCLUDE[TLA2#tla_winclient](../includes/tla2sharptla-winclient-md.md)] application that uses XAML, partial classes, and code-behind, the specified `x:Name` becomes the name of a field that is created in the underlying code when [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] is processed by a markup compilation build task, and that field holds a reference to the object. By default, the created field is internal. You can change field access by specifying the [x:FieldModifier attribute](xfieldmodifier-directive.md). In WPF and Silverlight, the sequence is that the markup compile defines and names the field in a partial class, but the value is initially empty. Then, a generated method named `InitializeComponent` is called from within the class constructor. `InitializeComponent` consists of `FindName` calls using each of the `x:Name` values that exist in the XAML-defined part of the partial class as input strings. The return values are then assigned to the like-named field reference to fill the field values with objects that were created from XAML parsing. The execution of `InitializeComponent` make it possible to reference the run time object graph using the `x:Name` / field name directly, rather than having to call `FindName` explicitly any time you need a reference to a XAML-defined object. + +For a WPF application that uses the Microsoft Visual Basic targets and includes XAML files with `Page` build action, a separate reference property is created during compilation that adds the `WithEvents` keyword to all elements that have an `x:Name`, to support `Handles` syntax for event handler delegates. This property is always public. For more information, see [Visual Basic and WPF Event Handling](../framework/wpf/advanced/visual-basic-and-wpf-event-handling.md). + +`x:Name` is used by the WPF XAML processor to register a name into a XAML namescope at load time, even for cases where the page is not markup-compiled by build actions (for example, loose XAML of a resource dictionary). One reason for this behavior is because the `x:Name` is potentially needed for binding. For details, see [Data Binding Overview](../net/wpf/data/data-binding-overview.md). + +As mentioned previously, `x:Name` (or `Name`) should not be applied in situations that also use `x:Key`. The [!INCLUDE[TLA2#tla_winclient](../includes/tla2sharptla-winclient-md.md)] has a special behavior of defining itself as a XAML namescope but returning Not Implemented or null values for APIs as a way to enforce this behavior. If the WPF XAML parser encounters `Name` or `x:Name` in a XAML-defined , the name is not added to any XAML namescope. Attempting to find that name from any XAML namescope and the `FindName` methods will not return valid results. + +### x:Name and Name + +Many WPF application scenarios can avoid any use of the `x:Name` attribute, because the `Name` dependency property as specified in the default XAML namespace for several of the important base classes such as and satisfies this same purpose. There are still some common XAML and WPF scenarios where code access to an element with no `Name` property at the framework level is important. For example, certain animation and storyboard support classes do not support a `Name` property, but they often need to be referenced in code in order to control the animation. You should specify `x:Name` as an attribute on timelines and transforms that are created in XAML, if you intend to reference them from code later. + +If is available as a property on the class, and `x:Name` can be used interchangeably as attributes, but a parse exception will result if both are specified on the same element. If the XAML is markup compiled, the exception will occur on the markup compile, otherwise it occurs on load. + + can be set using XAML attribute syntax, and in code using ; note however that setting the property in code does not create the representative field reference within the XAML namescope in most circumstances where the XAML is already loaded. Instead of attempting to set in code, use methods from code, against the appropriate namescope. + + can also be set using property element syntax with inner text, but that is uncommon. In contrast, `x:Name` cannot be set in XAML property element syntax, or in code using ; it can only be set using attribute syntax on objects because it is a directive. + +## Silverlight Usage Notes + +`x:Name` for Silverlight is documented separately. For more information, see [XAML Namespace (x:) Language Features (Silverlight)](https://docs.microsoft.com/previous-versions/windows/silverlight/dotnet-windows-silverlight/cc188995(v=vs.95)). + +## See also + +- +- +- [Trees in WPF](../framework/wpf/advanced/trees-in-wpf.md) diff --git a/dotnet-desktop-guide/xaml-services/xnull-markup-extension.md b/dotnet-desktop-guide/xaml-services/xnull-markup-extension.md new file mode 100644 index 0000000000..3e2056e7f4 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xnull-markup-extension.md @@ -0,0 +1,48 @@ +--- +title: "x:Null Markup Extension" +ms.date: "03/30/2017" +f1_keywords: + - "NullExtension" + - "x:NullExtension" + - "x:Null" + - "Null" + - "xNull" +helpviewer_keywords: + - "Null markup extension in XAML [XAML Services]" + - "x:Null markup extension [XAML Services]" + - "XAML [XAML Services], x:Null markup extension" +ms.assetid: 2e3ccc21-4996-481d-91b5-3910d8b3bfa3 +--- +# x:Null Markup Extension + +Specifies `null` as a value for a XAML member. + +## XAML Attribute Usage + +```xaml + +``` + +## Remarks + +The keyword for a null reference in C# and C++ is null. The Microsoft Visual Basic keyword for a null reference is `Nothing`, but you always use `{x:Null}` as the XAML usage regardless which code-behind language you associate with the XAML. + +The `x:Null` markup extension has no settable properties. + +A null usage is often associated with the XAML member exposure of a CLR value. + +The `x:Null` markup extension, like all XAML markup extensions, uses the braces (`{,}`) for escaping the handling of attribute values to be other than literals or event-handler references. Attribute syntax is the syntax most frequently used with this markup extension. An object element syntax `` is technically possible, but is rarely used because the `x:Null` markup extension has no positional parameters or construction arguments. + +For information about markup extensions, see [Markup Extensions and WPF XAML](../framework/wpf/advanced/markup-extensions-and-wpf-xaml.md). + +In .NET XAML Services, the handling for this markup extension is defined by the class. + +## WPF Usage Notes + +Note that `null` is not necessarily the initial unset value for a reference-type dependency property. The initial default value can vary for each dependency property and can be based on property-specific metadata. Many dependency properties do not accept `null` as a value, either through markup or code because of their validation callback implementations. For more information about dependency properties, see [Dependency Properties Overview](../framework/wpf/advanced/dependency-properties-overview.md). + +## See also + +- +- [XAML Overview (WPF)](../net/wpf/fundamentals/xaml.md) +- [Markup Extensions and WPF XAML](../framework/wpf/advanced/markup-extensions-and-wpf-xaml.md) diff --git a/dotnet-desktop-guide/xaml-services/xproperty-directive.md b/dotnet-desktop-guide/xaml-services/xproperty-directive.md new file mode 100644 index 0000000000..ad1e90fae9 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xproperty-directive.md @@ -0,0 +1,39 @@ +--- +title: "x:Property Directive" +ms.date: "03/30/2017" +ms.assetid: 618555a8-c893-455c-810f-ac54cd24ef10 +--- +# x:Property Directive + +Declares a XAML property in markup. + +## XAML Object Element Usage + +```xaml + + + + additionalProperties + + +``` + +## XAML Values + +||| +|-|-| +|`className`|Name of the backing class or partial class for the XAML production.| +|`propertyName`|Member name of the property being defined.| +|`propertyType`|Type name (or other string form, framework-specific) that specifies the type of this property.| + +## Remarks + +In .NET XAML Services implementation, . `x:Property` does not have a direct type backing, but is supported by the class. In a XAML node stream, an `x:Property` element is represented as a member named `Property`, from the XAML language XAML namespace. The member `Property` hold attributes as declared by markup. + +The meaning of `Name` and `Type` are not assigned at .NET XAML Services level. They are stored in the initial XAML node stream as string values, to be interpreted later under the rules that might be imposed by specific frameworks. The meaning might align to a XAML name and XAML type meaning, or might only be valid in a backing type system, depending on the implementation. + +To support a practical usage of `x:Members` as a means to specify member definitions in markup, the members must be associated with a class that can be modified. The intended model is that `x:Members` exists as a member of a type that specifies an `x:Class`. However, the mechanism for associating types and members or for producing dynamic member definitions is not supported at .NET XAML Services level. This is left to individual frameworks that have application models that support member definitions from XAML. Typically, MSBUILD build actions that markup-compile the XAML and either integrate it with code-behind or produce pure from-XAML assemblies are needed to support that feature. + +## x:Property for Windows Workflow Foundation + +For Windows Workflow Foundation, `x:Property` defines the members of a custom activity composed entirely in XAML, or XAML –defined dynamic members for an activity designer with code-behind. `x:Class` must also be specified on the root element of the XAML production. This is not a requirement at .NET XAML Services level, but becomes a requirement when the XAML production is loaded by the MSBUILD build actions that support custom activities and Windows Workflow Foundation XAML in general. Windows Workflow Foundation does not use the pure XAML type name as its intended value for the `x:Property` `Type` attribute, and instead uses a convention that is not documented here. For more information, see [DynamicActivity Creation](https://docs.microsoft.com/previous-versions/dotnet/netframework-4.0/dd807392(v=vs.100)). diff --git a/dotnet-desktop-guide/xaml-services/xreference-markup-extension.md b/dotnet-desktop-guide/xaml-services/xreference-markup-extension.md new file mode 100644 index 0000000000..78432c2bfd --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xreference-markup-extension.md @@ -0,0 +1,44 @@ +--- +title: "x:Reference Markup Extension" +ms.date: "03/30/2017" +helpviewer_keywords: + - "x:Reference markup extension [XAML Services]" + - "XAML [XAML Services], x:Reference Markup Extension" + - "Reference markup extension [XAML Services]" +ms.assetid: 2982e68b-d26b-4aa3-826a-34c57a9c5199 +--- +# x:Reference Markup Extension + +References an instance that is declared elsewhere in XAML markup. The reference refers to an element's `x:Name`. + +## XAML Attribute Usage + +```xaml + +``` + +## XAML Object Element Usage + +```xaml + + + + + +``` + +## XAML Values + +||| +|-|-| +|`instancexName`|The `x:Name` value (or value of the -identified property) of the referenced instance.| + +## Remarks + +`x:Reference` provides XAML language-level support for an element reference concept that was otherwise implemented in specific frameworks such as WPF. + +## x:Reference and WPF + +In WPF and XAML 2006, element references are addressed by the framework-level feature of binding. For most WPF applications and scenarios, binding should still be used. Exceptions to this general guidance might include cases where there are data context or other scoping considerations that make data binding impractical and where markup compilation is not involved. + +`x:Reference` is a construct defined in XAML 2009. In WPF, you can use XAML 2009 features, but only for XAML that is not WPF markup-compiled. Markup-compiled XAML and the BAML form of XAML do not currently support the XAML 2009 language keywords and features. diff --git a/dotnet-desktop-guide/xaml-services/xshared-attribute.md b/dotnet-desktop-guide/xaml-services/xshared-attribute.md new file mode 100644 index 0000000000..1d7da66cc8 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xshared-attribute.md @@ -0,0 +1,52 @@ +--- +title: "x:Shared Attribute" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML [XAML Services], x:Shared attribute" + - "x:Shared attribute [XAML Services]" + - "Shared attribute in XAML [XAML Services]" +ms.assetid: c8cff434-2785-405f-9f95-16deb34c9e64 +--- +# x:Shared Attribute + +When set to `false`, modifies WPF resource-retrieval behavior so that requests for the attributed resource create a new instance for each request instead of sharing the same instance for all requests. + +## XAML Attribute Usage + +```xaml + + + +``` + +## Remarks + +`x:Shared` is mapped to the XAML language XAML namespace and is recognized as a valid XAML language element by .NET XAML Services and its XAML readers. However, the stated capabilities of `x:Shared` are only relevant for WPF applications and for the WPF XAML parser. In WPF, `x:Shared` is only useful as an attribute when it is applied to an object that exists within a WPF . Other usages do not throw parse exceptions or other errors, but they have no effect. + +The meaning of `x:Shared` is not specified in the XAML language specification. Other XAML implementations, such as those that build on .NET XAML Services, do not necessarily provide resource-sharing support. Such XAML implementations could provide similar behavior in the supporting framework that also used `x:Shared` values. + +In WPF, the default `x:Shared` condition for resources is `true`. This condition means that any given resource request always returns the same instance. + +Modifying an object that is returned through a resource API, such as , or modifying an object directly within a , changes the original resource. If references to that resource were dynamic resource references, the consumers of that resource get the changed resource. + +If references to the resource were static resource references, changes to the resource after [!INCLUDE[TLA2#tla_xaml](../includes/tla2sharptla-xaml-md.md)] processing time are irrelevant. For more information about static versus dynamic resource references, see [XAML Resources](../net/wpf/fundamentals/xaml-resources-define.md). + +Explicitly specifying `x:Shared="true"` is rarely done, because that is already the default. There is no direct code equivalent for `x:Shared` in the WPF object model; it can only be specified in a XAML usage and must be processed either by the default WPF behavior or in an intermediate XAML node stream on the load path if processed using .NET XAML Services and its XAML readers. + +A scenario for `x:Shared="false"` is if you define a or derived class as a resource and then you introduce the element resource into a content model. `x:Shared="false"` enables an element resource to be introduced multiple times in the same collection (such as a ). Without `x:Shared="false"` this is invalid because the collection enforces uniqueness of its contents. However, the `x:Shared="false"` behavior creates another identical instance of the resource instead of returning the same instance. + +Another scenario for `x:Shared="false"` is if you use a resource for animation values but want to modify the resource on a per animation basis. + +The string handling of `false` is not case sensitive. + +In WPF, `x:Shared` is only valid under the following conditions: + +- The that contains the items with `x:Shared` must be compiled. The cannot be within loose XAML or used for themes. + +- The that contains the items must not be nested within another . For example, you cannot use `x:Shared` for items in a that is within a that is already a item. + +## See also + +- +- [XAML Resources](../net/wpf/fundamentals/xaml-resources-define.md) +- [Base Elements](../framework/wpf/advanced/base-elements.md) diff --git a/dotnet-desktop-guide/xaml-services/xstatic-markup-extension.md b/dotnet-desktop-guide/xaml-services/xstatic-markup-extension.md new file mode 100644 index 0000000000..518407ce06 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xstatic-markup-extension.md @@ -0,0 +1,84 @@ +--- +title: "x:Static Markup Extension" +ms.date: "03/30/2017" +f1_keywords: + - "StaticExtension" + - "xStatic" + - "x:Static" +helpviewer_keywords: + - "x:Static markup extension [XAML Services]" + - "Static markup extension in XAML [XAML Services]" + - "XAML [XAML Services], x:Static markup extension" +ms.assetid: 056aee79-7cdd-434f-8174-dfc856cad343 +--- +# x:Static Markup Extension + +References any static by-value code entity that is defined in a Common Language Specification (CLS)–compliant way. The static property that is referenced can be used to provide the value of a property in XAML. + +## XAML Attribute Usage + +```xaml + +``` + +## XAML Values + +| | | +|-|-| +|`prefix`|Optional. A prefix that refers to a mapped, non-default XAML namespace. `prefix` is shown explicitly in the usage because you rarely reference static properties that come from a default XAML namespace. See Remarks.| +|`typeName`|Required. The name of the type that defines the desired static member.| +|`staticMemberName`|Required. The name of the desired static value member (a constant, a static property, a field, or an enumeration value).| + +## Remarks + +The code entity that is referenced must be one of the following: + +- A constant +- A static property +- A field +- An enumeration value + +Specifying any other code entity, such as a nonstatic property, causes a compile-time error if the XAML is markup compiled, or a XAML load-time parse exception. + +You can make `x:Static` references to static fields or properties that are not in the default XAML namespace for the current XAML document; however, this requires a prefix mapping. XAML namespaces are almost always defined on the root element of the XAML document. + +The lookup operations for static properties can be performed by .NET XAML Services and its XAML readers and XAML writers, when they are running with the default XAML schema context. This XAML schema context can use CLR reflection to provide the necessary static values for object graph construction. The `typeName` you specify is actually a XAML type name, not a CLR type name, although these are essentially the same name when using the default XAML schema context or when using all existing CLR-based XAML-implementing frameworks. + +Use caution when you make `x:Static` references that are not directly the type of a property's value. In the XAML processing sequence, provided values from a markup extension do not invoke additional value conversion. This is true even if your `x:Static` reference creates a text string, and a value conversion for attribute values based on text string typically occurs either for that specific member or for any member values of the return type. + +Attribute syntax is the most common syntax used with this markup extension. The string token provided after the `x:Static` identifier string is assigned as the value of the underlying extension class. + +There are two other XAML usages that are technically possible. However, these usages are less common because they are unnecessarily verbose: + +01. Object element syntax. + + ```xaml + + ``` + +02. Attribute syntax with explicit Member property for initialization string. + + ```xaml + + ``` + +In .NET XAML Services implementation, the handling for this markup extension is defined by the class. + +`x:Static` is a markup extension. All markup extensions in XAML use the `{` and `}` characters in their attribute syntax, which is the convention by which a XAML processor recognizes that a markup extension must provide a value. For more information about markup extensions, see [Markup Extensions for XAML Overview](markup-extensions-overview.md). + +## WPF Usage Notes + +The default XAML namespace you use for WPF programming does not contain many useful static properties, and most of the useful static properties have support such as type converters that facilitate the usage without requiring `{x:Static}` . For static properties, you must map a prefix for a XAML namespace if one of the following is true: + +- You are referencing a type that exists in WPF but is not part of the default XAML namespace for WPF (`http://schemas.microsoft.com/winfx/2006/xaml/presentation`). This is a fairly common scenario for using `x:Static`. For example, you might use an `x:Static` reference with a XAML namespace mapping to the CLR namespace and mscorlib assembly in order to reference the static properties of the class. + +- You are referencing a type from a custom assembly. + +- You are referencing a type that exists in a WPF assembly, but that type is within a CLR namespace that was not mapped to be part of the WPF default XAML namespace. The mapping of CLR namespaces into the default XAML namespace for WPF is performed by definitions in the various WPF assemblies (for more information about this concept, see [XAML Namespaces and Namespace Mapping for WPF XAML](../framework/wpf/advanced/xaml-namespaces-and-namespace-mapping-for-wpf-xaml.md)). Non-mapped CLR namespaces can exist if that CLR namespace is composed mostly of class definitions that are not typically intended for XAML, such as . + +For more information on how to use prefixes and XAML namespaces for WPF, see [XAML Namespaces and Namespace Mapping for WPF XAML](../framework/wpf/advanced/xaml-namespaces-and-namespace-mapping-for-wpf-xaml.md). + +## See also + +- [x:Type Markup Extension](xtype-markup-extension.md) +- [Types Migrated from WPF to System.Xaml](../framework/wpf/advanced/types-migrated-from-wpf-to-system.md) diff --git a/dotnet-desktop-guide/xaml-services/xsubclass-directive.md b/dotnet-desktop-guide/xaml-services/xsubclass-directive.md new file mode 100644 index 0000000000..4a2a9d9d12 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xsubclass-directive.md @@ -0,0 +1,60 @@ +--- +title: "x:Subclass Directive" +ms.date: "03/30/2017" +f1_keywords: + - "Subclass" + - "xSubclass" + - "x:Subclass" +helpviewer_keywords: + - "x:Subclass attribute [XAML Services]" + - "XAML [XAML Services], x:Subclass attribute" + - "Subclass attribute in XAML [XAML Services]" +ms.assetid: 99f66072-8107-4362-ab99-8171dc83b469 +--- +# x:Subclass Directive + +Modifies XAML markup compile behavior when `x:Class` is also provided. Instead of creating a partial class that is based on `x:Class`, the provided `x:Class` is created as an intermediate class, and then your provided derived class is expected to be based on `x:Class`. + +## XAML Attribute Usage + +```xaml + + ... + +``` + +## XAML Values + +||| +|-|-| +|`namespace`|Optional. Specifies a CLR namespace that contains `classname`. If `namespace` is specified, a dot (.) separates `namespace` and `classname`.| +|`classname`|Required. Specifies the CLR name of the partial class that connects the loaded XAML and your code-behind for that XAML. See Remarks.| +|`subclassNamespace`|Optional. Can be different from `namespace` if each namespace can resolve the other. Specifies a CLR namespace that contains `subclassName`. If `subclassName` is specified, a dot (.) separates `subclassNamespace` and `subclassName`.| +|`subclassName`|Required. Specifies the CLR name of the subclass.| + +## Dependencies + +[x:Class Directive](xclass-directive.md) must also be provided on the same object, and that object must be the root element of the XAML production. + +## Remarks + +`x:Subclass` usage is primarily intended for languages that do not support partial class declarations. + +The class used as the `x:Subclass` cannot be a nested class, and `x:Subclass` must refer to the root object as explained in the "Dependencies" section. + +Otherwise, the conceptual meaning of `x:Subclass` is undefined by a .NET XAML Services implementation. This is because .NET XAML Services behavior does not specify the overall programming model by which XAML markup and backing code are connected. Implementations of further concepts related to `x:Class` and `x:Subclass` are performed by specific frameworks that use programming models or application models to define how to connect XAML markup, compiled markup, and CLR-based code-behind. Each framework might have its own build actions that enable some of the behavior, or specific components that must be included in the build environment. Within a framework, build actions can also vary based on the specific CLR language that is used for the code-behind. + +## WPF Usage Notes + +`x:Subclass` can be on a page root or on the root in the application definition, which already has `x:Class`. Declaring `x:Subclass` on any element other than a page or application root, or specifying it where no `x:Class` exists, causes a compile-time error. + +Creating derived classes that work correctly for the `x:Subclass` scenario is fairly complex. You might need to examine the intermediate files (the .g files produced in the obj folder of your project by markup compile, with names that incorporate the .xaml file names). These intermediate files can help you determine the origin of certain programming constructs in the joined partial classes in the compiled application. + +Event handlers in the derived class must be `internal override` (`Friend Overrides` in Microsoft Visual Basic) in order to override the stubs for the handlers as created in the intermediate class during compilation. Otherwise, the derived class implementations hide (shadow) the intermediate class implementation and the intermediate class handlers are not invoked. + +When you define both `x:Class` and `x:Subclass`, you do not need to provide any implementation for the class that is referenced by `x:Class`. You only need to give it a name via the `x:Class` attribute so that the compiler has some guidance for the class that it creates in the intermediate files (the compiler does not select a default name in this case). You can give the `x:Class` class an implementation; however, this is not the typical scenario for using both `x:Class` and `x:Subclass`. + +## See also + +- [x:Class Directive](xclass-directive.md) +- [XAML and Custom Classes for WPF](../framework/wpf/advanced/xaml-and-custom-classes-for-wpf.md) diff --git a/dotnet-desktop-guide/xaml-services/xtype-markup-extension.md b/dotnet-desktop-guide/xaml-services/xtype-markup-extension.md new file mode 100644 index 0000000000..1c645a4a85 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xtype-markup-extension.md @@ -0,0 +1,86 @@ +--- +title: "x:Type Markup Extension" +ms.date: "03/30/2017" +f1_keywords: + - "x:TypeExtension" + - "Type" + - "x:Type" + - "xType" + - "TypeExtension" +helpviewer_keywords: + - "x:Type markup extension [XAML Services]" + - "XAML [XAML Services], x:Type markup extension" + - "XAML [XAML Services], TargetType attribute" + - "TargetType attribute [XAML Services]" + - "Type markup extension in XAML [XAML Services]" +ms.assetid: e0e0ce6f-e873-49c7-8ad7-8b840eb353ec +--- +# x:Type Markup Extension + +Supplies the CLR object that is the underlying type for a specified XAML type. + +## XAML Attribute Usage + +```xaml + +``` + +## XAML Object Element Usage + +```xaml + +``` + +## XAML Values + +||| +|-|-| +|`prefix`|Optional. A prefix that maps a non-default XAML namespace. Specifying a prefix is frequently not necessary. See Remarks.| +|`typeNameValue`|Required. A type name resolvable to the current default XAML namespace; or the specified mapped prefix if `prefix` is supplied.| + +## Remarks + +The `x:Type` markup extension has a similar function to the `typeof()` operator in C# or the `GetType` operator in Microsoft Visual Basic. + +The `x:Type` markup extension supplies a from-string conversion behavior for properties that take the type . The input is a XAML type. The relationship between the input XAML type and the output CLR is that the output is the of the input , after looking up the necessary based on XAML schema context and the service the context provides. + +In .NET XAML Services, the handling for this markup extension is defined by the class. + +In specific framework implementations, some properties that take as a value can accept the name of the type directly (the string value of the type `Name`). However, implementing this behavior is a complex scenario. For examples, see the "WPF Usage Notes" section that follows. + +Attribute syntax is the most common syntax used with this markup extension. The string token provided after the `x:Type` identifier string is assigned as the value of the underlying extension class. Under the default XAML schema context for .NET XAML Services, which is based on CLR types, the value of this attribute is either the of the desired type, or contains that preceded by a prefix for a non-default XAML namespace mapping. + +The `x:Type` markup extension can be used in object element syntax. In this case, specifying the value of the property is required to properly initialize the extension. + +The `x:Type` markup extension can also be used as a verbose attribute; however this use is not typical: `` + +## WPF Usage Notes + +### Default XAML Namespace and Type Mapping + +The default XAML namespace for WPF programming contains most of the XAML types you need for typical XAML scenarios; therefore, you can often avoid prefixes when referencing XAML type values. You might need to map a prefix if you are referencing a type from a custom assembly or for types that exist in a WPF assembly but are from a CLR namespace that was not mapped to the default XAML namespace. For more information about prefixes, XAML namespaces, and mapping CLR namespaces, see [XAML Namespaces and Namespace Mapping for WPF XAML](../framework/wpf/advanced/xaml-namespaces-and-namespace-mapping-for-wpf-xaml.md). + +### Type Properties That Support Typename-as-String + +WPF supports techniques that enable specifying the value of some properties of type without requiring an `x:Type` markup extension usage. Instead, you can specify the value as a string that names the type. Examples of this are and . Support for this behavior is not provided through either type converters or markup extensions. Instead, this is a deferral behavior implemented through . + +Silverlight supports a similar convention. In fact, Silverlight does not currently support `{x:Type}` in its XAML language support, and does not accept `{x:Type}` usages outside of a few circumstances that are intended to support WPF-Silverlight XAML migration. Therefore, the typename-as-string behavior is built-in to all Silverlight native property evaluation where a is the value. + +## XAML 2009 + +XAML 2009 provides additional support for generic types and modifies the feature behavior of `x:TypeArguments` and `x:Type` to provide this support. + +- `x:TypeArguments` and the associated object element for a generic object instantiation can be on elements other than the root. For more information, see the "XAML 2009" section of [x:TypeArguments Directive](xtypearguments-directive.md). + +- XAML 2009 supports a syntax for specifying a generic type's constraint in markup. This can be used by `x:TypeArguments`, by `x:Type`, or by the two features in combination. + +- WPF XAML implementation when processing XAML 2009 for load also adds this capability to the implicit type conversion behavior for certain framework properties that use type . + +In WPF, you can use XAML 2009 features but only for loose XAML (XAML that is not markup-compiled). Markup-compiled XAML for WPF and the BAML form of XAML do not currently support the XAML 2009 keywords and features. + +## See also + +- +- [Styling and Templating](../net/wpf/fundamentals/styles-templates-overview.md) +- [XAML Overview (WPF)](../net/wpf/fundamentals/xaml.md) +- [Markup Extensions and WPF XAML](../framework/wpf/advanced/markup-extensions-and-wpf-xaml.md) diff --git a/dotnet-desktop-guide/xaml-services/xtypearguments-directive.md b/dotnet-desktop-guide/xaml-services/xtypearguments-directive.md new file mode 100644 index 0000000000..cfc09f374a --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xtypearguments-directive.md @@ -0,0 +1,91 @@ +--- +title: "x:TypeArguments Directive" +ms.date: "03/30/2017" +f1_keywords: + - "x:TypeArguments" + - "xTypeArguments" + - "TypeArguments" +helpviewer_keywords: + - "x:TypeArguments attribute [XAML Services]" + - "TypeArguments attribute in XAML [XAML Services]" + - "XAML [XAML Services], x:TypeArguments attribute" +ms.assetid: 86561058-d393-4a44-b5c3-993a4513ea74 +--- +# x:TypeArguments Directive + +Passes constraining type arguments of a generic to the constructor of the generic type. + +## XAML Attribute Usage + +```xaml + +``` + +## XAML Values + +||| +|-|-| +|`object`|An object element declaration of a XAML type, which is backed by a CLR generic type. If `object` refers to a XAML type that is not from the default XAML namespace, `object` requires a prefix to indicate the XAML namespace where `object` exists.| +|`typeString`|A string that declares one or more XAML type names as strings, which supplies the type arguments for the CLR generic type. See Remarks for additional syntax notes.| + +## Remarks + +In most cases, the XAML types that are used as an information item in a `typeString` string are prefixed. Typical types of CLR generic constraints (for example, and ) come from CLR base class libraries. Those libraries are not mapped to typical framework-specific default XAML namespaces, and therefore, require a prefix mapping for XAML usage. + +You can specify more than one XAML type name by using a comma delimiter. + +If the generic constraints themselves use generic types, the nested constraint type arguments can be contained by parentheses (). + +Note that this definition of `x:TypeArguments` is specific to .NET XAML Services and using CLR backing. A language-level definition can be found in [\[MS-XAML\] Section 5.3.11](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +## Usage Examples + +For these examples, assume that the following XAML namespace definitions are declared: + +```xaml +xmlns:sys="clr-namespace:System;assembly=mscorlib" +xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib" +``` + +### List\ + +`` instantiates a new with a type argument. + +### Dictionary\ + +`` instantiates a new with two type arguments. + +### Queue> + +`` instantiates a new that has a constraint of with the inner constraint type arguments and . + +## XAML 2006 and WPF Generic XAML Usages + +For XAML 2006 usage, and XAML that is used for WPF applications, the following restrictions exist for `x:TypeArguments` and generic type usages from XAML in general: + +- Only the root element of a XAML file can support a generic XAML usage that references a generic type. + +- The root element must map to a generic type with at least one type argument. An example is . The page functions are the primary scenario for XAML generic usage support in WPF. + +- The root element XAML object element for the generic must also declare a partial class using `x:Class`. This is true even if defining a WPF build action. + +- `x:TypeArguments` cannot reference nested generic constraints. + +## XAML 2009 or XAML 2006 with No WPF 3.0 or WPF 3.5 Dependency + +In .NET XAML Services for either XAML 2006 or XAML 2009, the WPF-related restrictions on generic XAML usage are relaxed. You can instantiate a generic object element at any position in XAML markup that the backing type system and object model can support. + +If you use XAML 2009 instead of mapping the CLR base types to obtain XAML types for common language primitives, you can use [Built-in Types for Common XAML Language Primitives](types-for-primitives.md) as information items in a `typeString`. For example, you could declare the following (prefix mappings not shown, but x is the XAML language XAML namespace for XAML 2009): + +```xaml + +``` + +In WPF and when targeting .NET Framework 4 or .NET Core 3.0 (or later), you can use XAML 2009 features together with `x:TypeArguments` but only for loose XAML (XAML that is not markup-compiled). Markup-compiled XAML for WPF and the BAML form of XAML do not currently support the XAML 2009 keywords and features. If you need to markup compile the XAML, you must operate under the restrictions noted in the [XAML 2006 and WPF Generic XAML Usages](#xaml-2006-and-wpf-generic-xaml-usages) section. BAML is only supported in .NET Framework. + +## See also + +- [x:Class Directive](xclass-directive.md) +- [x:Type Markup Extension](xtype-markup-extension.md) +- [Built-in Types for Common XAML Language Primitives](types-for-primitives.md) +- [Generics in XAML](generics.md) diff --git a/dotnet-desktop-guide/xaml-services/xuid-directive.md b/dotnet-desktop-guide/xaml-services/xuid-directive.md new file mode 100644 index 0000000000..d46b66afe7 --- /dev/null +++ b/dotnet-desktop-guide/xaml-services/xuid-directive.md @@ -0,0 +1,45 @@ +--- +title: "x:Uid Directive" +ms.date: "03/30/2017" +helpviewer_keywords: + - "XAML [XAML Services], localizable content attribute" + - "XAML [XAML Services], x:Uid attribute" + - "x:Uid attribute [XAML Services]" + - "Uid attribute [XAML Services]" +ms.assetid: 81defade-483b-4a89-b76d-9b25bba34010 +--- +# x:Uid Directive + +Provides a unique identifier for markup elements. In many scenarios, this unique identifier is used by XAML localization processes and tools. + +## XAML Attribute Usage + +```xaml + +``` + +## XAML Values + +||| +|-|-| +|`identifier`|A manually created or autogenerated string that should be unique in a file when it is interpreted by an `x:Uid` consumer.| + +## Remarks + +In [MS-XAML], `x:Uid` is defined as a directive. For more information, see [\[MS-XAML\] Section 5.3.6](https://docs.microsoft.com/previous-versions/msp-n-p/ff650760(v=pandp.10)). + +`x:Uid` is discrete from `x:Name` both because of the stated XAML localization scenario and so that identifiers that are used for localization have no dependencies on the programming model implications of `x:Name`. Also, `x:Name` is governed by the XAML namescope; however, `x:Uid` is not governed by any XAML language defined concept of uniqueness enforcement. XAML processors in a broad sense (processors that are not part of the localization process) are not expected to enforce uniqueness of `x:Uid` values. That responsibility is conceptually on the originator of the values. The expectation of uniqueness of `x:Uid` values within a single XAML source is reasonable for consumers of the values, such as dedicated globalization processes or tools. The typical uniqueness model is that `x:Uid` values are unique within an XML-encoded file that represents XAML. + +Tools that have significant knowledge of a particular XAML schema can choose to apply `x:Uid` only for true localizable strings, instead of for all cases where a text string value is encountered in markup. + +Frameworks can specify a particular property in their object model to be an alias for `x:Uid` by applying the attribute to the defining type. If a framework specifies a particular property, it is not valid to specify both `x:Uid` and the aliased member on the same object. If both `x:Uid` and the aliased member are specified, .NET XAML Services API typically throws for this case. + +## WPF Usage Notes + +For more information about the role of `x:Uid` in the WPF localization process and in the BAML form of XAML, see [Globalization for WPF](../framework/wpf/advanced/globalization-for-wpf.md) or + +## See also + +- +- +- [Globalization for WPF](../framework/wpf/advanced/globalization-for-wpf.md)