달력

8

« 2025/8 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
2017. 1. 10. 03:39

Data Binding 프로그래밍/WPF2017. 1. 10. 03:39


  1. Data Binding Overview
  2. Binding Sources Overview
  3. Data Templating Overview
  4. Binding Declarations Overview
  5. How to: Create a Simple Binding 
  6. How to: Specify the Binding Source 
  7. How to: Make Data Available for Binding in XAML 
  8. How to: Control When the TextBox Text Updates the Source 
  9. How to: Specify the Direction of the Binding 
  10. How to: Bind to a Collection and Display Information Based on Selection 
  11. How to: Bind to an Enumeration 
  12. How to: Bind the Properties of Two Controls 
  13. How to: Implement Binding Validation 
  14. How to: Implement Validation Logic on Custom Objects 
  15. How to: Get the Binding Object from a Bound Target Property 
  16. How to: Implement a CompositeCollection 
  17. How to: Convert Bound Data 
  18. How to: Create a Binding in Code 
  19. How to: Get the Default View of a Data Collection 
  20. How to: Navigate Through the Objects in a Data CollectionView 
  21. How to: Filter Data in a View 
  22. How to: Sort Data in a View 
  23. How to: Sort and Group Data Using a View in XAML 
  24. How to: Use the Master-Detail Pattern with Hierarchical Data 
  25. How to: Use the Master-Detail Pattern with Hierarchical XML Data 
  26. How to: Produce a Value Based on a List of Bound Items 
  27. How to: Implement Property Change Notification 
  28. How to: Create and Bind to an ObservableCollection 
  29. How to: Implement PriorityBinding 
  30. How to: Bind to XML Data Using an XMLDataProvider and XPath Queries 
  31. How to: Bind to XDocument, XElement, or LINQ for XML Query Results
  32. How to: Use XML Namespaces in Data Binding 
  33. How to: Bind to an ADO.NET Data Source 
  34. How to: Bind to a Method 
  35. How to: Set Up Notification of Binding Updates 
  36. How to: Clear Bindings 
  37. How to: Find DataTemplate-Generated Elements 
  38. How to: Bind to a Web Service 
  39. How to: Bind to the Results of a LINQ Query 





Data Binding


https://msdn.microsoft.com/en-us/library/ms750612(v=vs.110).aspx



Data Binding Overview



Windows Presentation Foundation (WPF) data binding provides a simple and consistent way for applications to present and interact with data. Elements can be bound to data from a variety of data sources in the form of common language runtime (CLR) objects and XML. ContentControls such as Button and ItemsControls such as ListBox and ListView 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 a broad range of properties that inherently support data binding, flexible UI representation of data, and clean separation of business logic from UI.

This topic first discusses concepts fundamental to WPF data binding and then goes into the usage of the Binding class and other features of data binding.

What Is Data Binding?

Data binding is the process that establishes a connection between the application UI and business logic. If the binding has the correct settings and the data provides the proper notifications, then, 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 the binding of a broad range of properties to a variety of data sources. In WPF, dependency properties of elements can be bound to CLR 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 application UI from the Data Binding Demo:

Data binding sample screen shot

The above is the UI of an application that displays a list of auction items. The application 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 DescriptionStartPriceStartDateCategorySpecialFeatures, etc.

  • The data (AuctionItem objects) displayed in the ListBox is templated so that the description and the current price are shown for each item. This is done using a DataTemplate. 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 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. This is done using a collection view. The Binding to Collections section discusses collection views.

  • When the user selects an item, the ContentControl displays the details of the selected item. This is called the Master-Detail scenario. The Master-Detail Scenario section provides information about this type of binding scenario.

  • The type of the StartDate property is DateTime, which returns a date that includes the time to the millisecond. In this application, a custom converter has been used so that a shorter date string is displayed. The Data Conversion section provides information about converters.

When the user clicks the Add Product button, the following form comes up:

Add Product Listing page

The user can edit the fields in the form, preview the product listing using the short preview and the more detailed preview panes, and then click submit to add the new product listing. Any existing grouping, filtering and sorting functionalities 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 TextBox. If the user enters an invalid date (invalid formatting or a past date), the user will be notified with a ToolTip and a red exclamation point next to the TextBox. The Data Validation section discusses how to create validation logic.

Before going into the different features of data binding outlined above, we will first discuss in the next section 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:

Basic data binding diagram

As illustrated by the above figure, 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 these four components: a binding target object, a target property, a binding source, and 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 Name property of an Employee object, your target object is the TextBox, the target property is the Text property, the value to use is Name, and the source object is the Employee object.

  • The target property must be a dependency property. Most UIElement properties are dependency properties and most dependency properties, except read-only ones, support data binding by default. (Only DependencyObject types can define dependency properties and all UIElements derive from DependencyObject.)

  • Although not specified in the figure, it should be noted that the binding source object is not restricted to being a custom CLR object. WPF data binding supports data in the form of CLR objects and XML. To provide some examples, your binding source may be a UIElement, any list object, a CLR object that is associated with ADO.NET data or Web Services, or an XmlNode that contains your XML data. For more information, see Binding Sources Overview.

As you read through other software development kit (SDK) topics, 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 ListBox using data binding, you are binding your ListBox to the XML data.

To establish a binding, you use the Binding object. The rest of this topic discusses many of the concepts associated with and some of the properties and usage of the Binding object.

Direction of the Data Flow

As mentioned previously and as indicated by the arrow in the figure above, 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 gets updated with changes in the binding source) if the binding source provides the proper notifications.

You may want your application 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 this by setting the Mode property of your Binding object. The following figure illustrates the different types of data flow:

Data binding data flow
  • OneWay 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 OneWay binding mode avoids the overhead of the TwoWay binding mode.

  • TwoWay 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 OneWay binding, but some dependency properties (typically properties of user-editable controls such as the Text property of TextBox and the IsChecked property of CheckBox) default to TwoWay binding. A programmatic way to determine whether a dependency property binds one-way or two-way by default is to get the property metadata of the property using GetMetadata and then check the Boolean value of the BindsTwoWayByDefault property.

  • OneWayToSource is the reverse of OneWay binding; it updates the source property when the target property changes. One example scenario is if you only need to re-evaluate the source value from the UI.

  • Not illustrated in the figure is OneTime binding, which causes the source property to initialize the target property, but subsequent changes do not propagate. This means that if the data context undergoes a change or the object in the data context changes, then the change is not reflected in the target property. This type of binding is appropriate if you are using data where either a snapshot of the current state is appropriate to use 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 is essentially a simpler form of OneWay binding that provides better performance in cases where the source value does not change.

Note that to detect source changes (applicable to OneWay and TwoWay bindings), the source must implement a suitable property change notification mechanism such as INotifyPropertyChanged. See How to: Implement Property Change Notification for an example of an INotifyPropertyChanged implementation.

The Mode property page 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 TwoWay or OneWayToSource listen for changes in the target property and propagate them back to the source. This is known as updating the source. For example, you may edit the text of a TextBox to change the underlying source value. As described in the last section, the direction of the data flow is determined by the value of the Mode property of the binding.

However, does your source value get updated while you are editing the text or after you finish editing the text and point your mouse away from the TextBox? The UpdateSourceTrigger property of the binding determines what triggers the update of the source. The dots of the right arrows in the following figure illustrate the role of the UpdateSourceTrigger property:

UpdateSourceTrigger diagram

If the UpdateSourceTrigger value is PropertyChanged, then the value pointed to by the right arrow of TwoWay or the OneWayToSource bindings gets updated as soon as the target property changes. However, if the UpdateSourceTrigger value is LostFocus, then that value only gets updated with the new value when the target property loses focus.

Similar to the Mode property, different dependency properties have different default UpdateSourceTrigger values. The default value for most dependency properties is PropertyChanged, while the Text property has a default value of LostFocus. This means that source updates usually happen whenever the target property changes, which is fine for CheckBoxes and other simple controls. However, for text fields, updating after every keystroke can diminish performance and it denies the user the usual opportunity to backspace and fix typing errors before committing to the new value. That is why the Text property has a default value of LostFocus instead of PropertyChanged.

See the UpdateSourceTrigger property page for information about how to find the default UpdateSourceTrigger value of a dependency property.

The following table provides an example scenario for each UpdateSourceTrigger value using the TextBox as an example:

UpdateSourceTrigger value

When the Source Value Gets Updated

Example Scenario for TextBox

LostFocus (default for TextBox.Text)

When the TextBox control loses focus

TextBox that is associated with validation logic (see Data Validation section)

PropertyChanged

As you type into the TextBox

TextBox controls in a chat room window

Explicit

When the application calls UpdateSource

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.

Creating a Binding

To recapitulate some of the concepts discussed in the previous sections, you establish a binding using the Binding object, and each binding usually has four components: binding target, target property, 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 class has a string property named ColorName, of which the value is set to "Red". Thus, this example generates a button with a red background.

<DockPanel
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:c="clr-namespace:SDKSample">
  <DockPanel.Resources>
    <c:MyData x:Key="myDataSource"/>
  </DockPanel.Resources>
  <DockPanel.DataContext>
    <Binding Source="{StaticResource myDataSource}"/>
  </DockPanel.DataContext>
  <Button Background="{Binding Path=ColorName}"
          Width="150" Height="30">I am bound to be RED!</Button>
</DockPanel>

For more details on the binding declaration syntax and for examples of how to set up a binding in code, see Binding Declarations Overview.

If we apply this example to our basic diagram, the resulting figure looks like the following. This is a OneWay binding because the Background property supports OneWay binding by default.

Data binding diagram

You may wonder why this works even though the ColorName property is of type string while the Background property is of type Brush. This is default type conversion at work and is discussed in the Data Conversion section.

Specifying the Binding Source

Notice that in the previous example, the binding source is specified by setting the DataContext property on the DockPanel element. The Button then inherits the DataContext value from the DockPanel, 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 DataContext 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 DataContext property, you can specify the binding source by setting the Source property directly on the binding declaration of the button, as in the following example:

<DockPanel.Resources>
  <c:MyData x:Key="myDataSource"/>
</DockPanel.Resources>
<Button Width="150" Height="30"
        Background="{Binding Source={StaticResource myDataSource},
                             Path=ColorName}">I am bound to be RED!</Button>

Other than setting the DataContext property on an element directly, inheriting the DataContext value from an ancestor (such as the button in the first example), and explicitly specifying the binding source by setting the Source property on the Binding (such as the button the last example), you can also use the ElementName property or the RelativeSource property to specify the binding source. The ElementName property is useful when you are binding to other elements in your application, such as when you are using a slider to adjust the width of a button. The RelativeSource property is useful when the binding is specified in a ControlTemplate or a Style. For more information, see How to: Specify the Binding Source.

Specifying the Path to the Value

If your binding source is an object, you use the Path property to specify the value to use for your binding. If you are binding to XML data, you use the XPath property to specify the value. In some cases, it may be applicable to use the Path 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 Path property in addition to the XPath property.

For syntax information and examples, see the Path and XPath property pages.

Note that although we have emphasized that the Path to the value to use is one of the four necessary components of a binding, in the scenarios which 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 Path. Consider the following example:

<ListBox ItemsSource="{Binding}"
         IsSynchronizedWithCurrentItem="true"/>

The above example uses the empty binding syntax: {Binding}. In this case, the ListBox 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 ItemsSource property to the entire object. (See the 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 string and you 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.

Note that 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 for information about converters.

Binding and BindingExpression

Before getting into other features and usages of data binding, it would be useful to introduce the BindingExpression class. As you have seen in previous sections, the Binding class is the high-level class for the declaration of a binding; the Binding class provides many properties that allow you to specify the characteristics of a binding. A related class, BindingExpression, 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 BindingExpression is an instance expression that cannot be shared and contains all the instance information of the Binding.

For example, consider the following, where myDataObject is an instance of MyData class, myBinding is the source Binding object, and MyData class is a defined class that contains a string property named MyDataProperty. This example binds the text content of mytext, an instance of TextBlock, to MyDataProperty.

//make a new source
  MyData myDataObject = new MyData(DateTime.Now);      
  Binding myBinding = new Binding("MyDataProperty");
  myBinding.Source = myDataObject;
  myText.SetBinding(TextBlock.TextProperty, myBinding);

You can use the same myBinding object to create other bindings. For example, you may use myBinding object to bind the text content of a check box to MyDataProperty. In that scenario, there will be two instances of BindingExpression sharing the myBinding object.

BindingExpression object can be obtained through the return value of calling GetBindingExpression on a data-bound object. The following topics demonstrate some of the usages of the BindingExpression class:

Data Conversion

In the previous example, the button is red because its Background property is bound to a string property with the value "Red". This works because a type converter is present on the Brush type to convert the string value to a Brush.

To add this information to the figure in the Creating a Binding section, the diagram looks like the following:

Data binding diagram

However, what if instead of having a property of type string your binding source object has a Color property of type Color? In that case, in order for the binding to work you would need to first turn the Color property value into something that the Background property accepts. You would need to create a custom converter by implementing the IValueConverter interface, as in the following example:

[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;
    }
}

The IValueConverter reference page provides more information.

Now the custom converter is used instead of default conversion, and our diagram looks like this:

Data binding diagram

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.

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 values or standards 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 to 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.

  • So far we have not yet discussed MultiBinding, where a target property has a collection of bindings. In the case of a MultiBinding, you use a custom IMultiValueConverter 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 the MultiBinding class page for examples and information.

Binding to Collections

A binding source object can be treated either as a single object of which the 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 ItemsControl such as a ListBoxListView, or TreeView to display a data collection, such as in the application shown in the What Is Data Binding? section.

Fortunately, our basic diagram still applies. If you are binding an ItemsControl to a collection, the diagram looks like this:

Data binding ItemsControl diagram

As shown in this diagram, to bind an ItemsControl to a collection object, ItemsSource property is the property to use. You can think of ItemsSource property as the content of the ItemsControl. Note that the binding is OneWay because the ItemsSource property supports OneWay binding by default.

How to Implement Collections

You can enumerate over any collection that implements the IEnumerable interface. However, to set up dynamic bindings so that insertions or deletions in the collection update the UI automatically, the collection must implement the INotifyCollectionChanged interface. This interface exposes an event that should be raised whenever the underlying collection changes.

WPF provides the ObservableCollection<T> class, which is a built-in implementation of a data collection that exposes the INotifyCollectionChanged interface. Note that to fully support transferring data values from source objects to targets, each object in your collection that supports bindable properties must also implement the INotifyPropertyChanged interface. For more information, see Binding Sources Overview.

Before implementing your own collection, consider using ObservableCollection<T> or one of the existing collection classes, such as List<T>Collection<T>, and BindingList<T>, among many others. If you have an advanced scenario and want to implement your own collection, consider using IList, which provides a non-generic collection of objects that can be individually accessed by index and thus the best performance.

Collection Views

Once your ItemsControl 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 ICollectionView 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 INotifyCollectionChanged interface, the changes raised by the CollectionChanged 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 application shown in the What Is Data Binding? section. The application is implemented such that the ListBox binds to a view over the data collection instead of the data collection directly. The following example is extracted from the Data Binding Demo application. The CollectionViewSource class is the Extensible Application Markup Language (XAML) proxy of a class that inherits from CollectionView. In this particular example, the Source of the view is bound to the AuctionItems collection (of type ObservableCollection<T>) of the current application object.

<Window.Resources>
<CollectionViewSource 
      Source="{Binding Source={x:Static Application.Current}, Path=AuctionItems}"   
      x:Key="listingDataView" />
</Window.Resources>

The resource listingDataView then serves as the binding source for elements in the application, such as the ListBox:

<ListBox Name="Master" Grid.Row="2" Grid.ColumnSpan="3" Margin="8"
    ItemsSource="{Binding Source={StaticResource listingDataView}}">
</ListBox>

To create another view for the same collection, you can create another CollectionViewSource instance and give it a different x:Key name.

The following table shows which view data types are created as the default collection view or by CollectionViewSource based on the source collection type.

Source collection type

Collection view type

Notes

IEnumerable

An internal type based on CollectionView

Cannot group items.

IList

ListCollectionView

Fastest.

IBindingList

BindingListCollectionView

 

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. Note that 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 GetDefaultView method. For an example, see How to: Get the Default View of a Data Collection.

Collection Views with ADO.NET DataTables

To improve performance, collection views for ADO.NET DataTable or DataView objects delegate sorting and filtering to the DataView. This 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 DataView 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 How to: Sort a GridView Column When a Header Is Clicked.

The following example shows the sorting logic of the "Sort by category and date" CheckBox of the application UI in the What Is Data Binding? section:

private void AddSorting(object sender, RoutedEventArgs args)
{
    // This sorts the items first by Category and within each Category,
    // by StartDate. Notice that because Category is an enumeration,
    // the order of the items is the same as in the enumeration declaration
    listingDataView.SortDescriptions.Add(
        new SortDescription("Category", ListSortDirection.Ascending));
    listingDataView.SortDescriptions.Add(
        new SortDescription("StartDate", ListSortDirection.Ascending));
}

Filtering

Views can also apply a filter to a collection. This means that although an item might exist in the collection, this particular view is intended to show only a certain subset of the full collection. You might filter on a condition in the data. For instance, as is done by the application in the What Is Data Binding? section, the "Show only bargains" CheckBox contains logic to filter out items that cost $25 or more. The following code is executed to set ShowOnlyBargainsFilter as the Filter event handler when that CheckBox is selected:

listingDataView.Filter += new FilterEventHandler(ShowOnlyBargainsFilter);

The ShowOnlyBargainsFilter event handler has the following implementation:

private void ShowOnlyBargainsFilter(object sender, FilterEventArgs e)
{
    AuctionItem product = e.Item as AuctionItem;
    if (product != null)
    {
        // Filter out products with price 25 or above
        if (product.CurrentPrice < 25)
        {
            e.Accepted = true;
        }
        else
        {
            e.Accepted = false;
        }
    }
}

If you are using one of the CollectionView classes directly instead of CollectionViewSource, you would use the Filter property to specify a callback. For an example, see How to: Filter Data in a View.

Grouping

Except for the internal class that views an IEnumerable collection, all collection views support the functionality of 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" CheckBox:

// This groups the items in the view by the property "Category"
PropertyGroupDescription groupDescription = new PropertyGroupDescription();
groupDescription.PropertyName = "Category";
listingDataView.GroupDescriptions.Add(groupDescription);

For another grouping example, see How to: Group Items in a ListView That Implements a GridView.

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 How to: Navigate Through the Objects in a Data CollectionView.

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.

<Button Content="{Binding }" />
<Button Content="{Binding Path=/}" />
<Button Content="{Binding Path=/Description}" /> 

The slash and property syntax can also be stacked to traverse a hierarchy of collections. The following example binds to the current item of a collection named Offices, which is a property of the current item of the source collection.

<Button Content="{Binding /Offices/}" />

The current item pointer can be affected by any sorting or filtering that is applied to the collection. Sorting preserves the current item pointer on the last item selected, but the collection view is now restructured around it. (Perhaps the selected item was at the beginning of the list before, but now the selected item might be somewhere in the middle.) Filtering preserves the selected item if that selection remains in view after the filtering. Otherwise, the current item pointer is set to the first item of the filtered collection view.

Master-Detail Binding Scenario

The notion of a current item is useful not only for navigation of items in a collection, but also for the master-detail binding scenario. Consider the application UI in the What Is Data Binding? section again. In that application, the selection within the ListBox determines the content shown in the ContentControl. To put it in another way, when a ListBox item is selected, the ContentControl shows the details of the selected item.

You can implement the master-detail scenario simply by having two or more controls bound to the same view. The following example from the Data Binding Demo shows the markup of the ListBox and the ContentControl you see on the application UI in the What Is Data Binding? section:

<ListBox Name="Master" Grid.Row="2" Grid.ColumnSpan="3" Margin="8"
    ItemsSource="{Binding Source={StaticResource listingDataView}}">
</ListBox>
<ContentControl Name="Detail" Grid.Row="3" Grid.ColumnSpan="3" 
        Content="{Binding Source={StaticResource listingDataView}}" 
        ContentTemplate="{StaticResource detailsProductListingTemplate}" 
        Margin="9,0,0,0"/>

Notice that both of the controls are bound to the same source, the listingDataView static resource (see the definition of this resource in the How to Create a View section). This works because when a singleton object (the ContentControl in this case) is bound to a collection view, it automatically binds to the CurrentItem of the view. Note that CollectionViewSource objects automatically synchronize currency and selection. If your list control is not bound to a CollectionViewSource object as in this example, then you would need to set its IsSynchronizedWithCurrentItem property to true for this to work.

For other examples, see How to: Bind to a Collection and Display Information Based on Selection and How to: Use the Master-Detail Pattern with Hierarchical Data.

You may have noticed that the above example uses a template. In fact, the data would not be displayed the way we wish without the use of templates (the one explicitly used by the ContentControl and the one implicitly used by the ListBox). We now turn to data templating in the next section.

Data Templating

Without the use of data templates, our application UI in the What Is Data Binding? section would look like the following:

Data Binding Demo without Data Templates

As shown in the example in the previous section, both the ListBox control and the ContentControl are bound to the entire collection object (or more specifically, the view over the collection object) of AuctionItems. Without specific instructions of how to display the data collection, the ListBox is displaying a string representation of each object in the underlying collection and the ContentControl is displaying a string representation of the object it is bound to.

To solve that problem, the application defines DataTemplates. As shown in the example in the previous section, the ContentControl explicitly uses the detailsProductListingTemplate DataTemplate. The ListBox control implicitly uses the following DataTemplate when displaying the AuctionItem objects in the collection:

<DataTemplate DataType="{x:Type src:AuctionItem}">
    <Border BorderThickness="1" BorderBrush="Gray"
            Padding="7" Name="border" Margin="3" Width="500">
        <Grid>
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
          </Grid.RowDefinitions>
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="86"/>
            <ColumnDefinition Width="*"/>
          </Grid.ColumnDefinitions>

            <Polygon Grid.Row="0" Grid.Column="0" Grid.RowSpan="4"
                     Fill="Yellow" Stroke="Black" StrokeThickness="1"
                     StrokeLineJoin="Round" Width="20" Height="20"
                     Stretch="Fill"
                     Points="9,2 11,7 17,7 12,10 14,15 9,12 4,15 6,10 1,7 7,7"
                     Visibility="Hidden" Name="star"/>

            <TextBlock Grid.Row="0" Grid.Column="1" Margin="0,0,8,0"
                       Name="descriptionTitle"
                       Style="{StaticResource smallTitleStyle}">Description:</TextBlock>
            <TextBlock Name="DescriptionDTDataType" Grid.Row="0" Grid.Column="2" 
                Text="{Binding Path=Description}" 
                Style="{StaticResource textStyleTextBlock}"/>

            <TextBlock Grid.Row="1" Grid.Column="1" Margin="0,0,8,0"
                       Name="currentPriceTitle"
                       Style="{StaticResource smallTitleStyle}">Current Price:</TextBlock>
            <StackPanel Grid.Row="1" Grid.Column="2" Orientation="Horizontal">
                <TextBlock Text="$" Style="{StaticResource textStyleTextBlock}"/>
                <TextBlock Name="CurrentPriceDTDataType" 
                    Text="{Binding Path=CurrentPrice}" 
                    Style="{StaticResource textStyleTextBlock}"/>
            </StackPanel>
        </Grid>
    </Border>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path=SpecialFeatures}">
            <DataTrigger.Value>
                <src:SpecialFeatures>Color</src:SpecialFeatures>
            </DataTrigger.Value>
          <DataTrigger.Setters>
            <Setter Property="BorderBrush" Value="DodgerBlue" TargetName="border" />
            <Setter Property="Foreground" Value="Navy" TargetName="descriptionTitle" />
            <Setter Property="Foreground" Value="Navy" TargetName="currentPriceTitle" />
            <Setter Property="BorderThickness" Value="3" TargetName="border" />
            <Setter Property="Padding" Value="5" TargetName="border" />
          </DataTrigger.Setters>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=SpecialFeatures}">
            <DataTrigger.Value>
                <src:SpecialFeatures>Highlight</src:SpecialFeatures>
            </DataTrigger.Value>
            <Setter Property="BorderBrush" Value="Orange" TargetName="border" />
            <Setter Property="Foreground" Value="Navy" TargetName="descriptionTitle" />
            <Setter Property="Foreground" Value="Navy" TargetName="currentPriceTitle" />
            <Setter Property="Visibility" Value="Visible" TargetName="star" />
            <Setter Property="BorderThickness" Value="3" TargetName="border" />
            <Setter Property="Padding" Value="5" TargetName="border" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

With the use of those two DataTemplates, the resulting UI is the one shown in the What Is Data Binding? section. As you can see from that screenshot, in addition to letting you place data in your controls, DataTemplates allow you to define compelling visuals for your data. For example, DataTriggers are used in the above DataTemplate so that AuctionItems with SpecialFeatures value of HighLight would be displayed with an orange border and a star.

For more information about data templates, see the Data Templating Overview.

Data Validation

Most applications that take user input need to have validation logic to ensure that the user has entered the expected information. The validation checks can be based on type, range, format, or other application-specific requirements. This section discusses how data validation works in the WPF.

Associating Validation Rules with a Binding

The WPF data binding model allows you to associate ValidationRules with your Binding object. For example, the following example binds a TextBox to a property named StartPrice and adds a ExceptionValidationRule object to the Binding.ValidationRules property.

<TextBox Name="StartPriceEntryForm" Grid.Row="2" Grid.Column="1"
    Style="{StaticResource textStyleTextBox}" Margin="8,5,0,5">
  <TextBox.Text>
    <Binding Path="StartPrice" UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <ExceptionValidationRule />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

ValidationRule object checks whether the value of a property is valid. WPF has the following two types of built-in ValidationRule objects:

You can also create your own validation rule by deriving from the ValidationRule class and implementing the Validate method. The following example shows the rule used by the Add Product Listing "Start Date" TextBox from the What Is Data Binding? section:

class FutureDateRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        DateTime date;
        try
        {
            date = DateTime.Parse(value.ToString());
        }
        catch (FormatException)
        {
            return new ValidationResult(false, "Value is not a valid date.");
        }
        if (DateTime.Now.Date > date)
        {
            return new ValidationResult(false, "Please enter a date in the future.");
        }
        else
        {
            return ValidationResult.ValidResult;
        }
    }
}

The StartDateEntryForm TextBox uses this FutureDateRule, as shown in the following example:

<TextBox Name="StartDateEntryForm" Grid.Row="3" Grid.Column="1" 
    Validation.ErrorTemplate="{StaticResource validationTemplate}" 
    Style="{StaticResource textStyleTextBox}" Margin="8,5,0,5">
    <TextBox.Text>
        <Binding Path="StartDate" UpdateSourceTrigger="PropertyChanged" 
            Converter="{StaticResource dateConverter}" >
            <Binding.ValidationRules>
                <src:FutureDateRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

Note that because the UpdateSourceTrigger value is PropertyChanged, the binding engine updates the source value on every keystroke, which means it also checks every rule in the ValidationRules collection on every keystroke. We discuss this further in the Validation Process section.

Providing Visual Feedback

If the user enters an invalid value, you may want to provide some feedback about the error on the application UI. One way to provide such feedback is to set the Validation.ErrorTemplate attached property to a custom ControlTemplate. As shown in the previous subsection, the StartDateEntryForm TextBox uses an ErrorTemplate called validationTemplate. The following example shows the definition of validationTemplate:

<ControlTemplate x:Key="validationTemplate">
  <DockPanel>
    <TextBlock Foreground="Red" FontSize="20">!</TextBlock>
    <AdornedElementPlaceholder/>
  </DockPanel>
</ControlTemplate>

The AdornedElementPlaceholder element specifies where the control being adorned should be placed.

In addition, you may also use a ToolTip to display the error message. Both the StartDateEntryForm and the StartPriceEntryForm TextBoxes use the style textStyleTextBox, which creates a ToolTip that displays the error message. The following example shows the definition of textStyleTextBox. The attached property Validation.HasError is true when one or more of the bindings on the properties of the bound element are in error.

<Style x:Key="textStyleTextBox" TargetType="TextBox">
  <Setter Property="Foreground" Value="#333333" />
  <Setter Property="MaxLength" Value="40" />
  <Setter Property="Width" Value="392" />
  <Style.Triggers>
    <Trigger Property="Validation.HasError" Value="true">
      <Setter Property="ToolTip"
        Value="{Binding RelativeSource={RelativeSource Self},
                        Path=(Validation.Errors)[0].ErrorContent}"/>
    </Trigger>
  </Style.Triggers>
</Style>

With the custom ErrorTemplate and the ToolTip, the StartDateEntryForm TextBox looks like the following when there is a validation error:

Data binding validation error

If your Binding has associated validation rules but you do not specify an ErrorTemplate on the bound control, a default ErrorTemplate will be used to notify users when there is a validation error. The default ErrorTemplate is a control template that defines a red border in the adorner layer. With the default ErrorTemplate and the ToolTip, the UI of the StartPriceEntryForm TextBox looks like the following when there is a validation error:

Data binding validation error

For an example of how to provide logic to validate all controls in a dialog box, see the Custom Dialog Boxes section in the Dialog Boxes Overview.

Validation Process

Validation usually occurs when the value of a target is transferred to the binding source property. This occurs on TwoWay and OneWayToSource bindings. To reiterate, what causes a source update depends on the value of the UpdateSourceTrigger property, as described in the What Triggers Source Updates section.

The following describes the validation process. Note that if a validation error or other type of error occurs at any time during this process, the process is halted.

  1. The binding engine checks if there are any custom ValidationRule objects defined whose ValidationStep is set to RawProposedValue for that Binding, in which case it calls the Validate method on each ValidationRule until one of them runs into an error or until all of them pass.

  2. The binding engine then calls the converter, if one exists.

  3. If the converter succeeds, the binding engine checks if there are any custom ValidationRule objects defined whose ValidationStep is set to ConvertedProposedValue for that Binding, in which case it calls the Validate method on each ValidationRule that has ValidationStep set to ConvertedProposedValue until one of them runs into an error or until all of them pass.

  4. The binding engine sets the source property.

  5. The binding engine checks if there are any custom ValidationRule objects defined whose ValidationStep is set to UpdatedValue for that Binding, in which case it calls the Validate method on each ValidationRule that has ValidationStep set to UpdatedValue until one of them runs into an error or until all of them pass. If a DataErrorValidationRule is associated with a binding and its ValidationStep is set to the default, UpdatedValue, the DataErrorValidationRule is checked at this point. This is also the point when bindings that have the ValidatesOnDataErrors set to true are checked.

  6. The binding engine checks if there are any custom ValidationRule objects defined whose ValidationStep is set to CommittedValue for that Binding, in which case it calls the Validate method on each ValidationRule that has ValidationStep set to CommittedValue until one of them runs into an error or until all of them pass.

If a ValidationRule does not pass at any time throughout this process, the binding engine creates a ValidationError object and adds it to the Validation.Errors collection of the bound element. Before the binding engine runs the ValidationRule objects at any given step, it removes any ValidationError that was added to the Validation.Errors attached property of the bound element during that step. For example, if a ValidationRule whose ValidationStep is set to UpdatedValue failed, the next time the validation process occurs, the binding engine removes that ValidationError immediately before it calls any ValidationRule that has ValidationStep set to UpdatedValue.

When Validation.Errors is not empty, the Validation.HasError attached property of the element is set to true. Also, if the NotifyOnValidationError property of the Binding is set to true, then the binding engine raises the Validation.Error attached event on the element.

Also note that a valid value transfer in either direction (target to source or source to target) clears the Validation.Errors attached property.

If the binding either has an ExceptionValidationRule associated with it, or had the ValidatesOnExceptions property is set to true and an exception is thrown when the binding engine sets the source, the binding engine checks to see if there is a UpdateSourceExceptionFilter. You have the option to use the UpdateSourceExceptionFilter callback to provide a custom handler for handling exceptions. If an UpdateSourceExceptionFilter is not specified on the Binding, the binding engine creates a ValidationError with the exception and adds it to the Validation.Errors collection of the bound element.

Debugging Mechanism

You can set the attached property PresentationTraceSources.TraceLevel on a binding-related object to receive information about the status of a specific binding.





Binding Sources Overview

In data binding, the binding source object refers to the object you obtain data from. This topic discusses the types of objects you can use as the binding source.

Binding Source Types

Windows Presentation Foundation (WPF) data binding supports the following binding source types:

Binding Source

Description

common language runtime (CLR) objects

You can bind to public properties, sub-properties, as well as indexers, of any common language runtime (CLR) object. The binding engine uses CLR reflection to get the values of the properties. Alternatively, objects that implement ICustomTypeDescriptor or have a registered TypeDescriptionProvider also work with the binding engine.

For more information about how to implement a class that can serve as a binding source, see Implementing a Class for the Binding Source later in this topic.

dynamic objects

You can bind to available properties and indexers of an object that implements the IDynamicMetaObjectProvider interface. If you can access the member in code, you can bind to it. For example, if a dynamic object enables you to access a member in code via someObjet.AProperty, you can bind to it by setting the binding path to AProperty.

ADO.NET objects

You can bind to ADO.NET objects, such as DataTable. The ADO.NET DataView implements the IBindingList interface, which provides change notifications that the binding engine listens for.

XML objects

You can bind to and run XPath queries on an XmlNodeXmlDocument, or XmlElement. A convenient way to access XML data that is the binding source in markup is to use an XmlDataProvider object. For more information, see How to: Bind to XML Data Using an XMLDataProvider and XPath Queries.

You can also bind to an XElement or XDocument, or bind to the results of queries run on objects of these types by using LINQ to XML. A convenient way to use LINQ to XML to access XML data that is the binding source in markup is to use an ObjectDataProvider object. For more information, see How to: Bind to XDocument, XElement, or LINQ for XML Query Results.

DependencyObject objects

You can bind to dependency properties of any DependencyObject. For an example, see How to: Bind the Properties of Two Controls.

Implementing a Class for the Binding Source

You can create your own binding sources. This section discusses the things you need to know if you are implementing a class to serve as a binding source.

Providing Change Notifications

If you are using either OneWay or TwoWay binding (because you want your UI to update when the binding source properties change dynamically), you must implement a suitable property changed notification mechanism. The recommended mechanism is for the CLR or dynamic class to implement the INotifyPropertyChanged interface. For more information, see How to: Implement Property Change Notification.

If you create a CLR object that does not implement INotifyPropertyChanged, then you must arrange for your own notification system to make sure that the data used in a binding stays current. You can provide change notifications by supporting the PropertyChanged pattern for each property that you want change notifications for. To support this pattern, you define a PropertyNameChanged event for each property, where PropertyName is the name of the property. You raise the event every time the property changes.

If your binding source implements one of these notification mechanisms, target updates happen automatically. If for any reason your binding source does not provide the proper property changed notifications, you have the option to use the UpdateTarget method to update the target property explicitly.

Other Characteristics

The following list provides other important points to note:

  • If you want to create the object in XAML, the class must have a default constructor. In some .NET languages, such as C#, the default constructor might be created for you.

  • The properties you use as binding source properties for a binding must be public properties of your class. Explicitly defined interface properties cannot be accessed for binding purposes, nor can protected, private, internal, or virtual properties that have no base implementation.

  • You cannot bind to public fields.

  • The type of the property declared in your class is the type that is passed to the binding. However, the type ultimately used by the binding depends on the type of the binding target property, not of the binding source property. If there is a difference in type, you might want to write a converter to handle how your custom property is initially passed to the binding. For more information, see IValueConverter.

Using Entire Objects as a Binding Source

You can use an entire object as a binding source. You can specify a binding source by using the Source or the DataContext property, and then provide a blank binding declaration: {Binding}. Scenarios in which this is useful include binding to objects that are of type string, binding to objects with multiple properties you are interested in, or binding to collection objects. For an example of binding to an entire collection object, see How to: Use the Master-Detail Pattern with Hierarchical Data.

Note that 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) or a DataTemplate. For more information about converters, see the Data Conversion section of Data Binding Overview. For more information about data templates, see Data Templating Overview.

Using Collection Objects as a Binding Source

Often, the object you want to use as the binding source is a collection of custom objects. Each object serves as the source for one instance of a repeated binding. For example, you might have a CustomerOrders collection that consists of CustomerOrder objects, where your application iterates over the collection to determine how many orders exist and the data contained in each.

You can enumerate over any collection that implements the IEnumerable interface. However, to set up dynamic bindings so that insertions or deletions in the collection update the UI automatically, the collection must implement the INotifyCollectionChanged interface. This interface exposes an event that must be raised whenever the underlying collection changes.

The ObservableCollection<T> class is a built-in implementation of a data collection that exposes the INotifyCollectionChanged interface. The individual data objects within the collection must satisfy the requirements described in the preceding sections. For an example, see How to: Create and Bind to an ObservableCollection. Before implementing your own collection, consider using ObservableCollection<T> or one of the existing collection classes, such as List<T>Collection<T>, and BindingList<T>, among many others.

WPF never binds directly to a collection. If you specify a collection as a binding source, WPF actually binds to the collection's default view. For information about default views, see Data Binding Overview.

If you have an advanced scenario and you want to implement your own collection, consider using the IList interface. IList provides a non-generic collection of objects that can be individually accessed by index, which can improve performance.

Permission Requirements in Data Binding

When data binding, you must consider the trust level of the application. The following table summarizes what property types can be bound to in an application that is executing in either full trust or partial trust:

Property type

(all access modifiers)

Dynamic object property

Dynamic object property

CLR property

CLR property

Dependency property

Dependency property

Trust level

Full trust

Partial trust

Full trust

Partial trust

Full trust

Partial trust

Public class

Yes

Yes

Yes

Yes

Yes

Yes

Non-public class

Yes

No

Yes

No

Yes

Yes

This table describes the following important points about permission requirements in data binding:

  • For CLR properties, data binding works as long as the binding engine is able to access the binding source property using reflection. Otherwise, the binding engine issues a warning that the property cannot be found and uses the fallback value or the default value, if it is available.

  • You can bind to properties on dynamic objects that are defined at compile time or run time.

  • You can always bind to dependency properties.

The permission requirement for XML binding is similar. In a partial-trust sandbox, XmlDataProvider fails when it does not have permissions to access the specified data.

Objects with an anonymous type are internal. You can bind to properties of anonymous types only when running in full trust. For more information about anonymous types, see Anonymous Types (C# Programming Guide) or Anonymous Types (Visual Basic) (Visual Basic).

For more information about partial-trust security, see WPF Partial Trust Security.





Data Templating Overview

The WPF data templating model provides you with great flexibility to define the presentation of your data. WPF controls have built-in functionality to support the customization of data presentation. This topic first demonstrates how to define a DataTemplate and then introduces other data templating features, such as the selection of templates based on custom logic and the support for the display of hierarchical data.

Prerequisites

This topic focuses on data templating features and is not an introduction of data binding concepts. For information about basic data binding concepts, see the Data Binding Overview.

DataTemplate is about the presentation of data and is one of the many features provided by the WPF styling and templating model. For an introduction of the WPF styling and templating model, such as how to use a Style to set properties on controls, see the Styling and Templating topic.

In addition, it is important to understand Resources, which are essentially what enable objects such as Style and DataTemplate to be reusable. For more information on resources, see XAML Resources.

Data Templating Basics

To demonstrate why DataTemplate is important, let's walk through a data binding example. In this example, we have a ListBox that is bound to a list of Task objects. Each Task object has a TaskName (string), a Description (string), a Priority (int), and a property of type TaskType, which is an Enum with values Home and Work.

<Window x:Class="SDKSample.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:SDKSample"
  Title="Introduction to Data Templating Sample">
  <Window.Resources>
    <local:Tasks x:Key="myTodoList"/>
</Window.Resources>
  <StackPanel>
    <TextBlock Name="blah" FontSize="20" Text="My Task List:"/>
    <ListBox Width="400" Margin="10"
             ItemsSource="{Binding Source={StaticResource myTodoList}}"/>
  </StackPanel>
</Window>

Without a DataTemplate

Without a DataTemplate, our ListBox currently looks like this:

Data templating sample screen shot

What's happening is that without any specific instructions, the ListBox by default calls ToString when trying to display the objects in the collection. Therefore, if the Task object overrides the ToString method, then the ListBox displays the string representation of each source object in the underlying collection.

For example, if the Task class overrides the ToString method this way, where name is the field for the TaskName property:

public override string ToString()
{
    return name.ToString();
}

Then the ListBox looks like the following:

Data templating sample screen shot

However, that is limiting and inflexible. Also, if you are binding to XML data, you wouldn't be able to override ToString.

Defining a Simple DataTemplate

The solution is to define a DataTemplate. One way to do that is to set the ItemTemplate property of the ListBox to a DataTemplate. What you specify in your DataTemplate becomes the visual structure of your data object. The following DataTemplate is fairly simple. We are giving instructions that each item appears as three TextBlock elements within a StackPanel. Each TextBlock element is bound to a property of the Taskclass.

<ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}">
   <ListBox.ItemTemplate>
     <DataTemplate>
       <StackPanel>
         <TextBlock Text="{Binding Path=TaskName}" />
         <TextBlock Text="{Binding Path=Description}"/>
         <TextBlock Text="{Binding Path=Priority}"/>
       </StackPanel>
     </DataTemplate>
   </ListBox.ItemTemplate>
 </ListBox>

The underlying data for the examples in this topic is a collection of CLR objects. If you are binding to XML data, the fundamental concepts are the same, but there is a slight syntactic difference. For example, instead of having Path=TaskName, you would set XPath to @TaskName (if TaskName is an attribute of your XML node).

Now our ListBox looks like the following:

Data templating sample screen shot

Creating the DataTemplate as a Resource

In the above example, we defined the DataTemplate inline. It is more common to define it in the resources section so it can be a reusable object, as in the following example:

<Window.Resources>
<DataTemplate x:Key="myTaskTemplate">
  <StackPanel>
    <TextBlock Text="{Binding Path=TaskName}" />
    <TextBlock Text="{Binding Path=Description}"/>
    <TextBlock Text="{Binding Path=Priority}"/>
  </StackPanel>
</DataTemplate>
</Window.Resources>

Now you can use myTaskTemplate as a resource, as in the following example:

<ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}"
         ItemTemplate="{StaticResource myTaskTemplate}"/>

Because myTaskTemplate is a resource, you can now use it on other controls that have a property that takes a DataTemplate type. As shown above, for ItemsControl objects, such as the ListBox, it is the ItemTemplate property. For ContentControl objects, it is the ContentTemplate property.

The DataType Property

The DataTemplate class has a DataType property that is very similar to the TargetType property of the Style class. Therefore, instead of specifying an x:Key for the DataTemplate in the above example, you can do the following:

<DataTemplate DataType="{x:Type local:Task}">
  <StackPanel>
    <TextBlock Text="{Binding Path=TaskName}" />
    <TextBlock Text="{Binding Path=Description}"/>
    <TextBlock Text="{Binding Path=Priority}"/>
  </StackPanel>
</DataTemplate>

This DataTemplate gets applied automatically to all Task objects. Note that in this case the x:Key is set implicitly. Therefore, if you assign this DataTemplate an x:Key value, you are overriding the implicit x:Key and the DataTemplate would not be applied automatically.

If you are binding a ContentControl to a collection of Task objects, the ContentControl does not use the above DataTemplate automatically. This is because the binding on a ContentControl needs more information to distinguish whether you want to bind to an entire collection or the individual objects. If your ContentControl is tracking the selection of an ItemsControl type, you can set the Path property of the ContentControl binding to "/" to indicate that you are interested in the current item. For an example, see How to: Bind to a Collection and Display Information Based on Selection. Otherwise, you need to specify the DataTemplate explicitly by setting the ContentTemplate property.

The DataType property is particularly useful when you have a CompositeCollection of different types of data objects. For an example, see How to: Implement a CompositeCollection.

Adding More to the DataTemplate

Currently the data appears with the necessary information, but there's definitely room for improvement. Let's improve on the presentation by adding a Border, a Grid, and some TextBlock elements that describe the data that is being displayed.

<DataTemplate x:Key="myTaskTemplate">
  <Border Name="border" BorderBrush="Aqua" BorderThickness="1"
          Padding="5" Margin="5">
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
      </Grid.ColumnDefinitions>
      <TextBlock Grid.Row="0" Grid.Column="0" Text="Task Name:"/>
      <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}" />
      <TextBlock Grid.Row="1" Grid.Column="0" Text="Description:"/>
      <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>
      <TextBlock Grid.Row="2" Grid.Column="0" Text="Priority:"/>
      <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/>
    </Grid>
  </Border>
</DataTemplate>

The following screenshot shows the ListBox with this modified DataTemplate:

Data templating sample screen shot

We can set HorizontalContentAlignment to Stretch on the ListBox to make sure the width of the items takes up the entire space:

<ListBox Width="400" Margin="10"
     ItemsSource="{Binding Source={StaticResource myTodoList}}"
     ItemTemplate="{StaticResource myTaskTemplate}" 
     HorizontalContentAlignment="Stretch"/>

With the HorizontalContentAlignment property set to Stretch, the ListBox now looks like this:

Data templating sample screen shot

Use DataTriggers to Apply Property Values

The current presentation does not tell us whether a Task is a home task or an office task. Remember that the Task object has a TaskTypeproperty of type TaskType, which is an enumeration with values Home and Work.

In the following example, the DataTrigger sets the BorderBrush of the element named border to Yellow if the TaskType property is TaskType.Home.

<DataTemplate x:Key="myTaskTemplate">
<DataTemplate.Triggers>
  <DataTrigger Binding="{Binding Path=TaskType}">
    <DataTrigger.Value>
      <local:TaskType>Home</local:TaskType>
    </DataTrigger.Value>
    <Setter TargetName="border" Property="BorderBrush" Value="Yellow"/>
  </DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>

Our application now looks like the following. Home tasks appear with a yellow border and office tasks appear with an aqua border:

Data templating sample screen shot

In this example the DataTrigger uses a Setter to set a property value. The trigger classes also have the EnterActions and ExitActions properties that allow you to start a set of actions such as animations. In addition, there is also a MultiDataTrigger class that allows you to apply changes based on multiple data-bound property values.

An alternative way to achieve the same effect is to bind the BorderBrush property to the TaskType property and use a value converter to return the color based on the TaskType value. Creating the above effect using a converter is slightly more efficient in terms of performance. Additionally, creating your own converter gives you more flexibility because you are supplying your own logic. Ultimately, which technique you choose depends on your scenario and your preference. For information about how to write a converter, see IValueConverter.

What Belongs in a DataTemplate?

In the previous example, we placed the trigger within the DataTemplate using the DataTemplate.Triggers property. The Setter of the trigger sets the value of a property of an element (the Border element) that is within the DataTemplate. However, if the properties that your Setters are concerned with are not properties of elements that are within the current DataTemplate, it may be more suitable to set the properties using a Style that is for the ListBoxItem class (if the control you are binding is a ListBox). For example, if you want your Trigger to animate the Opacity value of the item when a mouse points to an item, you define triggers within a ListBoxItem style. For an example, see the Introduction to Styling and Templating Sample.

In general, keep in mind that the DataTemplate is being applied to each of the generated ListBoxItem (for more information about how and where it is actually applied, see the ItemTemplate page.). Your DataTemplate is concerned with only the presentation and appearance of the data objects. In most cases, all other aspects of presentation, such as what an item looks like when it is selected or how the ListBox lays out the items, do not belong in the definition of a DataTemplate. For an example, see the Styling and Templating an ItemsControl section.

Choosing a DataTemplate Based on Properties of the Data Object

In The DataType Property section, we discussed that you can define different data templates for different data objects. That is especially useful when you have a CompositeCollection of different types or collections with items of different types. In the Use DataTriggers to Apply Property Values section, we have shown that if you have a collection of the same type of data objects you can create a DataTemplate and then use triggers to apply changes based on the property values of each data object. However, triggers allow you to apply property values or start animations but they don't give you the flexibility to reconstruct the structure of your data objects. Some scenarios may require you to create a different DataTemplate for data objects that are of the same type but have different properties.

For example, when a Task object has a Priority value of 1, you may want to give it a completely different look to serve as an alert for yourself. In that case, you create a DataTemplate for the display of the high-priority Task objects. Let's add the following DataTemplate to the resources section:

<DataTemplate x:Key="importantTaskTemplate">
  <DataTemplate.Resources>
    <Style TargetType="TextBlock">
      <Setter Property="FontSize" Value="20"/>
    </Style>
  </DataTemplate.Resources>
  <Border Name="border" BorderBrush="Red" BorderThickness="1"
          Padding="5" Margin="5">
    <DockPanel HorizontalAlignment="Center">
      <TextBlock Text="{Binding Path=Description}" />
      <TextBlock>!</TextBlock>
    </DockPanel>
  </Border>
</DataTemplate>

Notice this example uses the DataTemplate.Resources property. Resources defined in that section are shared by the elements within the DataTemplate.

To supply logic to choose which DataTemplate to use based on the Priority value of the data object, create a subclass of DataTemplateSelector and override the SelectTemplate method. In the following example, the SelectTemplate method provides logic to return the appropriate template based on the value of the Priority property. The template to return is found in the resources of the enveloping Window element.

using System.Windows;
using System.Windows.Controls;

namespace SDKSample
{
    public class TaskListDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate
            SelectTemplate(object item, DependencyObject container)
        {
            FrameworkElement element = container as FrameworkElement;

            if (element != null && item != null && item is Task)
            {
                Task taskitem = item as Task;

                if (taskitem.Priority == 1)
                    return
                        element.FindResource("importantTaskTemplate") as DataTemplate;
                else
                    return
                        element.FindResource("myTaskTemplate") as DataTemplate;
            }

            return null;
        }
    }
}

We can then declare the TaskListDataTemplateSelector as a resource:

<Window.Resources>
<local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>
</Window.Resources>

To use the template selector resource, assign it to the ItemTemplateSelector property of the ListBox. The ListBox calls the SelectTemplate method of the TaskListDataTemplateSelector for each of the items in the underlying collection. The call passes the data object as the item parameter. The DataTemplate that is returned by the method is then applied to that data object.

<ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}"
         ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
         HorizontalContentAlignment="Stretch"/>

With the template selector in place, the ListBox now appears as follows:

Data templating sample screen shot

This concludes our discussion of this example. For the complete sample, see Introduction to Data Templating Sample.

Styling and Templating an ItemsControl

Even though the ItemsControl is not the only control type that you can use a DataTemplate with, it is a very common scenario to bind an ItemsControl to a collection. In the What Belongs in a DataTemplate section we discussed that the definition of your DataTemplate should only be concerned with the presentation of data. In order to know when it is not suitable to use a DataTemplate it is important to understand the different style and template properties provided by the ItemsControl. The following example is designed to illustrate the function of each of these properties. The ItemsControl in this example is bound to the same Tasks collection as in the previous example. For demonstration purposes, the styles and templates in this example are all declared inline.

<ItemsControl Margin="10"
              ItemsSource="{Binding Source={StaticResource myTodoList}}">
  <!--The ItemsControl has no default visual appearance.
      Use the Template property to specify a ControlTemplate to define
      the appearance of an ItemsControl. The ItemsPresenter uses the specified
      ItemsPanelTemplate (see below) to layout the items. If an
      ItemsPanelTemplate is not specified, the default is used. (For ItemsControl,
      the default is an ItemsPanelTemplate that specifies a StackPanel.-->
  <ItemsControl.Template>
    <ControlTemplate TargetType="ItemsControl">
      <Border BorderBrush="Aqua" BorderThickness="1" CornerRadius="15">
        <ItemsPresenter/>
      </Border>
    </ControlTemplate>
  </ItemsControl.Template>
  <!--Use the ItemsPanel property to specify an ItemsPanelTemplate
      that defines the panel that is used to hold the generated items.
      In other words, use this property if you want to affect
      how the items are laid out.-->
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <WrapPanel />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  <!--Use the ItemTemplate to set a DataTemplate to define
      the visualization of the data objects. This DataTemplate
      specifies that each data object appears with the Proriity
      and TaskName on top of a silver ellipse.-->
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <DataTemplate.Resources>
        <Style TargetType="TextBlock">
          <Setter Property="FontSize" Value="18"/>
          <Setter Property="HorizontalAlignment" Value="Center"/>
        </Style>
      </DataTemplate.Resources>
      <Grid>
        <Ellipse Fill="Silver"/>
        <StackPanel>
          <TextBlock Margin="3,3,3,0"
                     Text="{Binding Path=Priority}"/>
          <TextBlock Margin="3,0,3,7"
                     Text="{Binding Path=TaskName}"/>
        </StackPanel>
      </Grid>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
  <!--Use the ItemContainerStyle property to specify the appearance
      of the element that contains the data. This ItemContainerStyle
      gives each item container a margin and a width. There is also
      a trigger that sets a tooltip that shows the description of
      the data object when the mouse hovers over the item container.-->
  <ItemsControl.ItemContainerStyle>
    <Style>
      <Setter Property="Control.Width" Value="100"/>
      <Setter Property="Control.Margin" Value="5"/>
      <Style.Triggers>
        <Trigger Property="Control.IsMouseOver" Value="True">
          <Setter Property="Control.ToolTip"
                  Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                          Path=Content.Description}"/>
        </Trigger>
      </Style.Triggers>
    </Style>
  </ItemsControl.ItemContainerStyle>
</ItemsControl>

The following is a screenshot of the example when it is rendered:

ItemsControl example screenshot

Note that instead of using the ItemTemplate, you can use the ItemTemplateSelector. Refer to the previous section for an example. Similarly, instead of using the ItemContainerStyle, you have the option to use the ItemContainerStyleSelector.

Two other style-related properties of the ItemsControl that are not shown here are GroupStyle and GroupStyleSelector.

Support for Hierarchical Data

So far we have only looked at how to bind to and display a single collection. Sometimes you have a collection that contains other collections. The HierarchicalDataTemplate class is designed to be used with HeaderedItemsControl types to display such data. In the following example, ListLeagueList is a list of League objects. Each League object has a Name and a collection of Division objects. Each Division has a Name and a collection of Team objects, and each Team object has a Name.

<Window x:Class="SDKSample.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="HierarchicalDataTemplate Sample"
  xmlns:src="clr-namespace:SDKSample">
  <DockPanel>
    <DockPanel.Resources>
      <src:ListLeagueList x:Key="MyList"/>

      <HierarchicalDataTemplate DataType    = "{x:Type src:League}"
                                ItemsSource = "{Binding Path=Divisions}">
        <TextBlock Text="{Binding Path=Name}"/>
      </HierarchicalDataTemplate>

      <HierarchicalDataTemplate DataType    = "{x:Type src:Division}"
                                ItemsSource = "{Binding Path=Teams}">
        <TextBlock Text="{Binding Path=Name}"/>
      </HierarchicalDataTemplate>

      <DataTemplate DataType="{x:Type src:Team}">
        <TextBlock Text="{Binding Path=Name}"/>
      </DataTemplate>
    </DockPanel.Resources>

    <Menu Name="menu1" DockPanel.Dock="Top" Margin="10,10,10,10">
        <MenuItem Header="My Soccer Leagues"
                  ItemsSource="{Binding Source={StaticResource MyList}}" />
    </Menu>

    <TreeView>
      <TreeViewItem ItemsSource="{Binding Source={StaticResource MyList}}" Header="My Soccer Leagues" />
    </TreeView>

  </DockPanel>
</Window>

The example shows that with the use of HierarchicalDataTemplate, you can easily display list data that contains other lists. The following is a screenshot of the example.

HierarchicalDataTemplate sample screen shot




Binding Declarations Overview

This topic discusses the different ways you can declare a binding.

Prerequisites

Before reading this topic, it is important that you are familiar with the concept and usage of markup extensions. For more information about markup extensions, see Markup Extensions and WPF XAML.

This topic does not cover data binding concepts. For a discussion of data binding concepts, see Data Binding Overview.

Declaring a Binding in XAML

This section discusses how to declare a binding in XAML.

Markup Extension Usage

Binding is a markup extension. When you use the binding extension to declare a binding, the declaration consists of a series of clauses following the Binding keyword and separated by commas (,). The clauses in the binding declaration can be in any order and there are many possible combinations. The clauses are Name=Value pairs where Name is the name of the Binding property and Value is the value you are setting for the property.

When creating binding declaration strings in markup, they must be attached to the specific dependency property of a target object. The following example shows how to bind the TextBox.Text property using the binding extension, specifying the Source and Path properties.

<TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=PersonName}"/>

You can specify most of the properties of the Binding class this way. For more information about the binding extension as well as for a list of Binding properties that cannot be set using the binding extension, see the Binding Markup Extension overview.

Object Element Syntax

Object element syntax is an alternative to creating the binding declaration. In most cases, there is no particular advantage to using either the markup extension or the object element syntax. However, in cases which the markup extension does not support your scenario, such as when your property value is of a non-string type for which no type conversion exists, you need to use the object element syntax.

The following is an example of both the object element syntax and the markup extension usage:

<TextBlock Name="myconvertedtext"
  Foreground="{Binding Path=TheDate,
                       Converter={StaticResource MyConverterReference}}">
  <TextBlock.Text>
    <Binding Path="TheDate"
             Converter="{StaticResource MyConverterReference}"/>
  </TextBlock.Text>
</TextBlock>

The example binds the Foreground property by declaring a binding using the extension syntax. The binding declaration for the Text property uses the object element syntax.

For more information about the different terms, see XAML Syntax In Detail.

MultiBinding and PriorityBinding

MultiBinding and PriorityBinding do not support the XAML extension syntax. Therefore, you must use the object element syntax if you are declaring a MultiBinding or a PriorityBinding in XAML.

Creating a Binding in Code

Another way to specify a binding is to set properties directly on a Binding object in code. The following example shows how to create a Binding object and specify the properties in code. In this example, TheConverter is an object that implements the IValueConverter interface.

   private void OnPageLoaded(object sender, EventArgs e)
   {
       // Make a new source, to grab a new timestamp
       MyData myChangedData = new MyData();

       // Create a new binding
// TheDate is a property of type DateTime on MyData class
       Binding myNewBindDef = new Binding("TheDate");

       myNewBindDef.Mode = BindingMode.OneWay;
       myNewBindDef.Source = myChangedData;
       myNewBindDef.Converter = TheConverter;
       myNewBindDef.ConverterCulture = new CultureInfo("en-US");

// myDatetext is a TextBlock object that is the binding target object
       BindingOperations.SetBinding(myDateText, TextBlock.TextProperty, myNewBindDef);
       BindingOperations.SetBinding(myDateText, TextBlock.ForegroundProperty, myNewBindDef);

If the object you are binding is a FrameworkElement or a FrameworkContentElement you can call the SetBinding method on your object directly instead of using BindingOperations.SetBinding. For an example, see How to: Create a Binding in Code.

Binding Path Syntax

Use the Path property to specify the source value you want to bind to:

  • In the simplest case, the Path property value is the name of the property of the source object to use for the binding, such as Path=PropertyName.

  • Subproperties of a property can be specified by a similar syntax as in C#. For instance, the clause Path=ShoppingCart.Order sets the binding to the subproperty Order of the object or property ShoppingCart.

  • To bind to an attached property, place parentheses around the attached property. For example, to bind to the attached property DockPanel.Dock, the syntax is Path=(DockPanel.Dock).

  • Indexers of a property can be specified within square brackets following the property name where the indexer is applied. For instance, the clause Path=ShoppingCart[0] sets the binding to the index that corresponds to how your property's internal indexing handles the literal string "0". Nested indexers are also supported.

  • Indexers and subproperties can be mixed in a Path clause; for example, Path=ShoppingCart.ShippingInfo[MailingAddress,Street].

  • Inside indexers you can have multiple indexer parameters separated by commas (,). The type of each parameter can be specified with parentheses. For example, you can have Path="[(sys:Int32)42,(sys:Int32)24]", where sys is mapped to the System namespace.

  • When the source is a collection view, the current item can be specified with a slash (/). For example, the clause Path=/ sets the binding to the current item in the view. When the source is a collection, this syntax specifies the current item of the default collection view.

  • Property names and slashes can be combined to traverse properties that are collections. For example, Path=/Offices/ManagerName specifies the current item of the source collection, which contains an Offices property that is also a collection. Its current item is an object that contains a ManagerName property.

  • Optionally, a period (.) path can be used to bind to the current source. For example, Text="{Binding}" is equivalent to Text="{Binding Path=.}".

Escaping Mechanism

  • Inside indexers ([ ]), the caret character (^) escapes the next character.

  • If you set Path in XAML, you also need to escape (using XML entities) certain characters that are special to the XML language definition:

    • Use &amp; to escape the character "&".

    • Use &gt; to escape the end tag ">".

  • Additionally, if you describe the entire binding in an attribute using the markup extension syntax, you need to escape (using backslash \) characters that are special to the WPF markup extension parser:

    • Backslash (\) is the escape character itself.

    • The equal sign (=) separates property name from property value.

    • Comma (,) separates properties.

    • The right curly brace (}) is the end of a markup extension.

Default Behaviors

The default behavior is as follows if not specified in the declaration.

  • A default converter is created that tries to do a type conversion between the binding source value and the binding target value. If a conversion cannot be made, the default converter returns null.

  • If you do not set ConverterCulture, the binding engine uses the Language property of the binding target object. In XAML, this defaults to "en-US" or inherits the value from the root element (or any element) of the page, if one has been explicitly set.

  • As long as the binding already has a data context (for instance, the inherited data context coming from a parent element), and whatever item or collection being returned by that context is appropriate for binding without requiring further path modification, a binding declaration can have no clauses at all: {Binding} This is often the way a binding is specified for data styling, where the binding acts upon a collection. For more information, see the "Entire Objects Used as a Binding Source" section in the Binding Sources Overview.

  • The default Mode varies between one-way and two-way depending on the dependency property that is being bound. You can always declare the binding mode explicitly to ensure that your binding has the desired behavior. In general, user-editable control properties, such as TextBox.Text and RangeBase.Value, default to two-way bindings, whereas most other properties default to one-way bindings.

  • The default UpdateSourceTrigger value varies between PropertyChanged and LostFocus depending on the bound dependency property as well. The default value for most dependency properties is PropertyChanged, while the TextBox.Text property has a default value of LostFocus.





How-to Topics




How to: Create a Simple Binding

This example shows you how to create a simple Binding.

Example

In this example, you have a Person object with a string property named PersonName. The Person object is defined in the namespace called SDKSample.

The following example instantiates the Person object with a PersonName property value of Joe. This is done in the Resources section and assigned an x:Key.

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:src="clr-namespace:SDKSample"
  SizeToContent="WidthAndHeight"
  Title="Simple Data Binding Sample">

  <Window.Resources>
    <src:Person x:Key="myDataSource" PersonName="Joe"/>
</Window.Resources>
</Window>

To bind to the PersonName property you would do the following:

<TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=PersonName}"/>

As a result, the TextBlock appears with the value "Joe".





How to: Specify the Binding Source

In data binding, the binding source object refers to the object you obtain your data from. This topic describes the different ways of specifying the binding source.

Example

If you are binding several properties to a common source, you want to use the DataContext property, which provides a convenient way to establish a scope within which all data-bound properties inherit a common source.

In the following example, the data context is established on the root element of the application. This allows all child elements to inherit that data context. Data for the binding comes from a custom data class, NetIncome, referenced directly through a mapping and given the resource key of incomeDataSource.

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.DirectionalBinding"
  xmlns:c="clr-namespace:SDKSample"
  Name="Page1"
>
  <Grid.Resources>
    <c:NetIncome x:Key="incomeDataSource"/>
    <Style TargetType="{x:Type TextBlock}">
      <Setter Property="Padding" Value="8"/>
    </Style>
    <Style TargetType="{x:Type TextBox}">
      <Setter Property="Margin" Value="0,6,0,0"/>
    </Style>
  </Grid.Resources>
  <Grid.DataContext>
    <Binding Source="{StaticResource incomeDataSource}"/>
  </Grid.DataContext>
</Grid>

The following example shows the definition of the NetIncome class.

public class NetIncome : INotifyPropertyChanged
{
    private int totalIncome = 5000;
    private int rent = 2000;
    private int food = 0;
    private int misc = 0;
    private int savings = 0;
    public NetIncome()
    {
        savings = totalIncome - (rent+food+misc);
    }

    public int TotalIncome
    {
        get
        {
            return totalIncome;
        }
        set
        {
            if( TotalIncome != value)
            {
                totalIncome = value;
                OnPropertyChanged("TotalIncome");
            }
        }
    }
    public int Rent
    {
        get
        {
            return rent;
        }
        set
        {
            if( Rent != value)
            {
                rent = value;
                OnPropertyChanged("Rent");
                UpdateSavings();
            }
        }
    }
    public int Food
    {
        get
        {
            return food;
        }
        set
        {
            if( Food != value)
            {
                food = value;
                OnPropertyChanged("Food");
                UpdateSavings();
            }
        }
    }
    public int Misc
    {
        get
        {
            return misc;
        }
        set
        {
            if( Misc != value)
            {
                misc = value;
                OnPropertyChanged("Misc");
                UpdateSavings();
            }
        }
    }
    public int Savings
    {
        get
        {
            return savings;
        }
        set
        {
            if( Savings != value)
            {
                savings = value;
                OnPropertyChanged("Savings");
                UpdateSavings();
            }
        }
    }

    private void UpdateSavings()
    {
        Savings = TotalIncome - (Rent+Misc+Food);
        if(Savings < 0)
        {}
        else if(Savings >= 0)
        {}
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(String info)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler !=null)
        {
            handler(this, new PropertyChangedEventArgs(info));
        }
    }
}
System_CAPS_noteNote

The above example instantiates the object in markup and uses it as a resource. If you want to bind to an object that has already been instantiated in code, you need to set the DataContext property programmatically. For an example, see How to: Make Data Available for Binding in XAML.

Alternatively, if you want to specify the source on your individual bindings explicitly, you have the following options. These take precedence over the inherited data context.

Property

Description

Source

You use this property to set the source to an instance of an object. If you do not need the functionality of establishing a scope in which several properties inherit the same data context, you can use the Source property instead of the DataContext property. For more information, see Source.

RelativeSource

This is useful when you want to specify the source relative to where your binding target is. Some common scenarios where you may use this property is when you want to bind one property of your element to another property of the same element or if you are defining a binding in a style or a template. For more information, see RelativeSource.

ElementName

You specify a string that represents the element you want to bind to. This is useful when you want to bind to the property of another element on your application. For example, if you want to use a Slider to control the height of another control in your application, or if you want to bind the Content of your control to the SelectedValue property of your ListBox control. For more information, see ElementName.





How to: Make Data Available for Binding in XAML

This topic discusses the different ways you can make data available for binding in Extensible Application Markup Language (XAML), depending on the needs of your application.

Example

If you have a common language runtime (CLR) object you would like to bind to from XAML, one way you can make the object available for binding is to define it as a resource and give it an x:Key. In the following example, you have a Person object with a string property named PersonName. The Person object is defined in the namespace called SDKSample.

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:src="clr-namespace:SDKSample"
  SizeToContent="WidthAndHeight"
  Title="Simple Data Binding Sample">

  <Window.Resources>
    <src:Person x:Key="myDataSource" PersonName="Joe"/>
</Window.Resources>

You can then bind to the object in XAML, as shown in the following example.

<TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=PersonName}"/>

Alternatively, you can use the ObjectDataProvider class, as in the following example.

<ObjectDataProvider x:Key="myDataSource" ObjectType="{x:Type src:Person}">
  <ObjectDataProvider.ConstructorParameters>
    <system:String>Joe</system:String>
  </ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>

You define the binding the same way:

<TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=PersonName}"/>

In this particular example, the result is the same: you have a TextBlock with the text content Joe. However, the ObjectDataProvider class provides functionality such as the ability to bind to the result of a method. You can choose to use the ObjectDataProvider class if you need the functionality it provides.

However, if you are binding to an object that has already been created, you need to set the DataContext in code, as in the following example.

DataSet myDataSet;

private void OnInit(object sender, EventArgs e)
{
  string mdbFile = Path.Combine(AppDataPath, "BookData.mdb");
  string connString = string.Format(
      "Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0}", mdbFile);
  OleDbConnection conn = new OleDbConnection(connString);
  OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM BookTable;", conn);

  myDataSet = new DataSet();
  adapter.Fill(myDataSet, "BookTable");

  // myListBox is a ListBox control.
  // Set the DataContext of the ListBox to myDataSet
  myListBox.DataContext = myDataSet;
}

To access XML data for binding using the XmlDataProvider class, see How to: Bind to XML Data Using an XMLDataProvider and XPath Queries. To access XML data for binding using the ObjectDataProvider class, see How to: Bind to XDocument, XElement, or LINQ for XML Query Results.

For information about the different ways you can specify the data you are binding to, see How to: Specify the Binding Source. For information about what types of data you can bind to or how to implement your own common language runtime (CLR) objects for binding, see Binding Sources Overview.





How to: Control When the TextBox Text Updates the Source

This topic describes how to use the UpdateSourceTrigger property to control the timing of binding source updates. The topic uses the TextBox control as an example.

Example

The TextBox.Text property has a default UpdateSourceTrigger value of LostFocus. This means if an application has a TextBox with a data-bound TextBox.Text property, the text you type into the TextBox does not update the source until the TextBox loses focus (for instance, when you click away from the TextBox).

If you want the source to get updated as you are typing, set the UpdateSourceTrigger of the binding to PropertyChanged. In the following example, the Text properties of both the TextBox and the TextBlock are bound to the same source property. The UpdateSourceTrigger property of the TextBox binding is set to PropertyChanged.

<Label>Enter a Name:</Label>
<TextBox>
  <TextBox.Text>
    <Binding Source="{StaticResource myDataSource}" Path="Name"
             UpdateSourceTrigger="PropertyChanged"/>
  </TextBox.Text>
</TextBox>

<Label>The name you entered:</Label>
<TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=Name}"/>

As a result, the TextBlock shows the same text (because the source changes) as the user enters text into the TextBox, as illustrated by the following screenshot of the sample:

Simple data binding sample screen shot

If you have a dialog or a user-editable form and you want to defer source updates until the user is finished editing the fields and clicks "OK", you can set the UpdateSourceTrigger value of your bindings to Explicit, as in the following example:

<TextBox Name="itemNameTextBox"
         Text="{Binding Path=ItemName, UpdateSourceTrigger=Explicit}" />

When you set the UpdateSourceTrigger value to Explicit, the source value only changes when the application calls the UpdateSource method. The following example shows how to call UpdateSource for itemNameTextBox:

// itemNameTextBox is an instance of a TextBox
BindingExpression be = itemNameTextBox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
System_CAPS_noteNote

You can use the same technique for properties of other controls, but keep in mind that most other properties have a default UpdateSourceTrigger value of PropertyChanged. For more information, see the UpdateSourceTrigger property page.

System_CAPS_noteNote

The UpdateSourceTrigger property deals with source updates and therefore is only relevant for TwoWay or OneWayToSource bindings. For TwoWay and OneWayToSource bindings to work, the source object needs to provide property change notifications. You can refer to the samples cited in this topic for more information. In addition, you can look at How to: Implement Property Change Notification.





How to: Specify the Direction of the Binding

This example shows how to specify whether the binding updates only the binding target (target) property, the binding source (source) property, or both the target property and the source property.

Example

You use the Mode property to specify the direction of the binding. The following enumeration list shows the available options for binding updates:

  • TwoWay updates the target property or the property whenever either the target property or the source property changes.

  • OneWay updates the target property only when the source property changes.

  • OneTime updates the target property only when the application starts or when the DataContext undergoes a change.

  • OneWayToSource updates the source property when the target property changes.

  • Default causes the default Mode value of target property to be used.

For more information, see the BindingMode enumeration.

The following example shows how to set the Mode property.

<TextBlock Name="IncomeText" Grid.Row="0" Grid.Column="1"
  Text="{Binding Path=TotalIncome, Mode=OneTime}"/>

To detect source changes (applicable to OneWay and TwoWay bindings), the source must implement a suitable property change notification mechanism such as INotifyPropertyChanged. See How to: Implement Property Change Notification for an example of an INotifyPropertyChanged implementation.

For TwoWay or OneWayToSource bindings, you can control the timing of the source updates by setting the UpdateSourceTrigger property. See UpdateSourceTrigger for more information.






How to: Bind to a Collection and Display Information Based on Selection

In a simple master-detail scenario, you have a data-bound ItemsControl such as a ListBox. Based on user selection, you display more information about the selected item. This example shows how to implement this scenario.

Example

In this example, People is an ObservableCollection<T> of Person classes. This Person class contains three properties: FirstNameLastName, and HomeTown, all of type string.

<Window x:Class="SDKSample.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:SDKSample"
  Title="Binding to a Collection"
  SizeToContent="WidthAndHeight">
  <Window.Resources>
    <local:People x:Key="MyFriends"/>
  </Window.Resources>

  <StackPanel>
    <TextBlock FontFamily="Verdana" FontSize="11"
               Margin="5,15,0,10" FontWeight="Bold">My Friends:</TextBlock>
    <ListBox Width="200" IsSynchronizedWithCurrentItem="True"
             ItemsSource="{Binding Source={StaticResource MyFriends}}"/>
    <TextBlock FontFamily="Verdana" FontSize="11"
               Margin="5,15,0,5" FontWeight="Bold">Information:</TextBlock>
    <ContentControl Content="{Binding Source={StaticResource MyFriends}}"
                    ContentTemplate="{StaticResource DetailTemplate}"/>
  </StackPanel>
</Window>

The ContentControl uses the following DataTemplate that defines how the information of a Person is presented:

<DataTemplate x:Key="DetailTemplate">
  <Border Width="300" Height="100" Margin="20"
          BorderBrush="Aqua" BorderThickness="1" Padding="8">
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
      </Grid.ColumnDefinitions>
      <TextBlock Grid.Row="0" Grid.Column="0" Text="First Name:"/>
      <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=FirstName}"/>
      <TextBlock Grid.Row="1" Grid.Column="0" Text="Last Name:"/>
      <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=LastName}"/>
      <TextBlock Grid.Row="2" Grid.Column="0" Text="Home Town:"/>
      <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=HomeTown}"/>
    </Grid>
  </Border>
</DataTemplate>

The following is a screenshot of what the example produces. The ContentControl shows the other properties of the person selected.

Binding to a collection

The two things to notice in this example are:

  1. The ListBox and the ContentControl bind to the same source. The Path properties of both bindings are not specified because both controls are binding to the entire collection object.

  2. You must set the IsSynchronizedWithCurrentItem property to true for this to work. Setting this property ensures that the selected item is always set as the CurrentItem. Alternatively, if the ListBox gets it data from a CollectionViewSource, it synchronizes selection and currency automatically.

Note that the Person class overrides the ToString method the following way. By default, the ListBox calls ToString and displays a string representation of each object in the bound collection. That is why each Person appears as a first name in the ListBox.

public override string ToString()
{
    return firstname.ToString();
}





How to: Bind to an Enumeration

This example shows how to bind to an enumeration by binding to the enumeration's GetValues method.

Example

In the following example, the ListBox displays the list of HorizontalAlignment enumeration values through data binding. The ListBox and the Button are bound such that you can change the HorizontalAlignment property value of the Button by selecting a value in the ListBox.

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:sys="clr-namespace:System;assembly=mscorlib" 
  SizeToContent="WidthAndHeight" 
  Title="Show Enums in a ListBox using Binding">

  <Window.Resources>
    <ObjectDataProvider MethodName="GetValues"
                        ObjectType="{x:Type sys:Enum}"
                        x:Key="AlignmentValues">
      <ObjectDataProvider.MethodParameters>
        <x:Type TypeName="HorizontalAlignment" />
      </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
  </Window.Resources>

  <Border Margin="10" BorderBrush="Aqua"
          BorderThickness="3" Padding="8">
    <StackPanel Width="300">
      <TextBlock>Choose the HorizontalAlignment value of the Button:</TextBlock>
      <ListBox Name="myComboBox" SelectedIndex="0" Margin="8"
               ItemsSource="{Binding Source={StaticResource AlignmentValues}}"/>
      <Button Content="Click Me!"
              HorizontalAlignment="{Binding ElementName=myComboBox,
                                            Path=SelectedItem}"/>
    </StackPanel>
  </Border>
</Window>





How to: Bind the Properties of Two Controls

This example shows how to bind the property of one instantiated control to that of another using the ElementName property.

Example

The following example shows how to bind the Background property of a Canvas to the SelectedItem.Content property of a ComboBox:

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Width="460" Height="200"
  Title="Binding the Properties of Two Controls">

  <Window.Resources>
    <Style TargetType="TextBlock">
      <Setter Property="FontSize" Value="16"/>
      <Setter Property="FontWeight" Value="Bold"/>
      <Setter Property="DockPanel.Dock" Value="Top"/>
      <Setter Property="HorizontalAlignment" Value="Center"/>
    </Style>
    <Style TargetType="Canvas">
      <Setter Property="Height" Value="50"/>
      <Setter Property="Width" Value="50"/>
      <Setter Property="Margin" Value="8"/>
      <Setter Property="DockPanel.Dock" Value="Top"/>
    </Style>
    <Style TargetType="ComboBox">
      <Setter Property="Width" Value="150"/>
      <Setter Property="Margin" Value="8"/>
      <Setter Property="DockPanel.Dock" Value="Top"/>
    </Style>
  </Window.Resources>

  <Border Margin="10" BorderBrush="Silver" BorderThickness="3" Padding="8">
    <DockPanel>
      <TextBlock>Choose a Color:</TextBlock>
      <ComboBox Name="myComboBox" SelectedIndex="0">
        <ComboBoxItem>Green</ComboBoxItem>
        <ComboBoxItem>Blue</ComboBoxItem>
        <ComboBoxItem>Red</ComboBoxItem>
      </ComboBox>
      <Canvas>
        <Canvas.Background>
          <Binding ElementName="myComboBox" Path="SelectedItem.Content"/>
        </Canvas.Background>
      </Canvas>
    </DockPanel>
  </Border>
</Window>

When this example is rendered it looks like the following:

A canvas with a green background

Note   The binding target property (in this example, the Background property) must be a dependency property. For more information, see Data Binding Overview.






How to: Implement Binding Validation

This example shows how to use an ErrorTemplate and a style trigger to provide visual feedback to inform the user when an invalid value is entered, based on a custom validation rule.

Example

The text content of the TextBox in the following example is bound to the Age property (of type int) of a binding source object named ods. The binding is set up to use a validation rule named AgeRangeRule so that if the user enters non-numeric characters or a value that is smaller than 21 or greater than 130, a red exclamation mark appears next to the text box and a tool tip with the error message appears when the user moves the mouse over the text box.

<TextBox Name="textBox1" Width="50" FontSize="15"
         Validation.ErrorTemplate="{StaticResource validationTemplate}"
         Style="{StaticResource textBoxInError}"
         Grid.Row="1" Grid.Column="1" Margin="2">
  <TextBox.Text>
    <Binding Path="Age" Source="{StaticResource ods}"
             UpdateSourceTrigger="PropertyChanged" >
      <Binding.ValidationRules>
        <c:AgeRangeRule Min="21" Max="130"/>
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

The following example shows the implementation of AgeRangeRule, which inherits from ValidationRule and overrides the Validate method. The Int32.Parse() method is called on the value to make sure that it does not contain any invalid characters. The Validate method returns a ValidationResult that indicates if the value is valid based on whether an exception is caught during the parsing and whether the age value is outside of the lower and upper bounds.

public class AgeRangeRule : ValidationRule
{
    private int _min;
    private int _max;

    public AgeRangeRule()
    {
    }

    public int Min
    {
        get { return _min; }
        set { _min = value; }
    }

    public int Max
    {
        get { return _max; }
        set { _max = value; }
    }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        int age = 0;

        try
        {
            if (((string)value).Length > 0)
                age = Int32.Parse((String)value);
        }
        catch (Exception e)
        {
            return new ValidationResult(false, "Illegal characters or " + e.Message);
        }

        if ((age < Min) || (age > Max))
        {
            return new ValidationResult(false,
              "Please enter an age in the range: " + Min + " - " + Max + ".");
        }
        else
        {
            return new ValidationResult(true, null);
        }
    }
}

The following example shows the custom ControlTemplate validationTemplate that creates a red exclamation mark to notify the user of a validation error. Control templates are used to redefine the appearance of a control.

<ControlTemplate x:Key="validationTemplate">
  <DockPanel>
    <TextBlock Foreground="Red" FontSize="20">!</TextBlock>
    <AdornedElementPlaceholder/>
  </DockPanel>
</ControlTemplate>

As shown in the following example, the ToolTip that shows the error message is created using the style named textBoxInError. If the value of HasError is true, the trigger sets the tool tip of the current TextBox to its first validation error. The RelativeSource is set to Self, referring to the current element.

<Style x:Key="textBoxInError" TargetType="{x:Type TextBox}">
  <Style.Triggers>
    <Trigger Property="Validation.HasError" Value="true">
      <Setter Property="ToolTip"
        Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                        Path=(Validation.Errors)[0].ErrorContent}"/>
    </Trigger>
  </Style.Triggers>
</Style>

For the complete example, see Binding Validation Sample.

Note that if you do not provide a custom ErrorTemplate the default error template appears to provide visual feedback to the user when there is a validation error. See "Data Validation" in Data Binding Overview for more information. Also, WPF provides a built-in validation rule that catches exceptions that are thrown during the update of the binding source property. For more information, see ExceptionValidationRule.






How to: Implement Validation Logic on Custom Objects

This example shows how to implement validation logic on a custom object and then bind to it.

Example

You can provide validation logic on the business layer if your source object implements IDataErrorInfo, as in the following example:

public class Person : IDataErrorInfo
{
    private int age;

    public int Age
    {
        get { return age; }
        set { age = value; }
    }

    public string Error
    {
        get
        {
            return null;
        }
    }

    public string this[string name]
    {
        get
        {
            string result = null;

            if (name == "Age")
            {
                if (this.age < 0 || this.age > 150)
                {
                    result = "Age must not be less than 0 or greater than 150.";
                }
            }
            return result;
        }
    }
}

In the following example, the text property of the text box binds to the Age property of the Person object, which has been made available for binding through a resource declaration that is given the x:Key data. The DataErrorValidationRule checks for the validation errors raised by the IDataErrorInfo implementation.

<TextBox Style="{StaticResource textBoxInError}">
    <TextBox.Text>
        <!--By setting ValidatesOnExceptions to True, it checks for exceptions
        that are thrown during the update of the source property.
        An alternative syntax is to add <ExceptionValidationRule/> within
        the <Binding.ValidationRules> section.-->
        <Binding Path="Age" Source="{StaticResource data}"
                 ValidatesOnExceptions="True"
                 UpdateSourceTrigger="PropertyChanged">
            <Binding.ValidationRules>
                <!--DataErrorValidationRule checks for validation 
                    errors raised by the IDataErrorInfo object.-->
                <!--Alternatively, you can set ValidationOnDataErrors="True" on the Binding.-->
                <DataErrorValidationRule/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

Alternatively, instead of using the DataErrorValidationRule, you can set the ValidatesOnDataErrors property to true.






How to: Get the Binding Object from a Bound Target Property

This example shows how to obtain the binding object from a data-bound target property.

Example

You can do the following to get the Binding object:

// textBox3 is an instance of a TextBox
// the TextProperty is the data-bound dependency property
Binding myBinding = BindingOperations.GetBinding(textBox3, TextBox.TextProperty);
System_CAPS_noteNote

You must specify the dependency property for the binding you want because it is possible that more than one property of the target object is using data binding.

Alternatively, you can get the BindingExpression and then get the value of the ParentBinding property.

For the complete example see Binding Validation Sample.

System_CAPS_noteNote

If your binding is a MultiBinding, use BindingOperations.GetMultiBinding. If it is a PriorityBinding, use BindingOperations.GetPriorityBinding. If you are uncertain whether the target property is bound using a Binding, a MultiBinding, or a PriorityBinding, you can use BindingOperations.GetBindingBase.






How to: Implement a CompositeCollection

Example

The following example shows how to display multiple collections and items as one list using the CompositeCollection class. In this example, GreekGodsis an ObservableCollection<T> of GreekGod custom objects. Data templates are defined so that GreekGod objects and GreekHero objects appear with a gold and a cyan foreground color respectively.

<Window Background="Cornsilk"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:c="clr-namespace:SDKSample"
  x:Class="SDKSample.Window1"
  Title="CompositeCollections"
  SizeToContent="WidthAndHeight"
  >
  <Window.Resources>
    <c:GreekGods x:Key="GreekGodsData"/>

    <XmlDataProvider x:Key="GreekHeroesData" XPath="GreekHeroes/Hero">
      <x:XData>
      <GreekHeroes xmlns="">
        <Hero Name="Jason" />
        <Hero Name="Hercules" />
        <Hero Name="Bellerophon" />
        <Hero Name="Theseus" />
        <Hero Name="Odysseus" />
        <Hero Name="Perseus" />
      </GreekHeroes>
      </x:XData>
    </XmlDataProvider>

    <DataTemplate DataType="{x:Type c:GreekGod}">
      <TextBlock Text="{Binding Path=Name}" Foreground="Gold"/>
    </DataTemplate>
    <DataTemplate DataType="Hero">
      <TextBlock Text="{Binding XPath=@Name}" Foreground="Cyan"/>
    </DataTemplate>
	</Window.Resources>

  <StackPanel>
    <TextBlock FontSize="18" FontWeight="Bold" Margin="10"
      HorizontalAlignment="Center">Composite Collections Sample</TextBlock>
    <ListBox Name="myListBox" Height="300" Width="200" Background="White">
      <ListBox.ItemsSource>
        <CompositeCollection>
          <CollectionContainer
            Collection="{Binding Source={StaticResource GreekGodsData}}" />
          <CollectionContainer
            Collection="{Binding Source={StaticResource GreekHeroesData}}" />
          <ListBoxItem Foreground="Red">Other Listbox Item 1</ListBoxItem>
          <ListBoxItem Foreground="Red">Other Listbox Item 2</ListBoxItem>
        </CompositeCollection>
      </ListBox.ItemsSource>
    </ListBox>
  </StackPanel>

</Window>





How to: Convert Bound Data

This example shows how to apply conversion to data that is used in bindings.

To convert data during binding, you must create a class that implements the IValueConverter interface, which includes the Convert and ConvertBack methods.

Example

The following example shows the implementation of a date converter that converts the date value passed in so that it only shows the year, the month, and the day. When implementing the IValueConverter interface, it is a good practice to decorate the implementation with a ValueConversionAttribute attribute to indicate to development tools the data types involved in the conversion, as in the following example:

[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 as string;
        DateTime resultDateTime;
        if (DateTime.TryParse(strValue, out resultDateTime))
        {
            return resultDateTime;
        }
        return DependencyProperty.UnsetValue;
    }
}

Once you have created a converter, you can add it as a resource in your Extensible Application Markup Language (XAML) file. In the following example, src maps to the namespace in which DateConverter is defined.

<src:DateConverter x:Key="dateConverter"/>

Finally, you can use the converter in your binding using the following syntax. In the following example, the text content of the TextBlock is bound to StartDate, which is a property of an external data source.

<TextBlock Grid.Row="2" Grid.Column="0" Margin="0,0,8,0"
           Name="startDateTitle"
           Style="{StaticResource smallTitleStyle}">Start Date:</TextBlock>
<TextBlock Name="StartDateDTKey" Grid.Row="2" Grid.Column="1" 
    Text="{Binding Path=StartDate, Converter={StaticResource dateConverter}}" 
    Style="{StaticResource textStyleTextBlock}"/>

The style resources referenced in the above example are defined in a resource section not shown in this topic.





How to: Convert Bound Data

This example shows how to apply conversion to data that is used in bindings.

To convert data during binding, you must create a class that implements the IValueConverter interface, which includes the Convert and ConvertBack methods.

Example

The following example shows the implementation of a date converter that converts the date value passed in so that it only shows the year, the month, and the day. When implementing the IValueConverter interface, it is a good practice to decorate the implementation with a ValueConversionAttribute attribute to indicate to development tools the data types involved in the conversion, as in the following example:

[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 as string;
        DateTime resultDateTime;
        if (DateTime.TryParse(strValue, out resultDateTime))
        {
            return resultDateTime;
        }
        return DependencyProperty.UnsetValue;
    }
}

Once you have created a converter, you can add it as a resource in your Extensible Application Markup Language (XAML) file. In the following example, src maps to the namespace in which DateConverter is defined.

<src:DateConverter x:Key="dateConverter"/>

Finally, you can use the converter in your binding using the following syntax. In the following example, the text content of the TextBlock is bound to StartDate, which is a property of an external data source.

<TextBlock Grid.Row="2" Grid.Column="0" Margin="0,0,8,0"
           Name="startDateTitle"
           Style="{StaticResource smallTitleStyle}">Start Date:</TextBlock>
<TextBlock Name="StartDateDTKey" Grid.Row="2" Grid.Column="1" 
    Text="{Binding Path=StartDate, Converter={StaticResource dateConverter}}" 
    Style="{StaticResource textStyleTextBlock}"/>

The style resources referenced in the above example are defined in a resource section not shown in this topic.





How to: Create a Binding in Code

This example shows how to create and set a Binding in code.

Example

The FrameworkElement class and the FrameworkContentElement class both expose a SetBinding method. If you are binding an element that inherits either of these classes, you can call the SetBinding method directly.

The following example creates a class named, MyData, which contains a property named MyDataProperty.

public class MyData : INotifyPropertyChanged
{
    private string myDataProperty;

    public MyData() { }

    public MyData(DateTime dateTime)
    {
        myDataProperty = "Last bound time was " + dateTime.ToLongTimeString();
    }

    public String MyDataProperty
    {
        get { return myDataProperty; }
        set
        {
            myDataProperty = value;
            OnPropertyChanged("MyDataProperty");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string info)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(info));
        }
    }
}

The following example shows how to create a binding object to set the source of the binding. The example uses SetBinding to bind the Text property of myText, which is a TextBlock control, to MyDataProperty.

//make a new source
  MyData myDataObject = new MyData(DateTime.Now);      
  Binding myBinding = new Binding("MyDataProperty");
  myBinding.Source = myDataObject;
  myText.SetBinding(TextBlock.TextProperty, myBinding);

For the complete code sample, see Code-only Binding Sample.

Instead of calling SetBinding, you can use the SetBinding static method of the BindingOperations class. The following example, calls BindingOperations.SetBinding instead of FrameworkElement.SetBinding to bind myText to myDataProperty.

//make a new source
MyData myDataObject = new MyData(DateTime.Now);
Binding myBinding = new Binding("MyDataProperty");
myBinding.Source = myDataObject;
BindingOperations.SetBinding(myText, TextBlock.TextProperty, myBinding);




How to: Get the Default View of a Data Collection

Views allow the same data collection to be viewed in different ways, depending on sorting, filtering, or grouping criteria. Every collection has one shared default view, which is used as the actual binding source when a binding specifies a collection as its source. This example shows how to get the default view of a collection.

Example

To create the view, you need an object reference to the collection. This data object can be obtained by referencing your own code-behind object, by getting the data context, by getting a property of the data source, or by getting a property of the binding. This example shows how to get the DataContext of a data object and use it to directly obtain the default collection view for this collection.

myCollectionView = (CollectionView)
    CollectionViewSource.GetDefaultView(rootElem.DataContext);

In this example, the root element is a StackPanel. The DataContext is set to myDataSource, which refers to a data provider that is an ObservableCollection<T> of Order objects.

<StackPanel.DataContext>
  <Binding Source="{StaticResource myDataSource}"/>
</StackPanel.DataContext>

Alternatively, you can instantiate and bind to your own collection view using the CollectionViewSource class. This collection view is only shared by controls that bind to it directly. For an example, see the How to Create a View section in the Data Binding Overview.

For examples of the functionality provided by a collection view, see How to: Sort Data in a ViewHow to: Filter Data in a View, and How to: Navigate Through the Objects in a Data CollectionView.





How to: Navigate Through the Objects in a Data CollectionView

Views allow the same data collection to be viewed in different ways, depending on sorting, filtering, or grouping. Views also provide a current record pointer concept and enable moving the pointer. This example shows how to get the current object as well as navigate through the objects in a data collection using the functionality provided in the CollectionView class.

Example

In this example, myCollectionView is a CollectionView object that is a view over a bound collection.

In the following example, OnButton is an event handler for the Previous and Next buttons in an application, which are buttons that allow the user to navigate the data collection. Note that the IsCurrentBeforeFirst and IsCurrentAfterLast properties report whether the current record pointer has come to the beginning and the end of the list respectively so that MoveCurrentToFirst and MoveCurrentToLast can be called as appropriately.

The CurrentItem property of the view is cast as an Order to return the current order item in the collection.

//OnButton is called whenever the Next or Previous buttons
//are clicked to change the currency
  private void OnButton(Object sender, RoutedEventArgs args)
  {
      Button b = sender as Button;

      switch (b.Name)
      {
          case "Previous":
              myCollectionView.MoveCurrentToPrevious();

              if (myCollectionView.IsCurrentBeforeFirst)
              {
                  myCollectionView.MoveCurrentToLast();
              }
              break;

          case "Next":
              myCollectionView.MoveCurrentToNext();
              if (myCollectionView.IsCurrentAfterLast)
              {
                  myCollectionView.MoveCurrentToFirst();
              }
              break;

          o = myCollectionView.CurrentItem as Order;
          // TODO: do something with the current Order o 
      }
  }





How to: Filter Data in a View

This example shows how to filter data in a view.

Example

To create a filter, define a method that provides the filtering logic. The method is used as a callback and accepts a parameter of type object. The following method returns all the Order objects with the filled property set to "No", filtering out the rest of the objects.

public bool Contains(object de)
{
    Order order = de as Order;
    //Return members whose Orders have not been filled
    return(order.Filled== "No");
}

You can then apply the filter, as shown in the following example. In this example, myCollectionView is a ListCollectionView object.

myCollectionView.Filter = new Predicate<object>(Contains);

To undo filtering, you can set the Filter property to null:

myCollectionView.Filter = null;

For information about how to create or obtain a view, see How to: Get the Default View of a Data Collection. For the complete example, see Sorting and Filtering Items in a View Sample.

If your view object comes from a CollectionViewSource object, you apply filtering logic by setting an event handler for the Filter event. In the following example, listingDataView is an instance of CollectionViewSource.

listingDataView.Filter += new FilterEventHandler(ShowOnlyBargainsFilter);

The following shows the implementation of the example ShowOnlyBargainsFilter filter event handler. This event handler uses the Accepted property to filter out AuctionItem objects that have a CurrentPrice of $25 or greater.

private void ShowOnlyBargainsFilter(object sender, FilterEventArgs e)
{
    AuctionItem product = e.Item as AuctionItem;
    if (product != null)
    {
        // Filter out products with price 25 or above
        if (product.CurrentPrice < 25)
        {
            e.Accepted = true;
        }
        else
        {
            e.Accepted = false;
        }
    }
}





How to: Sort Data in a View

This example describes how to sort data in a view.

Example

The following example creates a simple ListBox and a Button:

<Window x:Class="ListBoxSort_snip.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ListBoxSort_snip" Height="300" Width="300">
    <DockPanel>
      <ListBox Name="myListBox" DockPanel.Dock="Top">
        <ListBoxItem>my</ListBoxItem>
        <!--Or you can set the content this way:-->
        <!--<ListBoxItem Content="my"/>-->
        <ListBoxItem>1</ListBoxItem>
        <ListBoxItem>Sort</ListBoxItem>
        <ListBoxItem>3</ListBoxItem>
        <ListBoxItem>ListBox</ListBoxItem>
        <ListBoxItem>2</ListBoxItem>
      </ListBox>
      <Button Click="OnClick" Width="30" Height="20" DockPanel.Dock="Top">Sort</Button>
    </DockPanel>
</Window>

The Click event handler of the button contains logic to sort the items in the ListBox in the descending order. You can do this because adding items to a ListBox this way adds them to the ItemCollection of the ListBox, and ItemCollection derives from the CollectionView class. If you are binding your ListBox to a collection using the ItemsSource property, you can use the same technique to sort.

private void OnClick(object sender, RoutedEventArgs e)
{
    myListBox.Items.SortDescriptions.Add(
        new SortDescription("Content", ListSortDirection.Descending));
}

As long as you have a reference to the view object, you can use the same technique to sort the content of other collection views. For an example of how to obtain a view, see How to: Get the Default View of a Data Collection. For another example, see How to: Sort a GridView Column When a Header Is Clicked. For more information about views, see Binding to Collections in Data Binding Overview.

For an example of how to apply sorting logic in Extensible Application Markup Language (XAML), see How to: Sort and Group Data Using a View in XAML.






How to: Sort and Group Data Using a View in XAML

This example shows how to create a view of a data collection in Extensible Application Markup Language (XAML). Views allow for the functionalities of grouping, sorting, filtering, and the notion of a current item.

Example

In the following example, the static resource named places is defined as a collection of Place objects, in which each Place object is consisted of a city name and the state. The prefix src is mapped to the namespace where the data source Places is defined. The prefix scm maps to "clr-namespace:System.ComponentModel;assembly=WindowsBase" and dat maps to "clr-namespace:System.Windows.Data;assembly=PresentationFramework".

The following example creates a view of the data collection that is sorted by the city name and grouped by the state.

<Window.Resources>

  <src:Places x:Key="places"/>

  <CollectionViewSource Source="{StaticResource places}" x:Key="cvs">
    <CollectionViewSource.SortDescriptions>
      <scm:SortDescription PropertyName="CityName"/>
    </CollectionViewSource.SortDescriptions>
    <CollectionViewSource.GroupDescriptions>
      <dat:PropertyGroupDescription PropertyName="State"/>
    </CollectionViewSource.GroupDescriptions>
  </CollectionViewSource>

The view can then be a binding source, as in the following example:

<ListBox ItemsSource="{Binding Source={StaticResource cvs}}"
         DisplayMemberPath="CityName" Name="lb">
  <ListBox.GroupStyle>
    <x:Static Member="GroupStyle.Default"/>
  </ListBox.GroupStyle>
</ListBox>

For bindings to XML data defined in an XmlDataProvider resource, precede the XML name with an @ symbol.

<XmlDataProvider x:Key="myTasks" XPath="Tasks/Task">
    <x:XData>
        <Tasks xmlns="">
            <Task Name="Groceries" Priority="2" Type="Home">
<CollectionViewSource x:Key="mySortedTasks"
                      Source="{StaticResource myTasks}">
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="@Priority" />
    </CollectionViewSource.SortDescriptions>
    <CollectionViewSource.GroupDescriptions>
        <dat:PropertyGroupDescription PropertyName="@Priority" />
    </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>





How to: Use the Master-Detail Pattern with Hierarchical Data

This example shows how to implement the master-detail scenario.

Example

In this example, LeagueList is a collection of Leagues. Each League has a Name and a collection of Divisions, and each Division has a name and a collection of Teams. Each Team has a team name.

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:src="clr-namespace:SDKSample"
  Width="400" Height="180"
  Title="Master-Detail Binding" 
  Background="Silver">
  <Window.Resources>
    <src:LeagueList x:Key="MyList"/>
  <DockPanel DataContext="{Binding Source={StaticResource MyList}}">
    <StackPanel>
      <Label>My Soccer Leagues</Label>
      <ListBox ItemsSource="{Binding}" DisplayMemberPath="Name"
               IsSynchronizedWithCurrentItem="true"/>
    </StackPanel>

    <StackPanel>
      <Label Content="{Binding Path=Name}"/>
      <ListBox ItemsSource="{Binding Path=Divisions}" DisplayMemberPath="Name"
               IsSynchronizedWithCurrentItem="true"/>
    </StackPanel>

    <StackPanel>
      <Label Content="{Binding Path=Divisions/Name}"/>
      <ListBox DisplayMemberPath="Name" ItemsSource="{Binding Path=Divisions/Teams}"/>
    </StackPanel>
  </DockPanel>
</Window>

The following is a screenshot of the example. The Divisions ListBox automatically tracks selections in the Leagues ListBox and display the corresponding data. The Teams ListBox tracks selections in the other two ListBox controls.

Master-detail example

The two things to notice in this example are:

  1. The three ListBox controls bind to the same source. You set the Path property of the binding to specify which level of data you want the ListBox to display.

  2. You must set the IsSynchronizedWithCurrentItem property to true on the ListBox controls of which the selection you are tracking. Setting this property ensures that the selected item is always set as the CurrentItem. Alternatively, if the ListBox gets it data from a CollectionViewSource, it synchronizes selection and currency automatically.

The technique is slightly different when you are using XML data. For an example, see How to: Use the Master-Detail Pattern with Hierarchical XML Data.






How to: Use the Master-Detail Pattern with Hierarchical XML Data

This example shows how to implement the master-detail scenario with XML data.

Example

This example is the XML data version of the example discussed in How to: Use the Master-Detail Pattern with Hierarchical Data. In this example, the data is from the file League.xml. Note how the third ListBox control tracks selection changes in the second ListBox by binding to its SelectedValue property.

<Window x:Class="SDKSample.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Multiple ListBox Binding Sample"
  Width="400" Height="200"
  Background="Cornsilk">
    <Window.Resources>
      <XmlDataProvider x:Key="MyList" Source="Data\Leagues.xml"
                       XPath="Leagues/League"/>
      <DataTemplate x:Key="dataTemplate">
        <TextBlock Text="{Binding XPath=@name}" />
      </DataTemplate>
    </Window.Resources>

    <DockPanel DataContext="{Binding Source={StaticResource MyList}}">
      <StackPanel>
        <Label>My Soccer Leagues</Label>
        <ListBox ItemsSource="{Binding}"
                 ItemTemplate="{StaticResource dataTemplate}"
                 IsSynchronizedWithCurrentItem="true"/>
      </StackPanel>

      <StackPanel>
        <Label Content="{Binding XPath=@name}"/>
        <ListBox Name="divisionsListBox"
                 ItemsSource="{Binding XPath=Division}"
                 ItemTemplate="{StaticResource dataTemplate}"
                 IsSynchronizedWithCurrentItem="true"/>
      </StackPanel>

      <StackPanel>
        <Label Content="{Binding XPath=@name}"/>
        <ListBox DataContext="{Binding ElementName=divisionsListBox,
                                       Path=SelectedItem}"
                 ItemsSource="{Binding XPath=Team}"
                 ItemTemplate="{StaticResource dataTemplate}"/>
      </StackPanel>
    </DockPanel>
</Window>





How to: Produce a Value Based on a List of Bound Items

MultiBinding allows you to bind a binding target property to a list of source properties and then apply logic to produce a value with the given inputs. This example demonstrates how to use MultiBinding.

Example

In the following example, NameListData refers to a collection of PersonName objects, which are objects that contain two properties, firstName and lastName. The following example produces a TextBlock that shows the first and last names of a person with the last name first.

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:c="clr-namespace:SDKSample"
  x:Class="SDKSample.Window1"
  Width="400"
  Height="280"
  Title="MultiBinding Sample">

  <Window.Resources>
    <c:NameList x:Key="NameListData"/>
    <c:NameConverter x:Key="myNameConverter"/>
</Window.Resources>
<TextBlock Name="textBox2" DataContext="{StaticResource NameListData}">
  <TextBlock.Text>
    <MultiBinding Converter="{StaticResource myNameConverter}"
                  ConverterParameter="FormatLastFirst">
      <Binding Path="FirstName"/>
      <Binding Path="LastName"/>
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>
</Window>

To understand how the last-name-first format is produced, let's take a look at the implementation of the NameConverter:

public class NameConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        string name;

        switch ((string)parameter)
        {
            case "FormatLastFirst":
                name = values[1] + ", " + values[0];
                break;
            case "FormatNormal":
            default:
                name = values[0] + " " + values[1];
                break;
        }

        return name;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        string[] splitValues = ((string)value).Split(' ');
        return splitValues;
    }
}

NameConverter implements the IMultiValueConverter interface. NameConverter takes the values from the individual bindings and stores them in the values object array. The order in which the Binding elements appear under the MultiBinding element is the order in which those values are stored in the array. The value of the ConverterParameter attribute is referenced by the parameter argument of the Converter method, which performs a switch on the parameter to determine how to format the name.






How to: Implement Property Change Notification

To support OneWay or TwoWay binding to enable your binding target properties to automatically reflect the dynamic changes of the binding source (for example, to have the preview pane updated automatically when the user edits a form), your class needs to provide the proper property changed notifications. This example shows how to create a class that implements INotifyPropertyChanged.

Example

To implement INotifyPropertyChanged you need to declare the PropertyChanged event and create the OnPropertyChanged method. Then for each property you want change notifications for, you call OnPropertyChanged whenever the property is updated.

using System.ComponentModel;

namespace SDKSample
{
  // This class implements INotifyPropertyChanged
  // to support one-way and two-way bindings
  // (such that the UI element updates when the source
  // has been changed dynamically)
  public class Person : INotifyPropertyChanged
  {
      private string name;
      // Declare the event
      public event PropertyChangedEventHandler PropertyChanged;

      public Person()
      {
      }

      public Person(string value)
      {
          this.name = value;
      }

      public string PersonName
      {
          get { return name; }
          set
          {
              name = value;
              // Call OnPropertyChanged whenever the property is updated
              OnPropertyChanged("PersonName");
          }
      }

      // Create the OnPropertyChanged method to raise the event
      protected void OnPropertyChanged(string name)
      {
          PropertyChangedEventHandler handler = PropertyChanged;
          if (handler != null)
          {
              handler(this, new PropertyChangedEventArgs(name));
          }
      }
  }
}

To see an example of how the Person class can be used to support TwoWay binding, see How to: Control When the TextBox Text Updates the Source.






How to: Create and Bind to an ObservableCollection

This example shows how to create and bind to a collection that derives from the ObservableCollection<T> class, which is a collection class that provides notifications when items get added or removed.

Example

The following example shows the implementation of a NameList collection:

public class NameList : ObservableCollection<PersonName>
{
    public NameList() : base()
    {
        Add(new PersonName("Willa", "Cather"));
        Add(new PersonName("Isak", "Dinesen"));
        Add(new PersonName("Victor", "Hugo"));
        Add(new PersonName("Jules", "Verne"));
    }
  }

  public class PersonName
  {
      private string firstName;
      private string lastName;

      public PersonName(string first, string last)
      {
          this.firstName = first;
          this.lastName = last;
      }

      public string FirstName
      {
          get { return firstName; }
          set { firstName = value; }
      }

      public string LastName
      {
          get { return lastName; }
          set { lastName = value; }
      }
  }

You can make the collection available for binding the same way you would with other common language runtime (CLR) objects, as described in How to: Make Data Available for Binding in XAML. For example, you can instantiate the collection in XAML and specify the collection as a resource, as shown here:

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:c="clr-namespace:SDKSample"
  x:Class="SDKSample.Window1"
  Width="400"
  Height="280"
  Title="MultiBinding Sample">

  <Window.Resources>
    <c:NameList x:Key="NameListData"/>


...


</Window.Resources>

You can then bind to the collection:

<ListBox Width="200"
         ItemsSource="{Binding Source={StaticResource NameListData}}"
         ItemTemplate="{StaticResource NameItemTemplate}"
         IsSynchronizedWithCurrentItem="True"/>


The definition of NameItemTemplate is not shown here.

System_CAPS_noteNote

The objects in your collection must satisfy the requirements described in the Binding Sources Overview. In particular, if you are using OneWay or TwoWay (for example, you want your UI to update when the source properties change dynamically), you must implement a suitable property changed notification mechanism such as the INotifyPropertyChanged interface.

For more information, see the Binding to Collections section in the Data Binding Overview.






How to: Implement PriorityBinding

PriorityBinding in Windows Presentation Foundation (WPF) works by specifying a list of bindings. The list of bindings is ordered from highest priority to lowest priority. If the highest priority binding returns a value successfully when it is processed then there is never a need to process the other bindings in the list. It could be the case that the highest priority binding takes a long time to be evaluated, the next highest priority that returns a value successfully will be used until a binding of a higher priority returns a value successfully.

Example

To demonstrate how PriorityBinding works, the AsyncDataSource object has been created with the following three properties: FastDPSlowerDP, and SlowestDP.

The get accessor of FastDP returns the value of the _fastDP data member.

The get accessor of SlowerDP waits for 3 seconds before returning the value of the _slowerDP data member.

The get accessor of SlowestDP waits for 5 seconds before returning the value of the _slowestDP data member.

System_CAPS_noteNote

This example is for demonstration purposes only. The Microsoft .NET guidelines recommend against defining properties that are orders of magnitude slower than a field set would be. For more information, see NIB: Choosing Between Properties and Methods.

public class AsyncDataSource
{
	private string _fastDP;
	private string _slowerDP;
	private string _slowestDP;

	public AsyncDataSource()
	{
	}

	public string FastDP
	{
    get { return _fastDP; }
    set { _fastDP = value; }
	}

	public string SlowerDP
	{
    get
    {
      // This simulates a lengthy time before the
      // data being bound to is actualy available.
      Thread.Sleep(3000);
      return _slowerDP;
    }
    set { _slowerDP = value; }
	}

	public string SlowestDP
	{
    get
    {
      // This simulates a lengthy time before the
      // data being bound to is actualy available.
      Thread.Sleep(5000);
      return _slowestDP;
    }
    set { _slowestDP = value; }
	}
}

The Text property binds to the above AsyncDS using PriorityBinding:

<Window.Resources>
  <c:AsyncDataSource SlowestDP="Slowest Value" SlowerDP="Slower Value"
                     FastDP="Fast Value" x:Key="AsyncDS" />
</Window.Resources>

<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"
  DataContext="{Binding Source={StaticResource AsyncDS}}">
  <TextBlock FontSize="18" FontWeight="Bold" Margin="10"
    HorizontalAlignment="Center">Priority Binding</TextBlock>
  <TextBlock Background="Honeydew" Width="100" HorizontalAlignment="Center">
    <TextBlock.Text>
      <PriorityBinding FallbackValue="defaultvalue">
        <Binding Path="SlowestDP" IsAsync="True"/>
        <Binding Path="SlowerDP" IsAsync="True"/>
        <Binding Path="FastDP" />
      </PriorityBinding>
    </TextBlock.Text>
  </TextBlock>	
</StackPanel>

When the binding engine processes the Binding objects, it starts with the first Binding, which is bound to the SlowestDP property. When this Binding is processed, it does not return a value successfully because it is sleeping for 5 seconds, so the next Binding element is processed. The next Binding does not return a value successfully because it is sleeping for 3 seconds. The binding engine then moves onto the next Binding element, which is bound to the FastDP property. This Binding returns the value "Fast Value". The TextBlock now displays the value "Fast Value".

After 3 seconds elapses, the SlowerDP property returns the value "Slower Value". The TextBlock then displays the value "Slower Value".

After 5 seconds elapses, the SlowestDP property returns the value "Slowest Value". That binding has the highest priority because it is listed first. The TextBlock now displays the value "Slowest Value".

See PriorityBinding for information about what is considered a successful return value from a binding.





How to: Bind to XML Data Using an XMLDataProvider and XPath Queries

This example shows how to bind to XML data using an XmlDataProvider.

With an XmlDataProvider, the underlying data that can be accessed through data binding in your application can be any tree of XML nodes. In other words, an XmlDataProvider provides a convenient way to use any tree of XML nodes as a binding source.

Example

In the following example, the data is embedded directly as an XML data island within the Resources section. An XML data island must be wrapped in <x:XData> tags and always have a single root node, which is Inventory in this example.

System_CAPS_noteNote

The root node of the XML data has an xmlns attribute that sets the XML namespace to an empty string. This is a requirement for applying XPath queries to a data island that is inline within the XAML page. In this inline case, the XAML, and thus the data island, inherits the System.Windows namespace. Because of this, you need to set the namespace blank to keep XPath queries from being qualified by the System.Windows namespace, which would misdirect the queries.

<StackPanel
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Background="Cornsilk">

  <StackPanel.Resources>
    <XmlDataProvider x:Key="InventoryData" XPath="Inventory/Books">
      <x:XData>
        <Inventory xmlns="">
          <Books>
            <Book ISBN="0-7356-0562-9" Stock="in" Number="9">
              <Title>XML in Action</Title>
              <Summary>XML Web Technology</Summary>
            </Book>
            <Book ISBN="0-7356-1370-2" Stock="in" Number="8">
              <Title>Programming Microsoft Windows With C#</Title>
              <Summary>C# Programming using the .NET Framework</Summary>
            </Book>
            <Book ISBN="0-7356-1288-9" Stock="out" Number="7">
              <Title>Inside C#</Title>
              <Summary>C# Language Programming</Summary>
            </Book>
            <Book ISBN="0-7356-1377-X" Stock="in" Number="5">
              <Title>Introducing Microsoft .NET</Title>
              <Summary>Overview of .NET Technology</Summary>
            </Book>
            <Book ISBN="0-7356-1448-2" Stock="out" Number="4">
              <Title>Microsoft C# Language Specifications</Title>
              <Summary>The C# language definition</Summary>
            </Book>
          </Books>
          <CDs>
            <CD Stock="in" Number="3">
              <Title>Classical Collection</Title>
              <Summary>Classical Music</Summary>
            </CD>
            <CD Stock="out" Number="9">
              <Title>Jazz Collection</Title>
              <Summary>Jazz Music</Summary>
            </CD>
          </CDs>
        </Inventory>
      </x:XData>
    </XmlDataProvider>
  </StackPanel.Resources>

  <TextBlock FontSize="18" FontWeight="Bold" Margin="10"
    HorizontalAlignment="Center">XML Data Source Sample</TextBlock>
  <ListBox
    Width="400" Height="300" Background="Honeydew">
    <ListBox.ItemsSource>
      <Binding Source="{StaticResource InventoryData}"
               XPath="*[@Stock='out'] | *[@Number>=8 or @Number=3]"/>
    </ListBox.ItemsSource>

    <!--Alternatively, you can do the following. -->
    <!--<ListBox Width="400" Height="300" Background="Honeydew"
      ItemsSource="{Binding Source={StaticResource InventoryData},
      XPath=*[@Stock\=\'out\'] | *[@Number>\=8 or @Number\=3]}">-->

    <ListBox.ItemTemplate>
      <DataTemplate>
        <TextBlock FontSize="12" Foreground="Red">
          <TextBlock.Text>
            <Binding XPath="Title"/>
          </TextBlock.Text>
        </TextBlock>
      </DataTemplate>
    </ListBox.ItemTemplate>
  </ListBox>
</StackPanel>

As shown in this example, to create the same binding declaration in attribute syntax you must escape the special characters properly. For more information, see XML Character Entities and XAML.

The ListBox will show the following items when this example is run. These are the Titles of all of the elements under Books with either a Stock value of "out" or a Number value of 3 or greater than or equals to 8. Notice that no CD items are returned because the XPath value set on the XmlDataProvider indicates that only the Books elements should be exposed (essentially setting a filter).

XPath Example

In this example, the book titles are displayed because the XPath of the TextBlock binding in the DataTemplate is set to "Title". If you want to display the value of an attribute, such as the ISBN, you would set that XPath value to "@ISBN".

The XPath properties in WPF are handled by the XmlNode.SelectNodes method. You can modify the XPath queries to get different results. Here are some examples for the XPath query on the bound ListBox from the previous example:

  • XPath="Book[1]" will return the first book element ("XML in Action"). Note that XPath indexes are based on 1, not 0.

  • XPath="Book[@*]" will return all book elements with any attributes.

  • XPath="Book[last()-1]" will return the second to last book element ("Introducing Microsoft .NET").

  • XPath="*[position()>3]" will return all of the book elements except for the first 3.

When you run an XPath query, it returns an XmlNode or a list of XmlNodes. XmlNode is a common language runtime (CLR) object, which means you can use the Path property to bind to the common language runtime (CLR) properties. Consider the previous example again. If the rest of the example stays the same and you change the TextBlock binding to the following, you will see the names of the returned XmlNodes in the ListBox. In this case, the name of all the returned nodes is "Book".

<TextBlock FontSize="12" Foreground="Red">
  <TextBlock.Text>
    <Binding Path="Name"/>
  </TextBlock.Text>
</TextBlock>

In some applications, embedding the XML as a data island within the source of the XAML page can be inconvenient because the exact content of the data must be known at compile time. Therefore, obtaining the data from an external XML file is also supported, as in the following example:

<XmlDataProvider x:Key="BookData" Source="data\bookdata.xml" XPath="Books"/>

If the XML data resides in a remote XML file, you would define access to the data by assigning an appropriate URL to the Source attribute as follows:

<XmlDataProvider x:Key="BookData" Source="http://MyUrl" XPath="Books"/>





How to: Bind to XDocument, XElement, or LINQ for XML Query Results

This example demonstrates how to bind XML data to an ItemsControl using XDocument.

Example

The following XAML code defines an ItemsControl and includes a data template for data of type Planet in the http://planetsNS XML namespace. An XML data type that occupies a namespace must include the namespace in braces, and if it appears where a XAML markup extension could appear, it must precede the namespace with a brace escape sequence. This code binds to dynamic properties that correspond to the Element and Attribute methods of the XElement class. Dynamic properties enable XAML to bind to dynamic properties that share the names of methods. To learn more, see LINQ to XML Dynamic Properties. Notice how the default namespace declaration for the XML does not apply to attribute names.

<StackPanel Name="stacky">
  <StackPanel.Resources>
    <DataTemplate DataType="{}{http://planetsNS}Planet" >
      <StackPanel Orientation="Horizontal">
        <TextBlock Width="100" Text="{Binding Path=Element[{http://planetsNS}DiameterKM].Value}" />
        <TextBlock Width="100" Text="{Binding Path=Attribute[Name].Value}" />
        <TextBlock Text="{Binding Path=Element[{http://planetsNS}Details].Value}" /> 
      </StackPanel>
    </DataTemplate>
  </StackPanel.Resources>
  <ItemsControl 
    ItemsSource="{Binding }" >
  </ItemsControl>
</StackPanel>

The following C# code calls Load and sets the stack panel data context to all subelements of the element named SolarSystemPlanets in the http://planetsNS XML namespace.

planetsDoc = XDocument.Load("../../Planets.xml");
stacky.DataContext = planetsDoc.Element("{http://planetsNS}SolarSystemPlanets").Elements();

XML data can be stored as a XAML resource using ObjectDataProvider. For a complete example, see L2DBForm.xaml Source Code. The following sample shows how code can set the data context to an object resource.

planetsDoc = (XDocument)((ObjectDataProvider)Resources["justTwoPlanets"]).Data;
stacky.DataContext = planetsDoc.Element("{http://planetsNS}SolarSystemPlanets").Elements();

The dynamic properties that map to Element and Attribute provide flexibility within XAML. Your code can also bind to the results of a LINQ for XML query. This example binds to query results ordered by an element value.

stacky.DataContext =
from c in planetsDoc.Element("{http://planetsNS}SolarSystemPlanets").Elements()
orderby Int32.Parse(c.Element("{http://planetsNS}DiameterKM").Value)
select c;





How to: Use XML Namespaces in Data Binding

Example

This example shows how to handle namespaces specified in your XML binding source.

If your XML data has the following XML namespace definition:

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">

You can use the XmlNamespaceMapping element to map the namespace to a Prefix, as in the following example. You can then use the Prefix to refer to the XML namespace. The ListBox in this example displays the title and dc:date of each item.

<StackPanel.Resources>
  <XmlNamespaceMappingCollection x:Key="mapping">
    <XmlNamespaceMapping Uri="http://purl.org/dc/elements/1.1/" Prefix="dc" />
  </XmlNamespaceMappingCollection>

  <XmlDataProvider Source="http://msdn.microsoft.com/subscriptions/rss.xml"
                   XmlNamespaceManager="{StaticResource mapping}"
                   XPath="rss/channel/item" x:Key="provider"/>

  <DataTemplate x:Key="dataTemplate">
    <Border BorderThickness="1" BorderBrush="Gray">
      <Grid Width="600" Height="50">
        <Grid.RowDefinitions>
          <RowDefinition Height="25"/>
          <RowDefinition Height="25"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" Text="{Binding XPath=title}" />
        <TextBlock Grid.Row="1" Text="{Binding XPath=dc:date}" />
      </Grid>
    </Border>
  </DataTemplate>
</StackPanel.Resources>

<ListBox
  Width="600"
  Height="600"
  Background="Honeydew"
  ItemsSource="{Binding Source={StaticResource provider}}"
  ItemTemplate="{StaticResource dataTemplate}"/>

Note that the Prefix you specify does not have to match the one used in the XML source; if the prefix changes in the XML source your mapping still works.

In this particular example, the XML data comes from a web service, but the XmlNamespaceMapping element also works with inline XML or XML data in an embedded file.






How to: Bind to an ADO.NET Data Source

This example shows how to bind a Windows Presentation Foundation (WPF) ListBox control to an ADO.NET DataSet.

Example

In this example, an OleDbConnection object is used to connect to the data source which is an Access MDB file that is specified in the connection string. After the connection is established, an OleDbDataAdpater object is created. The OleDbDataAdpater object executes a select Structured Query Language (SQL) statement to retrieve the recordset from the database. The results from the SQL command are stored in a DataTable of the DataSet by calling the Fill method of the OleDbDataAdapter. The DataTable in this example is named BookTable. The example then sets the DataContext property of the ListBox to the DataSet object.

DataSet myDataSet;

private void OnInit(object sender, EventArgs e)
{
  string mdbFile = Path.Combine(AppDataPath, "BookData.mdb");
  string connString = string.Format(
      "Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0}", mdbFile);
  OleDbConnection conn = new OleDbConnection(connString);
  OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM BookTable;", conn);

  myDataSet = new DataSet();
  adapter.Fill(myDataSet, "BookTable");

  // myListBox is a ListBox control.
  // Set the DataContext of the ListBox to myDataSet
  myListBox.DataContext = myDataSet;
}

We can then bind the ItemsSource property of the ListBox to BookTable of the DataSet:

<ListBox Name="myListBox" Height="200"
  ItemsSource="{Binding Path=BookTable}"
  ItemTemplate  ="{StaticResource BookItemTemplate}"/>

BookItemTemplate is the DataTemplate that defines how the data appears:

<StackPanel.Resources>
  <c:IntColorConverter x:Key="MyConverter"/>

  <DataTemplate x:Key="BookItemTemplate">
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="250" />
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="*"/>
      </Grid.ColumnDefinitions>
      <TextBlock Text="{Binding Path=Title}" Grid.Column="0"
        FontWeight="Bold" />
      <TextBlock Text="{Binding Path=ISBN}" Grid.Column="1" />
      <TextBlock Grid.Column="2" Text="{Binding Path=NumPages}"
                 Background="{Binding Path=NumPages,
          Converter={StaticResource MyConverter}}"/>
    </Grid>
  </DataTemplate>
</StackPanel.Resources>

The IntColorConverter converts an int to a color. With the use of this converter, the Background color of the third TextBlock appears green if the value of NumPages is less than 350 and red otherwise. The implementation of the converter is not shown here.






How to: Bind to a Method

The following example shows how to bind to a method using ObjectDataProvider.

Example

In this example, TemperatureScale is a class that has a method ConvertTemp, which takes two parameters (one of double and one of the enum type TempType) and converts the given value from one temperature scale to another. In the following example, an ObjectDataProvider is used to instantiate the TemperatureScale object. The ConvertTemp method is called with two specified parameters.

<Window.Resources>
  <ObjectDataProvider ObjectType="{x:Type local:TemperatureScale}"
                      MethodName="ConvertTemp" x:Key="convertTemp">
    <ObjectDataProvider.MethodParameters>
      <system:Double>0</system:Double>
      <local:TempType>Celsius</local:TempType>
    </ObjectDataProvider.MethodParameters>
  </ObjectDataProvider>

  <local:DoubleToString x:Key="doubleToString" />

</Window.Resources>

Now that the method is available as a resource, you can bind to its results. In the following example, the Text property of the TextBox and the SelectedValue of the ComboBox are bound to the two parameters of the method. This allows users to specify the temperature to convert and the temperature scale to convert from. Note that BindsDirectlyToSource is set to true because we are binding to the MethodParameters property of the ObjectDataProvider instance and not properties of the object wrapped by the ObjectDataProvider (the TemperatureScale object).

The Content of the last Label updates when the user modifies the content of the TextBox or the selection of the ComboBox.

<Label Grid.Row="1" HorizontalAlignment="Right">Enter the degree to convert:</Label>
<TextBox Grid.Row="1" Grid.Column="1" Name="tb">
  <TextBox.Text>
    <Binding Source="{StaticResource convertTemp}" Path="MethodParameters[0]"
             BindsDirectlyToSource="true" UpdateSourceTrigger="PropertyChanged"
             Converter="{StaticResource doubleToString}">
      <Binding.ValidationRules>
        <local:InvalidCharacterRule/>
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>
<ComboBox Grid.Row="1" Grid.Column="2" 
  SelectedValue="{Binding Source={StaticResource convertTemp},
  Path=MethodParameters[1], BindsDirectlyToSource=true}">
  <local:TempType>Celsius</local:TempType>
  <local:TempType>Fahrenheit</local:TempType>
</ComboBox>
<Label Grid.Row="2" HorizontalAlignment="Right">Result:</Label>
<Label Content="{Binding Source={StaticResource convertTemp}}"
    Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2"/>

The converter DoubleToString takes a double and turns it into a string in the Convert direction (from the binding source to binding target, which is the Text property) and converts a string to a double in the ConvertBack direction.

The InvalidationCharacterRule is a ValidationRule that checks for invalid characters. The default error template, which is a red border around the TextBox, appears to notify users when the input value is not a double value.






How to: Set Up Notification of Binding Updates

This example shows how to set up to be notified when the binding target (target) or the binding source (source) property of a binding has been updated.

Example

Windows Presentation Foundation (WPF) raises a data update event each time that the binding source or target has been updated. Internally, this event is used to inform the user interface (UI) that it should update, because the bound data has changed. Note that for these events to work, and also for one-way or two-way binding to work properly, you need to implement your data class using the INotifyPropertyChanged interface. For more information, see How to: Implement Property Change Notification.

Set the NotifyOnTargetUpdated or NotifyOnSourceUpdated property (or both) to true in the binding. The handler you provide to listen for this event must be attached directly to the element where you want to be informed of changes, or to the overall data context if you want to be aware that anything in the context has changed.

Here is an example that shows how to set up for notification when a target property has been updated.

<TextBlock Grid.Row="1" Grid.Column="1" Name="RentText"
  Text="{Binding Path=Rent, Mode=OneWay, NotifyOnTargetUpdated=True}"
  TargetUpdated="OnTargetUpdated"/>

You can then assign a handler based on the EventHandler<T> delegate, OnTargetUpdated in this example, to handle the event:

private void OnTargetUpdated(Object sender, DataTransferEventArgs args)
{

  // Handle event
}

Parameters of the event can be used to determine details about the property that changed (such as the type or the specific element if the same handler is attached to more than one element), which can be useful if there are multiple bound properties on a single element.






How to: Clear Bindings

This example shows how to clear bindings from an object.

Example

To clear a binding from an individual property on an object, call ClearBinding as shown in the following example. The following example removes the binding from the TextProperty of mytext, a TextBlock object.

BindingOperations.ClearBinding(myText, TextBlock.TextProperty);

Clearing the binding removes the binding so that the value of the dependency property is changed to whatever it would have been without the binding. This value could be a default value, an inherited value, or a value from a data template binding.

To clear bindings from all possible properties on an object, use ClearAllBindings.






How to: Find DataTemplate-Generated Elements

This example shows how to find elements that are generated by a DataTemplate.

Example

In this example, there is a ListBox that is bound to some XML data:

<ListBox Name="myListBox" ItemTemplate="{StaticResource myDataTemplate}"
         IsSynchronizedWithCurrentItem="True">
  <ListBox.ItemsSource>
    <Binding Source="{StaticResource InventoryData}" XPath="Books/Book"/>
  </ListBox.ItemsSource>
</ListBox>

The ListBox uses the following DataTemplate:

<DataTemplate x:Key="myDataTemplate">
  <TextBlock Name="textBlock" FontSize="14" Foreground="Blue">
    <TextBlock.Text>
      <Binding XPath="Title"/>
    </TextBlock.Text>
  </TextBlock>
</DataTemplate>

If you want to retrieve the TextBlock element generated by the DataTemplate of a certain ListBoxItem, you need to get the ListBoxItem, find the ContentPresenter within that ListBoxItem, and then call FindName on the DataTemplate that is set on that ContentPresenter. The following example shows how to perform those steps. For demonstration purposes, this example creates a message box that shows the text content of the DataTemplate-generated text block.

// Getting the currently selected ListBoxItem
// Note that the ListBox must have
// IsSynchronizedWithCurrentItem set to True for this to work
ListBoxItem myListBoxItem =
    (ListBoxItem)(myListBox.ItemContainerGenerator.ContainerFromItem(myListBox.Items.CurrentItem));

// Getting the ContentPresenter of myListBoxItem
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);

// Finding textBlock from the DataTemplate that is set on that ContentPresenter
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
TextBlock myTextBlock = (TextBlock)myDataTemplate.FindName("textBlock", myContentPresenter);

// Do something to the DataTemplate-generated TextBlock
MessageBox.Show("The text of the TextBlock of the selected list item: "
    + myTextBlock.Text);

The following is the implementation of FindVisualChild, which uses the VisualTreeHelper methods:

private childItem FindVisualChild<childItem>(DependencyObject obj)
    where childItem : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if (child != null && child is childItem)
            return (childItem)child;
        else
        {
            childItem childOfChild = FindVisualChild<childItem>(child);
            if (childOfChild != null)
                return childOfChild;
        }
    }
    return null;
}





How to: Bind to a Web Service

This example shows how to bind to objects returned by Web service method calls.

Example

This example uses the MSDN/TechNet Publishing System (MTPS) Content Service to retrieve the list of languages supported by a specified document.

Before you call a Web service, you need to create a reference to it. To create a Web reference to the MTPS service using Microsoft Visual Studio, follow the following steps:

  1. Open your project in Visual Studio.

  2. From the Project menu, click Add Web Reference.

  3. In the dialog box, set the URL to http://services.msdn.microsoft.com/contentservices/contentservice.asmx?wsdl.

  4. Press Go and then Add Reference.

Next, you call the Web service method and set the DataContext of the appropriate control or window to the returned object. The GetContent method of the MTPS service takes a reference to the getContentRequest object. Therefore, the following example first sets up a request object:

// 1. Include the web service namespace
using BindtoContentService.com.microsoft.msdn.services;
// 2. Set up the request object
// To use the MSTP web service, we need to configure and send a request
// In this example, we create a simple request that has the ID of the XmlReader.Read method page
getContentRequest request = new getContentRequest();
request.contentIdentifier = "abhtw0f1";

// 3. Create the proxy
ContentService proxy = new ContentService();

// 4. Call the web service method and set the DataContext of the Window
// (GetContent returns an object of type getContentResponse)
this.DataContext = proxy.GetContent(request);

After the DataContext has been set, you can create bindings to the properties of the object that the DataContext has been set to. In this example, the DataContext is set to the getContentResponse object returned by the GetContent method. In the following example, the ItemsControl binds to and displays the locale values of availableVersionsAndLocales of getContentResponse.

<ItemsControl Grid.Column="1" Grid.Row="2" Margin="0,3,0,0"
              ItemsSource="{Binding Path=availableVersionsAndLocales}"
              DisplayMemberPath="locale"/>

For information about the structure of getContentResponse, see Content Service documentation.






How to: Bind to the Results of a LINQ Query

This example demonstrates how to run a LINQ query and then bind to the results.

Example

The following example creates two list boxes. The first list box contains three list items.

<ListBox SelectionChanged="ListBox_SelectionChanged"
         SelectedIndex="0" Margin="10,0,10,0" >
    <ListBoxItem>1</ListBoxItem>
    <ListBoxItem>2</ListBoxItem>
    <ListBoxItem>3</ListBoxItem>
</ListBox>
<ListBox Width="400" Margin="10" Name="myListBox"
         HorizontalContentAlignment="Stretch"
         ItemsSource="{Binding}"
         ItemTemplate="{StaticResource myTaskTemplate}"/>

Selecting an item from the first list box invokes the following event handler. In this example, Tasks is a collection of Task objects. The Task class has a property named Priority. This event handler runs a LINQ query that returns the collection of Task objects that have the selected priority value, and then sets that as the DataContext:

using System.Linq;
Tasks tasks = new Tasks();
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    int pri = Int32.Parse(((sender as ListBox).SelectedItem as ListBoxItem).Content.ToString());

    this.DataContext = from task in tasks
                       where task.Priority == pri
                       select task;
}

The second list box binds to that collection because its ItemsSource value is set to {Binding}. As a result, it displays the returned collection (based on the myTaskTemplate DataTemplate).




















'프로그래밍 > WPF' 카테고리의 다른 글

Properties  (0) 2017.01.24
Graphics and Multimedia - Multimedia, Visual Layer  (0) 2017.01.14
Graphics and Multimedia - Animation Overview  (0) 2017.01.07
Graphics and Multimedia  (0) 2016.11.24
Documents  (0) 2016.11.19
:
Posted by 지훈2


Animation Overview


https://msdn.microsoft.com/en-us/library/ms752312(v=vs.110).aspx


Windows Presentation Foundation (WPF) provides a powerful set of graphics and layout features that enable you to create attractive user interfaces and appealing documents. Animation can make an attractive user interface even more spectacular and usable. By just animating a background color or applying an animated  Transform, you can create dramatic screen transitions or provide helpful visual cues.

This overview provides an introduction to the WPF animation and timing system. It focuses on the animation of WPF objects by using storyboards. 

Introducing Animations

Animation is an illusion that is created by quickly cycling through a series of images, each slightly different from the last. The brain perceives the group of images as a single changing scene. In film, this illusion is created by using cameras that record many photographs, or frames, each second. When the frames are played back by a projector, the audience sees a moving picture.

Animation on a computer is similar. For example, a program that makes a drawing of a rectangle fade out of view might work as follows.

  • The program creates a timer.

  • The program checks the timer at set intervals to see how much time has elapsed.

  • Each time the program checks the timer, it computes the current opacity value for the rectangle based on how much time has elapsed.

  • The program then updates the rectangle with the new value and redraws it.

Prior to WPF, Microsoft Windows developers had to create and manage their own timing systems or use special custom libraries. WPF includes an efficient timing system that is exposed through managed code and Extensible Application Markup Language (XAML) and that is deeply integrated into the WPF framework.  WPF animation makes it easy to animate controls and other graphical objects.

WPF handles all the behind-the-scenes work of managing a timing system and redrawing the screen efficiently. It provides timing classes that enable you to focus on the effects you want to create, instead of the mechanics of achieving those effects. WPF also makes it easy to create your own animations by exposing animation base classes from which your classes can inherit, to produce customized animations. These custom animations gain many of the performance benefits of the standard animation classes.

WPF Property Animation System

If you understand a few important concepts about the timing system, WPF animations can be easier to use. Most important is that, in WPF, you animate objects by applying animation to their individual properties. For example, to make a framework element grow, you animate its  Width andHeight properties. To make an object fade from view, you animate its Opacity property.

For a property to have animation capabilities, it must meet the following three requirements:

WPF contains many objects that have IAnimatable properties. Controls such as Button and TabControl, and also  Panel and Shape objects inherit fromDependencyObject. Most of their properties are dependency properties

You can use animations almost anywhere, which includes in styles and control templates. Animations do not have to be visual; you can animate objects that are not part of the user interface if they meet the criteria that are described in this section.

Example: Make an Element Fade In and Out of View

This example shows how to use a WPF animation to animate the value of a dependency property. It uses a DoubleAnimation, which is a type of animation that generates Double values, to animate the Opacity property of a Rectangle. As a result, the Rectangle fades in and out of view.

The first part of the example creates a Rectangle element. The steps that follow show how to create an animation and apply it to the rectangle'sOpacity property .

The following shows how to create a Rectangle element in a StackPanel in XAML.

<StackPanel Margin="10">
    <Rectangle
        Name="MyRectangle"
        Width="100" 
        Height="100"
        Fill="Blue">
    </Rectangle>
</StackPanel>

The following shows how to create a Rectangle element in a StackPanel in code.

StackPanel myPanel = new StackPanel();
myPanel.Margin = new Thickness(10);

Rectangle myRectangle = new Rectangle();
myRectangle.Name = "myRectangle";
this.RegisterName(myRectangle.Name, myRectangle);
myRectangle.Width = 100;
myRectangle.Height = 100;
myRectangle.Fill = Brushes.Blue;
myPanel.Children.Add(myRectangle);
this.Content = myPanel;

Part 1: Create a DoubleAnimation

One way to make an element fade in and out of view is to animate its Opacity property. Because the Opacity property is of type Double, you need an animation that produces double values. A DoubleAnimation is one such animation . A DoubleAnimation creates a transition between two double values. To specify its starting value, you set its From property. To specify its ending value, you set its To property.

  1. An opacity value of 1.0 makes the object completely opaque, and an opacity value of 0.0 makes it completely invisible. To make the animation transition from 1.0 to 0.0 you set its From property to 1.0 and its To property to 0.0. The following shows how to create aDoubleAnimation in XAML.

    <DoubleAnimation From="1.0" To="0.0" />
    

    The following shows how to create a DoubleAnimation in code.

    DoubleAnimation myDoubleAnimation = new DoubleAnimation();
    myDoubleAnimation.From = 1.0;
    myDoubleAnimation.To = 0.0;
    
  2. Next, you must specify a Duration. The Duration of an animation specifies how long it takes to go from its starting value to its destination value. The following shows how to set the Duration to five seconds in XAML.

    <DoubleAnimation From="1.0" To="0.0" Duration="0:0:5" />
    

    The following shows how to set the Duration to five seconds in code.

    myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
    
  3. The previous code showed an animation that transitions from 1.0 to 0.0, which causes the target element to fade from completely opaque to completely invisible. To make the element fade back into view after it vanishes, set the AutoReverse property of the animation to true. To make the animation repeat indefinitely, set its RepeatBehavior property to Forever.The following shows how to set the AutoReverse andRepeatBehavior properties in XAML.

    <DoubleAnimation From="1.0" To="0.0" Duration="0:0:5" AutoReverse="True" RepeatBehavior="Forever"/>
    

    The following shows how to set the AutoReverse and RepeatBehavior properties in code.

    myDoubleAnimation.AutoReverse = true;
    myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
    

Part 2: Create a Storyboard

To apply an animation to an object, you create a Storyboard and use the TargetName and TargetPropertyattached properties to specify the object and property to animate.

  1. Create the Storyboard and add the animation as its child. The following shows how to create the Storyboard in XAML.

    <Storyboard>
        <DoubleAnimation
            From="1.0" To="0.0" Duration="0:0:1" 
            AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>
    

    To create the Storyboard in code, declare a Storyboard variable at the class level.

    public partial class MainWindow : Window
    {
        private Storyboard myStoryboard;
    

    Then initialize the Storyboard and add the animation as its child.

    myStoryboard = new Storyboard();
    myStoryboard.Children.Add(myDoubleAnimation);
    
  2. The Storyboard has to know where to apply the animation. Use the Storyboard.TargetName attached property to specify the object to animate. The following shows how to set the target name of the DoubleAnimation to MyRectangle in XAML.

    <Storyboard>
        <DoubleAnimation
            Storyboard.TargetName="MyRectangle" 
            From="1.0" To="0.0" Duration="0:0:1" 
            AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>
    

    The following shows how to set the target name of the DoubleAnimation to MyRectangle in code.

    Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
    
  3. Use the TargetProperty attached property to specify the property to animate. The following shows how the animation is configured to target the Opacity property of the Rectangle in XAML .

    <Storyboard>
        <DoubleAnimation
            Storyboard.TargetName="MyRectangle" 
            Storyboard.TargetProperty="Opacity"
            From="1.0" To="0.0" Duration="0:0:5" 
            AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>
    

    The following shows how the animation is configured to target the Opacity property of the Rectangle in code.

    Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.OpacityProperty));
    

For more information about TargetProperty syntax and for additional examples, see the Storyboards Overview.

Part 3 (XAML): Associate the Storyboard with a Trigger

The easiest way to apply and start a Storyboard in XAML is to use an event trigger . This section shows how to associate the Storyboard with a trigger in XAML.

  1. Create a BeginStoryboard object and associate your storyboard with it. A BeginStoryboard is a type of TriggerAction that applies and starts a Storyboard.

    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Storyboard.TargetName="MyRectangle" 
          Storyboard.TargetProperty="Opacity"
          From="1.0" To="0.0" Duration="0:0:5" 
          AutoReverse="True" RepeatBehavior="Forever" />
      </Storyboard>
    </BeginStoryboard>
    
  2. Create an EventTrigger and add the BeginStoryboard to its Actions collection. Set the RoutedEvent property of the EventTrigger to therouted event that you want to start the Storyboard. (For more information about routed events, see the Routed Events Overview.)

    <!-- Animates the rectangle's opacity. -->
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimation
            Storyboard.TargetName="MyRectangle" 
            Storyboard.TargetProperty="Opacity"
            From="1.0" To="0.0" Duration="0:0:5" 
            AutoReverse="True" RepeatBehavior="Forever" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
    

  3. Add the EventTrigger to the Triggers collection of the Rectangle.

    <Rectangle
      Name="MyRectangle"
      Width="100" 
      Height="100"
      Fill="Blue">
      <Rectangle.Triggers>
        <!-- Animates the rectangle's opacity. -->
        <EventTrigger RoutedEvent="Rectangle.Loaded">
          <BeginStoryboard>
            <Storyboard>
              <DoubleAnimation
                Storyboard.TargetName="MyRectangle" 
                Storyboard.TargetProperty="Opacity"
                From="1.0" To="0.0" Duration="0:0:5" 
                AutoReverse="True" RepeatBehavior="Forever" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers>
    </Rectangle>
    

Part 3 (Code): Associate the Storyboard with an Event Handler

The easiest way to apply and start a Storyboard in code is to use an event handler. This section shows how to associate the Storyboard with an event handler in code.

  1. Register for the Loaded event of the rectangle.

    myRectangle.Loaded += new RoutedEventHandler(myRectangleLoaded);
    
  2. Declare the event handler. In the event handler, use the Begin method to apply the storyboard.

    private void myRectangleLoaded(object sender, RoutedEventArgs e)
    {
        myStoryboard.Begin(this);
    }
    

Complete Example

The following shows how to create a rectangle that fades in and out of view in XAML .

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel Margin="10">
            <Rectangle
                Name="MyRectangle"
                Width="100" 
                Height="100"
                Fill="Blue">
                <Rectangle.Triggers>
                    <!-- Animates the rectangle's opacity. -->
                    <EventTrigger RoutedEvent="Rectangle.Loaded">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                                    Storyboard.TargetName="MyRectangle" 
                                    Storyboard.TargetProperty="Opacity"
                                    From="1.0" To="0.0" Duration="0:0:5" 
                                    AutoReverse="True" RepeatBehavior="Forever" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Rectangle.Triggers>
            </Rectangle>
        </StackPanel>
    </Grid>
</Window>

The following shows how to create a rectangle that fades in and out of view in code.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        private Storyboard myStoryboard;

        public MainWindow()
        {
            InitializeComponent();

            StackPanel myPanel = new StackPanel();
            myPanel.Margin = new Thickness(10);

            Rectangle myRectangle = new Rectangle();
            myRectangle.Name = "myRectangle";
            this.RegisterName(myRectangle.Name, myRectangle);
            myRectangle.Width = 100;
            myRectangle.Height = 100;
            myRectangle.Fill = Brushes.Blue;

            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 1.0;
            myDoubleAnimation.To = 0.0;
            myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
            myDoubleAnimation.AutoReverse = true;
            myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

            myStoryboard = new Storyboard();
            myStoryboard.Children.Add(myDoubleAnimation);
            Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
            Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.OpacityProperty));

            // Use the Loaded event to start the Storyboard.
            myRectangle.Loaded += new RoutedEventHandler(myRectangleLoaded);
            myPanel.Children.Add(myRectangle);
            this.Content = myPanel;
        }

        private void myRectangleLoaded(object sender, RoutedEventArgs e)
        {
            myStoryboard.Begin(this);
        }
    }
}

Animation Types

Because animations generate property values, different animation types exist for different property types. To animate a property that takes a Double, such as the Width property of an element, use an animation that produces Double values. To animate a property that takes a Point, use an animation that produces Point values, and so on. Because of the number of different property types, there are several animation classes in theSystem.Windows.Media.Animation namespace. Fortunately, they follow a strict naming convention that makes it easy to differentiate between them:

  • Type>Animation

    Known as a "From/To/By" or "basic" animation, these animate between a starting and destination value, or by adding an offset value to its starting value.

    • To specify a starting value, set the From property of the animation.

    • To specify an ending value, set the To property of the animation.

    • To specify an offset value, set the By property of the animation.

    The examples in this overview use these animations, because they are the simplest to use. From/To/By animations are described in detail in the From/To/By Animations Overview.

  • Type>AnimationUsingKeyFrames

    Key frame animations are more powerful than From/To/By animations because you can specify any number of target values and even control their interpolation method. Some types can only be animated with key frame animations. Key frame animations are described in detail in theKey-Frame Animations Overview.

  • Type>AnimationUsingPath

    Path animations enable you to use a geometric path in order to produce animated values.

  • Type>AnimationBase

    Abstract class that, when you implement it, animates a < Type> value. This class serves as the base class for < Type>Animation and <Type>AnimationUsingKeyFrames classes. You have to deal directly with these classes only if you want to create your own custom animations. Otherwise, use a < Type>Animation or KeyFrame< Type>Animation.

In most cases, you will want to use the < Type>Animation classes, such as DoubleAnimation and ColorAnimation.

The following table shows several common animation types and some properties with which they are used.

Property type

Corresponding basic (From/To/By) animation

Corresponding key frame animation

Corresponding Path Animation

Usage example

Color

ColorAnimation

ColorAnimationUsingKeyFrames

None

Animate the Color of a SolidColorBrushor a GradientStop.

Double

DoubleAnimation

DoubleAnimationUsingKeyFrames

DoubleAnimationUsingPath

Animate the Width of a DockPanel or the Height of a Button.

Point

PointAnimation

PointAnimationUsingKeyFrames

PointAnimationUsingPath

Animate the Center position of anEllipseGeometry.

String

None

StringAnimationUsingKeyFrames

None

Animate the Text of a TextBlock or theContent of a Button.

Animations Are Timelines

All the animation types inherit from the Timeline class; therefore, all animations are specialized types of timelines. A Timeline defines a segment of time. You can specify the timing behaviors of a timeline: its Duration, how many times it is repeated, and even how fast time progresses for it.

Because an animation is a Timeline, it also represents a segment of time. An animation also calculates output values as it progresses though its specified segment of time (or Duration). As the animation progresses, or "plays," it updates the property that it is associated with.

Three frequently used timing properties are DurationAutoReverse, and RepeatBehavior.

The Duration Property

As previously mentioned, a timeline represents a segment of time. The length of that segment is determined by the Duration of the timeline, which is usually specified by using a TimeSpan value. When a timeline reaches the end of its duration, it has completed an iteration.

An animation uses its Duration property to determine its current value. If you do not specify a Duration value for an animation, it uses 1 second, which is the default.

The following syntax shows a simplified version of the Extensible Application Markup Language (XAML) attribute syntax for the Durationproperty.

hours:minutes:seconds

The following table shows several Duration settings and their resulting values.

Setting

Resulting value

0:0:5.5

5.5 seconds.

0:30:5.5

30 minutes and 5.5 seconds.

1:30:5.5

1 hour, 30 minutes, and 5.5 seconds.

One way to specify a Duration in code is to use the FromSeconds method to create a TimeSpan, then declare a new Duration structure using that TimeSpan.

For more information about Duration values and the complete Extensible Application Markup Language (XAML) syntax, see the Durationstructure.

AutoReverse

The AutoReverse property specifies whether a timeline plays backward after it reaches the end of its Duration. If you set this animation property to true, an animation reverses after it reaches the end of its Duration, playing from its ending value back to its starting value. By default, this property is false.

RepeatBehavior

The RepeatBehavior property specifies how many times a timeline plays. By default, timelines have an iteration count of 1.0, which means they play one time and do not repeat at all.

For more information about these properties and others, see the Timing Behaviors Overview.

Applying an Animation to a Property

The previous sections describe the different types of animations and their timing properties. This section shows how to apply the animation to the property that you want to animate. Storyboard objects provide one way to apply animations to properties. A Storyboard is a container timeline that provides targeting information for the animations it contains.

Targeting Objects and Properties

The Storyboard class provides the TargetName and TargetPropertyattached properties. By setting these properties on an animation, you tell the animation what to animate. However, before an animation can target an object, the object must usually be given a name.

Assigning a name to a FrameworkElement differs from assigning a name to a Freezable object. Most controls and panels are framework elements; however, most purely graphical objects, such as brushes, transforms, and geometries, are freezable objects. If you are not sure whether a type is aFrameworkElement or a Freezable, refer to the Inheritance Hierarchy section of its reference documentation.

  • To make a FrameworkElement an animation target, you give it a name by setting its Name property. In code, you must also use theRegisterName method to register the element name with the page to which it belongs.

  • To make a Freezable object an animation target in XAML, you use the x:Name Directive to assign it a name. In code, you just use theRegisterName method to register the object with the page to which it belongs.

The sections that follow provide an example of naming an element in XAML and code. For more detailed information about naming and targeting, see the  Storyboards Overview.

Applying and Starting Storyboards

To start a storyboard in XAML, you associate it with an EventTrigger. An EventTrigger is an object that describes what actions to take when a specified event occurs. One of those actions can be a BeginStoryboard action, which you use to start your storyboard. Event triggers are similar in concept to event handlers because they enable you to specify how your application responds to a particular event. Unlike event handlers, event triggers can be fully described in XAML; no other code is required.

To start a Storyboard in code, you can use an EventTrigger or use the Begin method of the Storyboard class.

Interactively Control a Storyboard

The previous example showed how to start a Storyboard when an event occurs. You can also interactively control a Storyboard after it starts: you can pause, resume, stop, advance it to its fill period, seek, and remove the Storyboard. For more information and an example that shows how to interactively control a Storyboard, see the Storyboards Overview.

What Happens After an Animation Ends?

The FillBehavior property specifies how a timeline behaves when it ends. By default, a timeline starts Filling when it ends. An animation that is Fillingholds its final output value.

The DoubleAnimation in the previous example does not end because its RepeatBehavior property is set to Forever. The following example animates a rectangle by using a similar animation. Unlike the previous example, the RepeatBehavior and AutoReverse properties of this animation are left at their default values. Therefore, the animation progresses from 1 to 0 over five seconds and then stops.

<Rectangle
  Name="MyRectangle"
  Width="100" 
  Height="100"
  Fill="Blue">
  <Rectangle.Triggers>

    <!-- Animates the rectangle's opacity. -->
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimation
            Storyboard.TargetName="MyRectangle" 
            Storyboard.TargetProperty="Opacity"
            From="1.0" To="0" Duration="0:0:5" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 1.0;
myDoubleAnimation.To = 0.0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));

Because its FillBehavior was not changed from its default value, which is HoldEnd, the animation holds it final value, 0, when it ends. Therefore, theOpacity of the rectangle remains at 0 after the animation ends. If you set the Opacity of the rectangle to another value, your code appears to have no effect, because the animation is still affecting the Opacity property.

One way to regain control of an animated property in code is to use the BeginAnimation method and specify null for the AnimationTimelineparameter. For more information and an example, see How to: Set a Property After Animating It with a Storyboard.

Note that, although setting a property value that has an Active or Filling animation appears to have no effect, the property value does change. For more information, see the Animation and Timing System Overview.

Data Binding and Animating Animations

Most animation properties can be data bound or animated; for example, you can animate the Duration property of a DoubleAnimation. However, because of the way the timing system works, data bound or animated animations do not behave like other data bound or animated objects. To understand their behavior, it helps to understand what it means to apply an animation to a property.

Refer to the example in the previous section that showed how to animate the Opacity of a rectangle. When the rectangle in the previous example is loaded, its event trigger applies the Storyboard. The timing system creates a copy of the Storyboard and its animation. These copies are frozen (made read-only) and Clock objects are created from them. These clocks do the actual work of animating the targeted properties.

The timing system creates a clock for the DoubleAnimation and applies it to the object and property that is specified by the TargetName andTargetProperty of the DoubleAnimation. In this case, the timing system applies the clock to the Opacity property of the object that is named "MyRectangle."

Although a clock is also created for the Storyboard, the clock is not applied to any properties. Its purpose is to control its child clock, the clock that is created for the DoubleAnimation.

For an animation to reflect data binding or animation changes, its clock must be regenerated. Clocks are not regenerated for you automatically. To make an animation reflect changes, reapply its storyboard by using a BeginStoryboard or the Begin method. When you use either of these methods, the animation restarts. In code, you can use the Seek method to shift the storyboard back to its previous position.

For an example of a data bound animation, see Key Spline Animation Sample. For more information about how the animation and timing system works, see Animation and Timing System Overview.

Other Ways to Animate

The examples in this overview show how to animate by using storyboards. When you use code, you can animate in several other ways. For more information, see the Property Animation Techniques Overview.

Animation Samples

The following samples can help you start adding animation to your applications.

Related Topics

Title

Description

Animation and Timing System Overview

Describes how the timing system uses the Timeline and Clock classes, which allow you to create animations.

Animation Tips and Tricks

Lists helpful tips for solving issues with animations, such as performance.

Custom Animations Overview

Describes how to extend the animation system with key frames, animation classes, or per-frame callbacks.

From/To/By Animations Overview

Describes how to create an animation that transitions between two values.

Key-Frame Animations Overview

Describes how to create an animation with multiple target values, including the ability to control the interpolation method.

Easing Functions

Explains how to apply mathematical formulas to your animations to get realistic behavior, such as bouncing.

Path Animations Overview

Describes how to move or rotate an object along a complex path.

Property Animation Techniques Overview

Describes property animations using storyboards, local animations, clocks, and per-frame animations.

Storyboards Overview

Describes how to use storyboards with multiple timelines to create complex animations.

Timing Behaviors Overview

Describes the Timeline types and properties used in animations.

Timing Events Overview

Describes the events available on the Timeline and Clock objects for executing code at points in the timeline, such as begin, pause, resume, skip, or stop.

Animation and Timing How-to Topics

Contains code examples for using animations and timelines in your application.

Clocks How-to Topics

Contains code examples for using the Clock object in your application.

Key-Frame Animation How-to Topics

Contains code examples for using key-frame animations in your application.

Path Animation How-to Topics

Contains code examples for using path animations in your application.





Animation and Timing System Overview


This topic describes how the timing system uses the animation, Timeline, and Clock classes to animate properties.

Prerequisites

To understand this topic, you should be able to use WPF animations to animate properties, as described in the Animation Overview. It also helps to be familiar with dependency properties; for more information, see the Dependency Properties Overview.

Timelines and Clocks

The Animation Overview described how a Timeline represents a segment of time, and an animation is a type of Timeline that produces output values. By itself, a Timeline, doesn't do anything other than just describe a segment of time. It's the timeline's Clock object that does the real work. Likewise, animation doesn't actually animate properties: an animation class describes how output values should be calculated, but it’s the Clock that was created for the animation that drives the animation output and applies it to properties.

Clock is a special type of object that maintains timing-related run-time state for the Timeline. It provides three bits of information that are essential to the animation and timing system: CurrentTimeCurrentProgress, and CurrentState. A Clock determines its current time, progress, and state by using the timing behaviors described by its TimelineDurationRepeatBehaviorAutoReverse, and so on.

In most cases, a Clock is created automatically for your timeline. When you animate by using a Storyboard or the BeginAnimation method, clocks are automatically created for your timelines and animations and applied to their targeted properties. You can also create a Clock explicitly by using the CreateClock method of your Timeline. The MediaTimeline.CreateClock method creates a clock of the appropriate type for the Timeline on which it is called. If the Timeline contains child timelines, it creates Clock objects for them as well. The resulting Clock objects are arranged in trees that match the structure of the Timeline objects tree from which they are created.

There are different types of clocks for different types of timelines. The following table shows the Clock types that correspond to some of the different Timeline types.

Timeline type

Clock type

Clock purpose

Animation (inherits from AnimationTimeline)

AnimationClock

Generates output values for a dependency property.

MediaTimeline

MediaClock

Processes a media file.

ParallelTimeline

ClockGroup

Groups and controls its child Clock objects

Storyboard

ClockGroup

Groups and controls its child Clock objects

You can apply any AnimationClock objects you create to compatible dependency properties by using the ApplyAnimationClock method.

In performance-intensive scenarios, such as animating large numbers of similar objects, managing your own Clock use can provide performance benefits.

Clocks and the Time Manager

When you animate objects in WPF, it’s the time manager that manages the Clock objects created for your timelines. The time manager is the root of a tree of Clock objects and controls the flow of time in that tree. A time manager is automatically created for each WPF application and is invisible to the application developer. The time manager "ticks" many times per second; the actual number of ticks that occur each second varies depending on available system resources. During each one of these ticks, the time manager computes the state of all Active Clock objects in the timing tree.  

The following illustration shows the relationship between the time manager, and AnimationClock, and an animated dependency property.

Timing system components

Animating a property

When the time manager ticks, it updates the time of every Active Clock in the application. If the Clock is an AnimationClock, it uses the GetCurrentValue method of the AnimationTimeline from which it was created to calculate its current output value. The AnimationClock supplies the AnimationTimeline with the current local time, an input value, which is typically the base value of the property, and a default destination value. When you retrieve the value of an animated by property using the GetValue method or its CLR accessor, you get the output of its AnimationClock.

Clock Groups

The preceding section described how there are different types of Clock objects for different types of timelines. The following illustration shows the relationship between the time manager, a ClockGroup, an AnimationClock, and an animated dependency property. A ClockGroup is created for timelines that group other timelines, such as the Storyboard class, which groups animations and other timelines.

Timing system components

A ClockGroup

Composition

It's possible to associate multiple clocks with a single property, in which case each clock uses the output value of the preceding clock as its base value. The following illustration shows three AnimationClock objects applied to the same property. Clock1 uses the base value of the animated property as its input and uses it to generate output. Clock2 takes the output from Clock1 as its input and uses it to generate output. Clock3 takes the output from Clock2 as its input and uses it to generate output. When multiple clocks affect the same property simultaneously, they are said to be in a composition chain.

Timing system components

A composition chain

Note that although a relationship is created among the input and output of the AnimationClock objects in the composition chain, their timing behaviors are not affected; Clock objects (including AnimationClock objects) have a hierarchical dependency on their parent Clock objects.

To apply multiple clocks to the same property, use the Compose HandoffBehavior when applying a Storyboard, animation, or AnimationClock.

Ticks and Event Consolidation

In addition to calculating output values, the time manager does other work every time it ticks: it determines the state of each clock and raises events as appropriate.

While ticks occur frequently, it's possible for a lot of things to happen between ticks. For example, a Clock might be stopped, started, and stopped again, in which case its CurrentState value will have changed three times. In theory, the CurrentStateInvalidated event could be raised multiple times in a single tick; however, the timing engine consolidates events, so that the CurrentStateInvalidated event can be raised at most once per tick. This is true for all timing events: at most one event of each type is raised for a given Clock object.

When a Clock switches states and returns back to its original state between ticks (such as changing from Active to Stopped and back to Active), the associated event still occurs.

For more information about timing events, see the Timing Events Overview.

Current Values and Base Values of Properties

An animatable property can have two values: a base value and a current value. When you set property using its CLR accessor or the SetValue method, you set its base value. When a property is not animated, its base and current values are the same.

When you animate a property, the AnimationClock sets the property's current value. Retrieving the property's value through its CLR accessor or the GetValue method returns the output of the AnimationClock when the AnimationClock is Active or Filling. You can retrieve the property's base value by using the GetAnimationBaseValue method.





Animation Tips and Tricks


When working with animations in WPF, there are a number of tips and tricks that can make your animations perform better and save you frustration.

General Issues

Animating the Position of a Scroll Bar or Slider Freezes It

If you animate the position of a scroll bar or slider using an animation that has a FillBehavior of HoldEnd (the default value), the user will no longer be able to move the scroll bar or slider. That's because, even though the animation ended, it's still overriding the target property's base value. To stop the animation from overriding the property's current value, remove it, or give it a FillBehavior of Stop. For more information and an example, see How to: Set a Property After Animating It with a Storyboard.

Animating the Output of an Animation Has No Effect

You can't animate an object that is the output of another animation. For example, if you use an ObjectAnimationUsingKeyFrames to animate theFill of a Rectangle from a RadialGradientBrush to a SolidColorBrush, you can't animate any properties of the RadialGradientBrush orSolidColorBrush.

Can't Change the Value of a Property after Animating it

In some cases, it might appear that you can't change the value of a property after it's been animated, even after the animation has ended. That's because, even though the animation ended, it's still overriding the property's base value. To stop the animation from overriding the property's current value, remove it, or give it a FillBehavior of Stop. For more information and an example, see How to: Set a Property After Animating It with a Storyboard.

Changing a Timeline Has No Effect

Although most Timeline properties are animatable and can be data bound, changing the property values of an active Timeline seems to have no effect. That's because, when a Timeline is begun, the timing system makes a copy of the Timeline and uses it to create a Clock object. Modifying the original has no effect on the system's copy.

For a Timeline to reflect changes, its clock must be regenerated and used to replace the previously created clock. Clocks are not regenerated for you automatically. The following are several ways to apply timeline changes:

  • If the timeline is or belongs to a Storyboard, you can make it reflect changes by reapplying its storyboard using a BeginStoryboard or theBegin method. This has the side effect of also restarting the animation. In code, you can use the Seek method to advance the storyboard back to its previous position.

  • If you applied an animation directly to a property using the BeginAnimation method, call the BeginAnimation method again and pass it the animation that has been modified.

  • If you are working directly at the clock level, create and apply a new set of clocks and use them to replace the previous set of generated clocks.

For more information about timelines and clocks, see Animation and Timing System Overview.

FillBehavior.Stop Doesn't Work as Expected

There are times when setting the FillBehavior property to Stop seems to have no effect, such as when one animation "hands off" to another because it has a HandoffBehavior setting of SnapshotAndReplace.

The following example creates a Canvas, a Rectangle and a TranslateTransform. The TranslateTransform will be animated to move the Rectanglearound the Canvas.

<Canvas Width="600" Height="200">
  <Rectangle 
    Canvas.Top="50" Canvas.Left="0" 
    Width="50" Height="50" Fill="Red">
    <Rectangle.RenderTransform>
      <TranslateTransform 
        x:Name="MyTranslateTransform" 
        X="0" Y="0" />
    </Rectangle.RenderTransform>
  </Rectangle>
</Canvas>

The examples in this section use the preceding objects to demonstrate several cases where the FillBehavior property doesn't behave as you might expect it to.

FillBehavior="Stop" and HandoffBehavior with Multiple Animations

Sometimes it seems as though an animation ignores its FillBehavior property when it is replaced by a second animation. Take the following example, which creates two Storyboard objects and uses them to animate the same TranslateTransform shown in the preceding example.

The first StoryboardB1, animates the X property of the TranslateTransform from 0 to 350, which moves the rectangle 350 pixels to the right. When the animation reaches the end of its duration and stops playing, the X property reverts to its original value, 0. As a result, the rectangle moves to the right 350 pixels and then jumps back to its original position.

<Button Content="Start Storyboard B1">
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
      <BeginStoryboard>
        <Storyboard x:Name="B1">
          <DoubleAnimation 
            Storyboard.TargetName="MyTranslateTransform"
            Storyboard.TargetProperty="X"
            From="0" To="350" Duration="0:0:5"
            FillBehavior="Stop"
            />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

The second StoryboardB2, also animates the X property of the same TranslateTransform. Because only the To property of the animation in thisStoryboard is set, the animation uses the current value of the property it animates as its starting value.

<!-- Animates the same object and property as the preceding
     Storyboard. -->
<Button Content="Start Storyboard B2">
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
      <BeginStoryboard>
        <Storyboard x:Name="B2">
          <DoubleAnimation 
            Storyboard.TargetName="MyTranslateTransform"
            Storyboard.TargetProperty="X"
            To="500" Duration="0:0:5" 
            FillBehavior="Stop" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

If you click the second button while the first Storyboard is playing, you might expect the following behavior:

  1. The first storyboard ends and sends the rectangle back to its original position, because the animation has a FillBehavior of Stop.

  2. The second storyboard takes effect and animates from the current position, which is now 0, to 500.

But that's not what happens. Instead, the rectangle does not jump back; it continues moving to the right. That's because the second animation uses the current value of the first animation as its starting value and animates from that value to 500. When the second animation replaces the first because the SnapshotAndReplaceHandoffBehavior is used, the FillBehavior of the first animation does not matter.

FillBehavior and the Completed Event

The next examples demonstrate another scenario in which the StopFillBehavior seems to have no effect. Again, the example uses a Storyboard to animate the X property of the TranslateTransform from 0 to 350. However, this time the example registers for the Completed event.

<Button Content="Start Storyboard C">
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
      <BeginStoryboard>
        <Storyboard Completed="StoryboardC_Completed">
          <DoubleAnimation 
            Storyboard.TargetName="MyTranslateTransform"
            Storyboard.TargetProperty="X"
            From="0" To="350" Duration="0:0:5"
            FillBehavior="Stop" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

The Completed event handler starts another Storyboard that animates the same property from its current value to 500.

private void StoryboardC_Completed(object sender, EventArgs e)
{

    Storyboard translationAnimationStoryboard =
        (Storyboard)this.Resources["TranslationAnimationStoryboardResource"];
    translationAnimationStoryboard.Begin(this);
}

The following is the markup that defines the second Storyboard as a resource.

<Page.Resources>
  <Storyboard x:Key="TranslationAnimationStoryboardResource">
    <DoubleAnimation 
      Storyboard.TargetName="MyTranslateTransform"
      Storyboard.TargetProperty="X"
      To="500" Duration="0:0:5" />
  </Storyboard>
</Page.Resources>

When you run the Storyboard, you might expect the X property of the TranslateTransform to animate from 0 to 350, then revert to 0 after it completes (because it has a FillBehavior setting of Stop), and then animate from 0 to 500. Instead, the TranslateTransform animates from 0 to 350 and then to 500.

That's because of the order in which WPF raises events and because property values are cached and are not recalculated unless the property is invalidated. The Completed event is processed first because it was triggered by the root timeline (the first Storyboard). At this time, the Xproperty still returns its animated value because it hasn't been invalidated yet. The second Storyboard uses the cached value as its starting value and begins animating.

Performance

Animations Continue to Run After Navigating Away from a Page

When you navigate away from a Page that contains running animations, those animations will continue to play until the Page is garbage collected. Depending on the navigation system you're using, a page that you navigate away from might stay in memory for an indefinite amount of time, all the while consuming resources with its animations. This is most noticeable when a page contains constantly running ("ambient") animations.

For this reason, it's a good idea to use the Unloaded event to remove animations when you navigate away from a page.

There are different ways to remove an animation. The following techniques can be used to remove animations that belong to a Storyboard.

The next technique may be used regardless of how the animation was started.

For more information about the different ways to animate properties, see Property Animation Techniques Overview.

Using the Compose HandoffBehavior Consumes System Resources

When you apply a StoryboardAnimationTimeline, or AnimationClock to a property using the ComposeHandoffBehavior, any Clock objects previously associated with that property continue to consume system resources; the timing system will not remove these clocks automatically.

To avoid performance issues when you apply a large number of clocks using Compose, you should remove composing clocks from the animated property after they complete. There are several ways to remove a clock.

This is primarily an issue for animations on objects that have a long lifetime. When an object is garbage collected, its clocks will also be disconnected and garbage collected.

For more information about clock objects, see Animation and Timing System Overview.





Custom Animations Overview


This topic describes how and when to extend the WPF animation system by creating custom key frames, animation classes, or by using per-frame callback to bypass it.  

Prerequisites

To understand this topic, you should be familiar with the different types of animations provided by the WPF. For more information, see the From/To/By Animations Overview, the Key-Frame Animations Overview, and the Path Animations Overview.

Because the animation classes inherit from the Freezable class, you should be familiar with Freezable objects and how to inherit from Freezable. For more information, see the Freezable Objects Overview.

Extending the Animation System

There are a number of ways to extend the WPF animation system, depending on the level of built-in functionality you want to use. There are three primary extensibility points in the WPF animation engine:

  • Create a custom key frame object by inheriting from one of the <Type>KeyFrame classes, such as DoubleKeyFrame. This approach uses most of the built-in functionality of the WPF animation engine.

  • Create your own animation class by inheriting from AnimationTimeline or one of the <Type>AnimationBase classes.

  • Use per-frame callback to generate animations on a per-frame basis. This approach completely bypasses the animation and timing system.

The following table describes some the scenarios for extending the animation system.

When you want to...

Use this approach

Customize the interpolation between values of a type that has a corresponding <Type>AnimationUsingKeyFrames

Create a custom key frame. For more information, see the Create a Custom Key Frame section.

Customize more than just the interpolation between values of a type that has a corresponding <Type>Animation.

Create a custom animation class that inherits from the <Type>AnimationBase class that corresponds to the type you want to animate. For more information, see the Create a Custom Animation Class section.

Animate a type that has no corresponding WPF animation

Use an ObjectAnimationUsingKeyFrames or create a class that inherits from AnimationTimeline. For more information, see the Create a Custom Animation Class section.

Animate multiple objects with values that are computed each frame and are based on the last set of object interactions

Use per-frame callback. For more information, see the Create a Use Per-Frame Callback section.

Create a Custom Key Frame

Creating a custom key frame class is the simplest way to extend the animation system. Use this approach when you want to a different interpolation method for a key-frame animation. As described in the Key-Frame Animations Overview, a key-frame animation uses key frame objects to generate its output values. Each key frame object performs three functions:

  • Specifies a target value using its Value property.

  • Specifies the time at which that value should be reached using its KeyTime property.

  • Interpolates between the value of the previous key frame and its own value by implementing the InterpolateValueCore method.

 

Implementation Instructions

Derive from the <Type>KeyFrame abstract class and implement the InterpolateValueCore method. The InterpolateValueCore method returns the current value of the key frame. It takes two parameters: the value of the previous key frame and a progress value that ranges from 0 to 1. A progress of 0 indicates the key frame has just started, and a value of 1 indicates that the key frame has just completed and should return the value specified by its Value property.

Because the <Type>KeyFrame classes inherit from the Freezable class, you must also override CreateInstanceCore core to return a new instance of your class. If the class does not use dependency properties to store its data or it requires extra initialization after creation, you might need to override additional methods; see the Freezable Objects Overview for more information.

After you've created your custom <Type>KeyFrame animation, you can use it with the <Type>AnimationUsingKeyFrames for that type.

Create a Custom Animation Class

Creating your own animation type gives you more control over how an object in animated. There are two recommended ways to create your own animation type: you can derive from the AnimationTimeline class or the <Type>AnimationBase class. Deriving from the <Type>Animation or <Type>AnimationUsingKeyFrames classes is not recommended.

Derive from <Type>AnimationBase

Deriving from a <Type>AnimationBase class is the simplest way to create a new animation type. Use this approach when you want to create a new animation for type that already has a corresponding <Type>AnimationBase class.

Implementation Instructions

Derive from a <Type>Animation class and implement the GetCurrentValueCore method. The GetCurrentValueCore method returns the current value of the animation. It takes three parameters: a suggested starting value, a suggested ending value, and an AnimationClock, which you use to determine the progress of the animation.

Because the <Type>AnimationBase classes inherit from the Freezable class, you must also override CreateInstanceCore core to return a new instance of your class. If the class does not use dependency properties to store its data or it requires extra initialization after creation, you might need to override additional methods; see the Freezable Objects Overview for more information.

For more information, see the GetCurrentValueCore method documentation for the <Type>AnimationBase class for the type that you want to animate. For an example, see the Custom Animation Sample

Alternative Approaches

If you simply want to change how animation values are interpolated, considering deriving from one of the <Type>KeyFrame classes. The key frame you create can be used with the corresponding <Type>AnimationUsingKeyFrames provided by WPF. 

Derive from AnimationTimeline

Derive from the AnimationTimeline class when you want to create an animation for a type that doesn't already have a matching WPF animation, or you want to create an animation that is not strongly typed.

Implementation Instructions

Derive from the AnimationTimeline class and override the following members:

  • CreateInstanceCore – If your new class is concrete, you must override CreateInstanceCore to return a new instance of your class.

  • GetCurrentValue – Override this method to return the current value of your animation. It takes three parameters: a default origin value, a default destination value, and an AnimationClock. Use the AnimationClock to obtain the current time or progress for the animation. You can choose whether to use the default origin and destination values.

  • IsDestinationDefault – Override this property to indicate whether your animation uses the default destination value specified by the GetCurrentValue method.

  • TargetPropertyType – Override this property to indicate the Type of output your animation produces.

If the class does not use dependency properties to store its data or it requires extra initialization after creation, you might need to override additional methods; see the Freezable Objects Overview for more information.

The recommended paradigm (used by WPF animations) is to use two inheritance levels:

  1. Create an abstract <Type>AnimationBase class that derives from AnimationTimeline. This class should override the TargetPropertyType method. It should also introduce a new abstract method, GetCurrentValueCore, and override GetCurrentValue so that it validates the types of the default origin value and default destination value parameters, then calls GetCurrentValueCore.

  2. Create another class that inherits from your new <Type>AnimationBase class and overrides the CreateInstanceCore method, the GetCurrentValueCore method that you introduced, and the IsDestinationDefault property.

Alternative Approaches

If you want to animate a type that has no corresponding From/To/By animation or key-frame animation, consider using an ObjectAnimationUsingKeyFrames. Because it is weakly typed, an ObjectAnimationUsingKeyFrames can animate any type of value. The drawback to this approach is that ObjectAnimationUsingKeyFrames only supports discrete interpolation.

Use Per-Frame Callback

Use this approach when you need to completely bypass the WPF animation system. One scenario for this approach is physics animations, where at each animation step a new direction or position of animated objects needs to be recomputed based on the last set of object interactions.

Implementation Instructions

Unlike the other approaches described in this overview, to use per-frame callback you don't need to create a custom animation or key frame class.

Instead, you register for the Rendering event of the object that contains the objects you want to animate. This event handler method gets called once per frame. Each time that WPF marshals the persisted rendering data in the visual tree across to the composition tree, your event handler method is called.

In your event handler, perform your whatever calculations necessary for your animation effect and set the properties of the objects you want to animate with these values.

To obtain the presentation time of the current frame, the EventArgs associated with this event can be cast as RenderingEventArgs, which provide a RenderingTime property that you can use to obtain the current frame's rendering time.

For more information, see the Rendering page.





From/To/By Animations Overview


This topic describes how to use From/To/By animations to animate dependency properties. A From/To/By animation creates a transition between two values.

This topic contains the following sections.

Prerequisites

To understand this topic, you should be familiar with WPF animations features. For an introduction to animation features, see the Animation Overview.

What Is a From/To/By Animation?

A From/To/By animation is a type of AnimationTimeline that creates a transition between a starting value and an ending value. The amount of time that the transition takes to complete is determined by the Duration of that animation.

You can apply a From/To/By animation to a property by using a Storyboard in markup and code, or by using the BeginAnimation method in code. You may also use a From/To/By Animation to create an AnimationClock and apply it to one or more properties. For more information about the different methods for applying animations, see the Property Animation Techniques Overview.

From/To/By animations can have no more than two target values. If you require an animation that has more than two target values, use a key-frame animation. Key-frame animations are described in the Key-Frame Animations Overview.

From/To/By Animation Types

Because animations generate property values, there are different animation types for different property types. To animate a property that takes aDouble, such as the Width property of an element, use an animation that produces Double values. To animate a property that takes a Point, use an animation that produces Point values, and so on.

From/To/By animation classes belong to the System.Windows.Media.Animation namespace and use the following naming convention:

<Type>Animation

Where <Type> is the type of value that the class animates.

WPF provides the following From/To/By animation classes.

Target Values

A From/To/By animation creates a transition between two target values. It is common to specify a starting value (set it by using the From property) and an ending value (set it by using the To property). However, you can also specify only a starting value, a destination value, or an offset value. In these cases, the animation obtains the missing target value from the property that is being animated. The following list describes the different ways to specify the target values of an animation.

  • Starting Value

    Use the From property when you want to explicitly specify the starting value of an animation. You can use the From property by itself, or with the To or By property. If you specify only the From property, the animation transitions from that value to the base value of the animated property.

  • Ending Value

    To specify an ending value of an animation, use its To property. If you use the To property by itself, the animation obtains its starting value from the property that is being animated or from the output of another animation that is applied to the same property. You can use the Toproperty together with the From property to explicitly specify starting and ending values for the animation.

  • Offset Value

    The By property enables you to specify an offset instead of an explicit starting or ending value for the animation. The By property of an animation specifies by how much the animation changes a value over its duration. You can use the By property by itself or with the Fromproperty. If you specify only the By property, the animation adds the offset value to the base value of the property or to the output of another animation.

Using From/To/By Values

The following sections describe how to use the FromTo, and By properties together or separately.

The examples in this section each use a DoubleAnimation, which is a type of From/To/By animation, to animate the Width property of a Rectangle that is 10 device independent pixels high and 100 device independent pixels wide.

Although each example uses a DoubleAnimation, the From, To, and By properties of all From/To/By animations behave identically. Although each of these examples uses a Storyboard, you can use From/To/By animations in other ways. For more information, see Property Animation Techniques Overview.

From/To

When you set the From and To values together, the animation progresses from the value that is specified by the From property, to the value that is specified by the To property.

The following example sets the From property of the DoubleAnimation to 50 and its To property to 300. As a result, the Width of the Rectangle is animated from 50 to 300.

// Demonstrates the From and To properties used together.

// Create a NameScope for this page so that
// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

Rectangle myRectangle = new Rectangle();

// Assign the Rectangle a name so that
// it can be targeted by a Storyboard.
this.RegisterName(
    "fromToAnimatedRectangle", myRectangle);
myRectangle.Height = 10;
myRectangle.Width = 100;
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myRectangle.Fill = Brushes.Black;

// Demonstrates the From and To properties used together.
// Animates the rectangle's Width property from 50 to 300 over 10 seconds.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 50;
myDoubleAnimation.To = 300;
myDoubleAnimation.Duration =
    new Duration(TimeSpan.FromSeconds(10));

Storyboard.SetTargetName(myDoubleAnimation, "fromToAnimatedRectangle");
Storyboard.SetTargetProperty(myDoubleAnimation,
    new PropertyPath(Rectangle.WidthProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);

// Use an anonymous event handler to begin the animation
// when the rectangle is clicked.
myRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs args)
    {
        myStoryboard.Begin(myRectangle);

    };

To

When you set just the To property, the animation progresses from the base value of the animated property, or from the output of a composing animation that was previously applied to the same property, to the value that is specified by the To property.

("Composing animation" refers to an Active or Filling animation that previously applied to the same property that is still in effect when the current animation was applied by using the Compose handoff behavior.)

The following example sets just the To property of the DoubleAnimation to 300. Because no starting value was specified, the DoubleAnimationuses the base value (100) of the Width property as its starting value. The Width of the Rectangle is animated from 100 to the animation's target value of 300.

// Demonstrates the use of the To property.

// Create a NameScope for this page so that
// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

Rectangle myRectangle = new Rectangle();

// Assign the Rectangle a name so that
// it can be targeted by a Storyboard.
this.RegisterName(
    "toAnimatedRectangle", myRectangle);
myRectangle.Height = 10;
myRectangle.Width = 100;
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myRectangle.Fill = Brushes.Gray;

// Demonstrates the To property used by itself. Animates
// the Rectangle's Width property from its base value
// (100) to 300 over 10 seconds.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.To = 300;
myDoubleAnimation.Duration =
    new Duration(TimeSpan.FromSeconds(10));

Storyboard.SetTargetName(myDoubleAnimation, "toAnimatedRectangle");
Storyboard.SetTargetProperty(myDoubleAnimation,
    new PropertyPath(Rectangle.WidthProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);

// Use an anonymous event handler to begin the animation
// when the rectangle is clicked.
myRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs args)
    {
        myStoryboard.Begin(myRectangle);

    };

By

When you set just the By property of an animation, the animation progresses from the base value of the property that is being animated, or from the output of a composing animation to the sum of that value and the value that is specified by the By property.

The following example sets just the By property of the DoubleAnimation to 300. Because the example does not specify a starting value, theDoubleAnimation uses the base value of the Width property, 100, as its starting value. The ending value is determined by adding the By value of the animation, 300, to its starting value, 100: 400. As a result, the Width of the Rectangle is animated from 100 to 400.

// Demonstrates the use of the By property.

// Create a NameScope for this page so that
// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

Rectangle myRectangle = new Rectangle();

// Assign the Rectangle a name so that
// it can be targeted by a Storyboard.
this.RegisterName(
    "byAnimatedRectangle", myRectangle);
myRectangle.Height = 10;
myRectangle.Width = 100;
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myRectangle.Fill = Brushes.RoyalBlue;

// Demonstrates the By property used by itself.
// Increments the Rectangle's Width property by 300 over 10 seconds.
// As a result, the Width property is animated from its base value
// (100) to 400 (100 + 300) over 10 seconds.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.By = 300;
myDoubleAnimation.Duration =
    new Duration(TimeSpan.FromSeconds(10));

Storyboard.SetTargetName(myDoubleAnimation, "byAnimatedRectangle");
Storyboard.SetTargetProperty(myDoubleAnimation,
    new PropertyPath(Rectangle.WidthProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);

// Use an anonymous event handler to begin the animation
// when the rectangle is clicked.
myRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs args)
    {
        myStoryboard.Begin(myRectangle);

    };

From/By

When you set the From and By properties of an animation, the animation progresses from the value that is specified by the From property, to the value that is specified by the sum of the From and By properties.

The following example sets the From property of the DoubleAnimation to 50 and its By property to 300. The ending value is determined by adding the By value of the animation, 300, to its starting value, 50: 350. As a result, the Width of the Rectangle is animated from 50 to 350.

// Demonstrates the use of the From and By properties.

// Create a NameScope for this page so that
// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

Rectangle myRectangle = new Rectangle();

// Assign the Rectangle a name so that
// it can be targeted by a Storyboard.
this.RegisterName(
    "byAnimatedRectangle", myRectangle);
myRectangle.Height = 10;
myRectangle.Width = 100;
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myRectangle.Fill = Brushes.BlueViolet;

// Demonstrates the From and By properties used together.
// Increments the Rectangle's Width property by 300 over 10 seconds.
// As a result, the Width property is animated from 50
// to 350 (50 + 300) over 10 seconds.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 50;
myDoubleAnimation.By = 300;
myDoubleAnimation.Duration =
    new Duration(TimeSpan.FromSeconds(10));

Storyboard.SetTargetName(myDoubleAnimation, "byAnimatedRectangle");
Storyboard.SetTargetProperty(myDoubleAnimation,
    new PropertyPath(Rectangle.WidthProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);

// Use an anonymous event handler to begin the animation
// when the rectangle is clicked.
myRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs args)
    {
        myStoryboard.Begin(myRectangle);
    };

From

When you specify just the From value of an animation, the animation progresses from the value that is specified by the From property, to the base value of the property that is being animated or to the output of a composing animation.

The following example sets just the From property of the DoubleAnimation to 50. Because no ending value was specified, the DoubleAnimationuses the base value of the Width property, 100, as its ending value. The Width of the Rectangle is animated from 50 to the base value of the Widthproperty, 100.

// Demonstrates the use of the From property.

// Create a NameScope for this page so that
// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

Rectangle myRectangle = new Rectangle();

// Assign the Rectangle a name so that
// it can be targeted by a Storyboard.
this.RegisterName(
    "fromAnimatedRectangle", myRectangle);
myRectangle.Height = 10;
myRectangle.Width = 100;
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myRectangle.Fill = Brushes.Purple;

// Demonstrates the From property used by itself. Animates the
// rectangle's Width property from 50 to its base value (100)
// over 10 seconds.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 50;
myDoubleAnimation.Duration =
    new Duration(TimeSpan.FromSeconds(10));

Storyboard.SetTargetName(myDoubleAnimation, "fromAnimatedRectangle");
Storyboard.SetTargetProperty(myDoubleAnimation,
    new PropertyPath(Rectangle.WidthProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);

// Use an anonymous event handler to begin the animation
// when the rectangle is clicked.
myRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs args)
    {
        myStoryboard.Begin(myRectangle);
    };

To/By

If you set both the To and the By properties of an animation, the By property is ignored.

Other Animation Types

From/To/By animations are not the only type of animations that WPF provides: it also provides key-frame animations and path animations.

WPF also enables you to create your own custom animation types. For more information, see the Custom Animations Overview.






Key-Frame Animations Overview


This topic introduces you to key-frame animations. Key-frame animations enable you to animate using more than two target values, and control an animation's interpolation method.

Prerequisites

To understand this overview, you should be familiar with Windows Presentation Foundation (WPF) animations and timelines. For an introduction to animations, see the Animation Overview. It also helps to be familiar with From/To/By animations. For more information, see the From/To/By Animations Overview.

What is a Key-Frame Animation?

Like a From/To/By animation, a key-frame animation animates the value of a target property. It creates a transition among its target values over its Duration. However, while a From/To/By animation creates a transition between two values, a single key-frame animation can create transitions among any number of target values. Unlike a From/To/By animation, a key frame animation has no From, To, or By properties with which to set its target values. A key-frame animation's target values are described using key frames objects (hence the term, "key-frame animation"). To specify the animation's target values, you create key frame objects and add them to the animation's KeyFrames collection. When the animation runs, it transitions between the frames you specified.

In addition to supporting multiple target values, some key-frame methods even support multiple interpolation methods. An animation's interpolation method defines how it transitions from one value to the next. There are three types of interpolations: discretelinear, and splined.

To animate with a key-frame animation, you complete the following steps.

  • Declare the animation and specify its Duration, just like you would for a from/to/by animation.

  • For each target value, create a key frame of the appropriate type, set its value and KeyTime, and add it to the animation's KeyFrames collection.

  • Associate the animation with a property, just like you would with a From/To/By animation. For more information about applying an animation to a property using a storyboard, see Storyboards Overview.

The following example uses a DoubleAnimationUsingKeyFrames to animate a Rectangle element to four different locations.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="Microsoft.Samples.KeyFrameAnimations.KeyFramesIntroduction"
  WindowTitle="KeyFrame Animations">

  <Border Width="400" BorderBrush="Black">  

    <Rectangle Fill="Blue" 
      Width="50" Height="50"
      HorizontalAlignment="Left">
      <Rectangle.RenderTransform>
        <TranslateTransform 
          x:Name="MyAnimatedTranslateTransform" 
          X="0" Y="0" />
      </Rectangle.RenderTransform>
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
          <BeginStoryboard>
            <Storyboard>

              <!-- Animate the TranslateTransform's X property
                   from 0 to 350, then 50,
                   then 200 over 10 seconds. -->

              <DoubleAnimationUsingKeyFrames
                Storyboard.TargetName="MyAnimatedTranslateTransform"
                Storyboard.TargetProperty="X"
                Duration="0:0:10">
                <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />
                <LinearDoubleKeyFrame Value="350" KeyTime="0:0:2" />
                <LinearDoubleKeyFrame Value="50" KeyTime="0:0:7" />
                <LinearDoubleKeyFrame Value="200" KeyTime="0:0:8" />                          
              </DoubleAnimationUsingKeyFrames>
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers> 
    </Rectangle>
  </Border> 
</Page>

Like a From/To/By animation, a key-frame animation can be applied to a property by using a Storyboard in markup and code or by using the BeginAnimation method in code. You may also use a key-frame animation to create an AnimationClock and apply it to one or more properties. For more information about the different methods for applying animations, see the Property Animation Techniques Overview.

Key-Frame Animation Types

Because animations generate property values, there are different animation types for different property types. To animate a property that takes a Double (such as an element's Width property), you use an animation that produces Double values. To animate a property that takes a Point, you use an animation that produces Point values, and so on.

The key-frame animation classes belong to the System.Windows.Media.Animation namespace and adhere to the following naming convention:

<Type>AnimationUsingKeyFrames

Where <Type> is the type of value that the class animates.

WPF provides the following key-frame animation classes.

Property type

Corresponding from/to/by animation class

Interpolation methods supported

Boolean

BooleanAnimationUsingKeyFrames

Discrete

Byte

ByteAnimationUsingKeyFrames

Discrete, Linear, Splined

Color

ColorAnimationUsingKeyFrames

Discrete, Linear, Splined

Decimal

DecimalAnimationUsingKeyFrames

Discrete, Linear, Splined

Double

DoubleAnimationUsingKeyFrames

Discrete, Linear, Splined

Int16

Int16AnimationUsingKeyFrames

Discrete, Linear, Splined

Int32

Int32AnimationUsingKeyFrames

Discrete, Linear, Splined

Int64

Int64AnimationUsingKeyFrames

Discrete, Linear, Splined

Matrix

MatrixAnimationUsingKeyFrames

Discrete

Object

ObjectAnimationUsingKeyFrames

Discrete

Point

PointAnimationUsingKeyFrames

Discrete, Linear, Splined

Quaternion

QuaternionAnimationUsingKeyFrames

Discrete, Linear, Splined

Rect

RectAnimationUsingKeyFrames

Discrete, Linear, Splined

Rotation3D

Rotation3DAnimationUsingKeyFrames

Discrete, Linear, Splined

Single

SingleAnimationUsingKeyFrames

Discrete, Linear, Splined

String

StringAnimationUsingKeyFrames

Discrete

Size

SizeAnimationUsingKeyFrames

Discrete, Linear, Splined

Thickness

ThicknessAnimationUsingKeyFrames

Discrete, Linear, Splined

Vector3D

Vector3DAnimationUsingKeyFrames

Discrete, Linear, Splined

Vector

VectorAnimationUsingKeyFrames

Discrete, Linear, Splined

Target Values (key frames) and Key Times

Just as there are different types of key-frame animations for animating different property types, there are also different types of key frame objects: one for each type of value animated and interpolation method supported. Key frame types adhere to the following naming convention:

<InterpolationMethod><Type>KeyFrame

Where <InterpolationMethod> is the interpolation method the key frame uses and <Type> is the type of value that the class animates. A key-frame animation that supports all three interpolation methods will have three key frame types that you can use. For example, you can use three key frame types with a DoubleAnimationUsingKeyFramesDiscreteDoubleKeyFrameLinearDoubleKeyFrame, and SplineDoubleKeyFrame. (Interpolation methods are described in detail in a later section.)

The primary purpose of a key frame is to specify a KeyTime and a Value. Every key frame type provides these two properties.

  • The Value property specifies the target value for that key-frame.

  • The KeyTime property specifies when (within the animation's Duration) a key frame's Value is reached.

When a key frame animation begins, iterates through its key frames in the order defined by their KeyTime properties.

  • If there is no key frame at time 0, the animation creates a transition between the target property's current value and the Value of the first key frame; otherwise, the animation's output value becomes the value of the first key frame.

  • The animation creates a transition between the Value of the first and second key frames using the interpolation method specified by the second key frame. The transition starts at the first key frame's KeyTime and ends when the second key frame's KeyTime is reached.

  • The animation continues, creating transitions between each subsequent key frame and its preceding key frame.

  • Finally, the animation transitions to the value of the key frame with the greatest key time that is equal to or smaller than the animation's Duration.

If the animation's Duration is Automatic or its Duration is equal to the time of the last key frame, the animation ends. Otherwise, if the animation's Duration is greater than the key time of the last key frame, the animation holds the key frame value until it reaches the end of its Duration. Like all animations, a key-frame animation uses its FillBehavior property to determine whether it holds it final value when it reaches the end of its active period. For more information, see the Timing Behaviors Overview.

The following example uses the DoubleAnimationUsingKeyFrames object defined in the preceding example to demonstrate how the Value and KeyTime properties work.

  • The first key frame immediately sets the animation's output value to 0.

  • The second key frame animates from 0 to 350. It starts after the first key frame ends (at time = 0 seconds) and plays for 2 seconds, ending at time = 0:0:2.

  • The third key frame animates from 350 to 50. It starts when the second key frame ends (at time = 2 seconds) and plays for 5 seconds, ending at time = 0:0:7.

  • The fourth key frame animates from 50 to 200. It starts when the third key frame ends (at time = 7 seconds) and plays for 1 second, ending at time = 0:0:8.

  • Because the Duration property of the animation was set to 10 seconds, the animation holds its final value for two seconds before ending at time = 0:0:10.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="Microsoft.Samples.KeyFrameAnimations.KeyFramesIntroduction"
  WindowTitle="KeyFrame Animations">

  <Border Width="400" BorderBrush="Black">  

    <Rectangle Fill="Blue" 
      Width="50" Height="50"
      HorizontalAlignment="Left">
      <Rectangle.RenderTransform>
        <TranslateTransform 
          x:Name="MyAnimatedTranslateTransform" 
          X="0" Y="0" />
      </Rectangle.RenderTransform>
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
          <BeginStoryboard>
            <Storyboard>

              <!-- Animate the TranslateTransform's X property
                   from 0 to 350, then 50,
                   then 200 over 10 seconds. -->

              <DoubleAnimationUsingKeyFrames
                Storyboard.TargetName="MyAnimatedTranslateTransform"
                Storyboard.TargetProperty="X"
                Duration="0:0:10">
                <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />
                <LinearDoubleKeyFrame Value="350" KeyTime="0:0:2" />
                <LinearDoubleKeyFrame Value="50" KeyTime="0:0:7" />
                <LinearDoubleKeyFrame Value="200" KeyTime="0:0:8" />                          
              </DoubleAnimationUsingKeyFrames>
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers> 
    </Rectangle>
  </Border> 
</Page>

Interpolation Methods

The preceding sections mentioned that some key-frame animations support multiple interpolation methods. An animation's interpolation describes how an animation transitions between values over its duration. By selecting which key frame type you use with your animation, you can define the interpolation method for that key frame segment. There are three different types of interpolation methods: linear, discrete, and splined.

Linear Interpolation

With linear interpolation, the animation progresses at a constant rate of the segment duration. For example, if a key frame segment transitions from 0 to 10 over a duration of 5 seconds, the animation will output the following values at the specified times:

Time

Output value

0

0

1

2

2

4

3

6

4

8

4.25

8.5

4.5

9

5

10

Discrete Interpolation

With discrete interpolation, the animation function jumps from one value to the next without interpolation. If a key frame segment transitions from 0 to 10 over a duration of 5 seconds, the animation will output the following values at the specified times:

Time

Output value

0

0

1

0

2

0

3

0

4

0

4.25

0

4.5

0

5

10

Notice how the animation does not change its output value until the very end of the segment duration.

Splined interpolation is more complex. It is described in the next section.

Splined Interpolation

Splined interpolation can be used to achieve more realistic timing effects. Because animations are so often used to imitate effects that occur in the real world, developers might need fine control of the acceleration and deceleration of objects, and close manipulation of timing segments. Spline key frames enable you to animate with splined interpolation. With other key frames, you specify a Value and KeyTime. With a spline key frame, you also specify a KeySpline. The following example shows a single spline key frame for a DoubleAnimationUsingKeyFrames. Notice the KeySpline property; that's what makes a spline key frame different from the other types of key frames.

<SplineDoubleKeyFrame Value="500" KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />

cubic Bezier curve is defined by a start point, an end point, and two control points. The KeySpline property of a spline key frame defines the two control point of a Bezier curve that extends from (0,0) to (1,1). The first control point controls the curve factor of the first half of the Bezier curve, and the second control point controls the curve factor of the second half of the Bezier segment. The resulting curve describes the rate of change for that spline key frame. The steeper the curve, the faster the key frame changes its values. As the curve gets flatter, the key frame changes its values more slowly.

You might use KeySpline to simulate physical trajectories like falling water or bouncing balls, or apply other "ease in" and "ease out" effects to motion animations. For user interaction effects like background fades or control button rebound, you might apply splined interpolation to speed up or slow down the rate of change for an animation in a specific way.

The following example specifies a KeySpline of 0,1 1,0, which creates the following Bezier curve.

A Bezier curve

A key spline with control points (0.0, 1.0) and (1.0, 0.0)

<SplineDoubleKeyFrame Value="500" KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />

This key frame animates rapidly when it begins, slows down, and then speeds up again before it ends.

The following example specifies a KeySpline of 0.5,0.25 0.75,1.0, which creates the following Bezier curve.

A Bezier curve

A key spline with control points (0.25, 0.5) and (0.75, 1.0)

<SplineDoubleKeyFrame Value="350" KeyTime="0:0:15"  KeySpline="0.25,0.5 0.75,1" />

Because the curvature of the Bezier curve changes very little, this key frame animates at an almost constant rate; it slows down somewhat toward its very end.

The following example uses a DoubleAnimationUsingKeyFrames to animate the position of rectangle. Because the DoubleAnimationUsingKeyFrames uses SplineDoubleKeyFrame objects, the transition between each key frame value uses splined interpolation.

<!-- This rectangle is animated using a key frame animation
     with splined interpolation. -->
<Rectangle 
  Width="50"
  Height="50"
  Fill="Purple">  
  <Rectangle.RenderTransform>
    <TranslateTransform 
      x:Name="SplineAnimatedTranslateTransform" 
      X="0" Y="0" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>

          <!-- Animate the TranslateTransform's X property
               from its base value (0) to 500, then 200,
               then 350 over 15 seconds. -->
          <DoubleAnimationUsingKeyFrames
            Storyboard.TargetName="SplineAnimatedTranslateTransform"
            Storyboard.TargetProperty="X"
            Duration="0:0:15"
            RepeatBehavior="Forever">                
            <SplineDoubleKeyFrame Value="500" KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />

            <SplineDoubleKeyFrame Value="200" KeyTime="0:0:10"  KeySpline="0.0,0.0 1.0,0.0" />

            <SplineDoubleKeyFrame Value="350" KeyTime="0:0:15"  KeySpline="0.25,0.5 0.75,1" />
          </DoubleAnimationUsingKeyFrames>           
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers> 
</Rectangle>

Splined interpolation can be difficult to understand; experimenting with different settings can help. The Key Spline Animation Sample enables you to change key spline values and see the result it has on an animation.

Combining Interpolation Methods

You can use key frames with different interpolation types in a single key frame animation. When two key frame animations with different interpolations follow each other, the interpolation method of the second key frame is used to create the transition from the first value to the second.

In the following example, a DoubleAnimationUsingKeyFrames is created that uses linear, splined, and discrete interpolation.

<!-- This rectangle is animated using a key frame animation
     with a combination of interpolation methods. -->
<Rectangle 
  Width="50"
  Height="50"
  Fill="Orange">  
  <Rectangle.RenderTransform>
    <TranslateTransform 
      x:Name="ComboAnimatedTranslateTransform" 
      X="0" Y="0" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>

          <!-- Animate the TranslateTransform's X property
               from its base value (0) to 500, then 200,
               then 350 over 15 seconds. -->
          <DoubleAnimationUsingKeyFrames
            Storyboard.TargetName="ComboAnimatedTranslateTransform"
            Storyboard.TargetProperty="X"
            Duration="0:0:15"
            RepeatBehavior="Forever">
            <DiscreteDoubleKeyFrame Value="500" KeyTime="0:0:7" />
            <LinearDoubleKeyFrame Value="200" KeyTime="0:0:10" />
            <SplineDoubleKeyFrame Value="350" KeyTime="0:0:15"  
              KeySpline="0.25,0.5 0.75,1" />                      
          </DoubleAnimationUsingKeyFrames>           
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers> 
</Rectangle>

More about Duration and Key Times

Like other animations, key-frame animations have a Duration property. In addition to specifying the animation's Duration, you need to specify what portion of that duration is given to each key frame. You do so by describing a KeyTime for each of the animation's key frames. Each key frame's KeyTime specifies when that key frame ends.

The KeyTime property does not specify how long the key time plays. The amount of time a key frame plays is determined by when the key frame ends, when the previous key frame ended, and the animation's duration. Key times may be specified as a time value, a percentage, or as the special values Uniform or Paced.

The following list describes the different ways of specifying key times.

TimeSpan Values

You may use TimeSpan values to specify a KeyTime. The value should be greater than or equal to 0 and less than or equal to the animation's duration. The following example shows an animation with a duration of 10 seconds and four key frames whose key times are specified as time values.

  • The first key frame animates from the base value to 100 over the first 3 seconds, ending at time = 0:0:03.

  • The second key frame animates from 100 to 200. It starts after the first key frame ends (at time = 3 seconds) and plays for 5 seconds, ending at time = 0:0:8.

  • The third key frame animates from 200 to 500. It starts when the second key frame ends (at time = 8 seconds) and plays for 1 second, ending at time = 0:0:9.

  • The fourth key frame animates from 500 to 600. It starts when the third key frame ends (at time = 9 seconds) and plays for 1 second, ending at time = 0:0:10.

<!-- This rectangle is animated with KeyTimes using TimeSpan values. 
     Goes to 100 in the first 3 seconds, 100 to 200 in 
     the next 5 seconds, 300 to 500 in the next second,
     and 500 to 600 in the final second. -->
<Rectangle Width="50" Height="50" Fill="Blue">
  <Rectangle.RenderTransform>
    <TranslateTransform x:Name="TranslateTransform01" X="10" Y="30" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetName="TranslateTransform01" 
            Storyboard.TargetProperty="X"
            Duration="0:0:10"
            RepeatBehavior="Forever">

            <!-- KeyTime properties are expressed as TimeSpan values 
                 which are in the form of "hours:minutes:seconds". -->
            <LinearDoubleKeyFrame Value="100" KeyTime="0:0:3" />
            <LinearDoubleKeyFrame Value="200" KeyTime="0:0:8" />
            <LinearDoubleKeyFrame Value="500" KeyTime="0:0:9" />
            <LinearDoubleKeyFrame Value="600" KeyTime="0:0:10" />
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

Percentage Values

A percentage value specifies that the key frame ends at some percentage of the animation's Duration. In XAML, you specify the percentage as a number followed by the % symbol. In code, you use the FromPercent method and pass it a Double indicating the percentage. The value must be greater than or equal to 0 and less than or equal to 100 percent. The following example shows an animation with a duration of 10 seconds and four key frames whose key times are specified as percentages.

  • The first key frame animates from the base value to 100 over the first 3 seconds, ending at time = 0:0:3.

  • The second key frame animates from 100 to 200. It starts after the first key frame ends (at time = 3 seconds) and plays for 5 seconds, ending at time = 0:0:8 (0.8 * 10 = 8).

  • The third key frame animates from 200 to 500. It starts when the second key frame ends (at time = 8 seconds) and plays for 1 second, ending at time = 0:0:9 (0.9 * 10 = 9).

  • The fourth key frame animates from 500 to 600. It starts when the third key frame ends (at time = 9 seconds) and plays for 1 second, ending at time = 0:0:10 (1 * 10 = 10).

<!-- Identical animation behavior to the previous rectangle 
     but using percentage values for KeyTimes rather then TimeSpan. -->
<Rectangle Height="50" Width="50" Fill="Purple">
  <Rectangle.RenderTransform>
    <TranslateTransform x:Name="TranslateTransform02" X="10" Y="110" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetName="TranslateTransform02" 
            Storyboard.TargetProperty="X"
            Duration="0:0:10"
            RepeatBehavior="Forever">

            <!-- KeyTime properties are expressed as Percentages. -->
            <LinearDoubleKeyFrame Value="100" KeyTime="30%" />
            <LinearDoubleKeyFrame Value="200" KeyTime="80%" />
            <LinearDoubleKeyFrame Value="500" KeyTime="90%" />
            <LinearDoubleKeyFrame Value="600" KeyTime="100%" />
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

Special Value, Uniform

Use Uniform timing when you want each key frame to take the same amount of time.

Uniform key time divides the available time equally by the number of key frames to determine the end time of each key frame. The following example shows an animation with a duration of 10 seconds and four key frames whose key times are specified as Uniform.

  • The first key frame animates from the base value to 100 over the first 2.5 seconds, ending at time = 0:0:2.5.

  • The second key frame animates from 100 to 200. It starts after the first key frame ends (at time = 2.5 seconds) and plays for approximately 2.5 seconds, ending at time = 0:0:5.

  • The third key frame animates from 200 to 500. It starts when the second key frame ends (at time = 5 seconds) and plays for 2.5 seconds, ending at time = 0:0:7.5.

  • The fourth key frame animates from 500 to 600. It starts when the second key frame ends (at time = 7.5 seconds) and plays for 2.5 seconds, ending at time = 0:0:1.

<!-- This rectangle is animated with KeyTimes using Uniform values.  -->
<Rectangle Height="50" Width="50" Fill="Red">
  <Rectangle.RenderTransform>
    <TranslateTransform x:Name="TranslateTransform03" X="10" Y="190" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetName="TranslateTransform03" 
            Storyboard.TargetProperty="X"
            Duration="0:0:10"
            RepeatBehavior="Forever">

            <!-- KeyTime properties are expressed with values of Uniform. 
                 When a key time is set to "Uniform" the total allotted 
                 time of the animation is divided evenly between key frames.  
                 In this example, the total duration of the animation is 
                 ten seconds and there are four key frames each of which 
                 are set to "Uniform", therefore, the duration of each key frame 
                 is 3.3 seconds (10/3). -->
            <LinearDoubleKeyFrame Value="100" KeyTime="Uniform" />
            <LinearDoubleKeyFrame Value="200" KeyTime="Uniform" />
            <LinearDoubleKeyFrame Value="500" KeyTime="Uniform" />
            <LinearDoubleKeyFrame Value="600" KeyTime="Uniform" />
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

Special Value, Paced

Use Paced timing when you want to animate at a constant rate.

Paced key time allocates the available time according to the length of each of the key frames to determine the duration of each frame. This will provide the behavior that the velocity or pace of the animation remains constant. The following example shows an animation with a duration of 10 seconds and three key frames whose key times are specified as Paced.

<!-- Using Paced Values. Rectangle moves between key frames at 
     uniform rate except for first key frame
     because using a Paced value on the first KeyFrame in a 
     collection of frames gives a time of zero. -->
<Rectangle Height="50" Width="50" Fill="Orange">
  <Rectangle.RenderTransform>
    <TranslateTransform x:Name="TranslateTransform04" X="10" Y="270" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetName="TranslateTransform04" 
            Storyboard.TargetProperty="X"
            Duration="0:0:10"
            RepeatBehavior="Forever">

            <!-- KeyTime properties are expressed with values of Paced. 
                 Paced values are used when a constant rate is desired. 
                 The time allocated to a key frame with a KeyTime of "Paced" 
                 is determined by the time allocated to the other key 
                 frames of the animation. This time is calculated to 
                 attempt to give a "paced" or "constant velocity" 
                 for the animation. -->
            <LinearDoubleKeyFrame Value="100" KeyTime="Paced" />
            <LinearDoubleKeyFrame Value="200" KeyTime="Paced" />
            <LinearDoubleKeyFrame Value="500" KeyTime="Paced" />
            <LinearDoubleKeyFrame Value="600" KeyTime="Paced" />
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

Note that, if the last key frame's key time is Paced or Uniform, its resolved key time will be set to 100 percent. If the first key frame in a multiframe animation is paced, its resolved key time will be set to 0. (If the key frame collection contains only a single key frame and it is a paced key frame, its resolved key time will be set to 100 percent.)

Different key frames within a single key frame animation may use different key time types.

Combining Key Times, Out-Of-Order Key Frames

You can use key frames with different KeyTime value types in the same animation. And, although it's recommended that you add key frames in the order in which they should play, it's not necessary. The animation and timing system is capable of resolving out of order key frames. Key frames with invalid key times are ignored.

The following list describes the procedure by which key times are resolved for a key-frame animation's key frames.

  1. Resolve TimeSpan KeyTime values.

  2. Determine the animation’s total interpolation time, the total time it takes the key-frame animation to complete a forward iteration.

    1. If the animation's Duration is not Automatic or Forever, the total interpolation time is the value of the animation's Duration property.

    2. Otherwise, the total interpolation time is the largest TimeSpan KeyTime value specified among its key frames, if any exist.

    3. Otherwise, the total interpolation time is 1 second.

  3. Use the total interpolation time value to resolve Percent KeyTime values.

  4. Resolve last key frame, if it wasn't already resolved in the previous steps. If the KeyTime of the last key frame is Uniform or Paced, its resolved time will be equal to the total interpolation time.

    If the KeyTime of the first key frame is Paced and this animation has more than on key frames, resolve its KeyTime value to zero; if there is only one key frame and its KeyTime value is Paced, it is resolved to the total interpolation time, as described in the preceding step.

  5. Resolve remaining Uniform KeyTime values: they are each given an equal share of the available time. During this process, unresolved Paced KeyTime values are temporarily treated as Uniform KeyTime values, and get a temporary resolved time.

  6. Resolve the KeyTime values of key frames with unspecified key times by using the key frames declared nearest them that have resolved KeyTime values.

  7. Resolve remaining Paced KeyTime values. Paced KeyTime use the KeyTime values of the neighboring key frames to determine their resolved time. The goal is to ensure that the velocity of the animation is constant around this key frame's resolved time.

  8. Sort key frames in order of resolved time (primary key), and order of declaration (secondary key), i.e., use a stable sort based on the resolved key frame KeyTime values.






Easing Functions


Easing functions allow you to apply custom mathematical formulas to your animations. For example, you may want an object to realistically bounce or behave as though it were on a spring. You could use Key-Frame or even From/To/By animations to approximate these effects but it would take a significant amount of work and the animation would be less accurate than using a mathematical formula.

Besides creating your own custom easing function by inheriting from EasingFunctionBase, you can use one of several easing functions provided by the runtime to create common effects.

  • BackEase: Retracts the motion of an animation slightly before it begins to animate in the path indicated.

  • BounceEase: Creates a bouncing effect.

  • CircleEase: Creates an animation that accelerates and/or decelerates using a circular function.

  • CubicEase: Creates an animation that accelerates and/or decelerates using the formula ft) = t3.

  • ElasticEase: Creates an animation that resembles a spring oscillating back and forth until it comes to rest.

  • ExponentialEase: Creates an animation that accelerates and/or decelerates using an exponential formula.

  • PowerEase: Creates an animation that accelerates and/or decelerates using the formula ft) = tp where p is equal to the Power property.

  • QuadraticEase: Creates an animation that accelerates and/or decelerates using the formula ft) = t2.

  • QuarticEase: Creates an animation that accelerates and/or decelerates using the formula ft) = t4.

  • QuinticEase: Create an animation that accelerates and/or decelerates using the formula ft) = t5.

  • SineEase: Creates an animation that accelerates and/or decelerates using a sine formula.

You can explore the behavior of these easing functions with the following sample.

Run this sample

To apply an easing function to an animation, use the EasingFunction property of the animation specify the easing function to apply to the animation. The following example applies a BounceEase easing function to a DoubleAnimation to create a bouncing effect.

Run this sample

<Rectangle Name="myRectangle" Width="200" Height="30" Fill="Blue">
    <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.MouseDown">
            <BeginStoryboard>
                <Storyboard>
                    <Storyboard x:Name="myStoryboard">
                        <DoubleAnimation From="30" To="200" Duration="00:00:3" 
                         Storyboard.TargetName="myRectangle" 
                         Storyboard.TargetProperty="Height">
                            <DoubleAnimation.EasingFunction>
                                <BounceEase Bounces="2" EasingMode="EaseOut" 
                                 Bounciness="2" />
                            </DoubleAnimation.EasingFunction>
                        </DoubleAnimation>
                    </Storyboard>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Rectangle.Triggers>
</Rectangle>

In the previous example, the easing function was applied to a From/To/By animation. You can also apply these easing functions to Key-Frame animations. The following example shows how to use key frames with easing functions associated with them to create an animation of a rectangle that contracts upward, slows down, then expands downward (as though falling) and then bounces to a stop.

Run this sample

<Rectangle Name="myRectangle" Width="200" Height="200" Fill="Blue">
    <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.MouseDown">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames
                     Storyboard.TargetProperty="Height"
                     Storyboard.TargetName="myRectangle">

                        <!-- This keyframe animates the ellipse up to the crest 
                             where it slows down and stops. -->
                        <EasingDoubleKeyFrame Value="30" KeyTime="00:00:02">
                            <EasingDoubleKeyFrame.EasingFunction>
                                <CubicEase EasingMode="EaseOut"/>
                            </EasingDoubleKeyFrame.EasingFunction>
                        </EasingDoubleKeyFrame>

                        <!-- This keyframe animates the ellipse back down and makes
                             it bounce. -->
                        <EasingDoubleKeyFrame Value="200" KeyTime="00:00:06">
                            <EasingDoubleKeyFrame.EasingFunction>
                                <BounceEase Bounces="5" EasingMode="EaseOut"/>
                            </EasingDoubleKeyFrame.EasingFunction>
                        </EasingDoubleKeyFrame>

                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Rectangle.Triggers>

</Rectangle>

You can use the EasingMode property to alter how the easing function behaves, that is, change how the animation interpolates. There are three possible values you can give for EasingMode:

  • EaseIn: Interpolation follows the mathematical formula associated with the easing function.

  • EaseOut: Interpolation follows 100% interpolation minus the output of the formula associated with the easing function.

  • EaseInOut: Interpolation uses EaseIn for the first half of the animation and EaseOut for the second half.

The graphs below demonstrate the different values of EasingMode where fx) represents the animation progress and t represents time.

BackEase

BackEase EasingMode graphs.

BounceEase

BounceEase EasingMode graphs.

CircleEase

CircleEase EasingMode graphs.

CubicEase

CubicEase EasingMode graphs.

ElasticEase

ElasticEase with graphs of different easingmodes.

ExponentialEase

ExponentialEase graphs of different easingmodes.

PowerEase

QuarticEase with graphs of different easingmodes.

QuadraticEase

QuadraticEase with graphs of different easingmodes

QuarticEase

QuarticEase with graphs of different easingmodes.

QuinticEase

QuinticEase with graphs of different easingmodes.

SineEase

SineEase for different EasingMode values
System_CAPS_noteNote

You can use PowerEase to create the same behavior as CubicEaseQuadraticEaseQuarticEase, and QuinticEase by using the Power property. For example, if you want to use PowerEase to substitute for CubicEase, specify a Power value of 3.

In addition to using the easing functions included in the run-time, you can create your own custom easing functions by inheriting fromEasingFunctionBase. The following example demonstrates how to create a simple custom easing function. You can add your own mathematical logic for how the easing function behaves by overriding the EaseInCore method.

Run this sample

namespace CustomEasingFunction
{
    public class CustomSeventhPowerEasingFunction : EasingFunctionBase
    {
        public CustomSeventhPowerEasingFunction()
            : base()
        {
        }

        // Specify your own logic for the easing function by overriding
        // the EaseInCore method. Note that this logic applies to the "EaseIn"
        // mode of interpolation. 
        protected override double EaseInCore(double normalizedTime)
        {
            // applies the formula of time to the seventh power.
            return Math.Pow(normalizedTime, 7);
        }

        // Typical implementation of CreateInstanceCore
        protected override Freezable CreateInstanceCore()
        {

            return new CustomSeventhPowerEasingFunction();
        }

    }
}
<Window x:Class="CustomEasingFunction.Window1"
        xmlns:CustomEase="clr-namespace:CustomEasingFunction"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="500" Width="300">
    <StackPanel>
        <TextBlock Margin="10" TextWrapping="Wrap">Click on the rectangle to start the animation</TextBlock>
        <StackPanel x:Name="LayoutRoot" Background="White">

            <Rectangle Name="myRectangle" Width="200" Height="30" Fill="Blue">
                <Rectangle.Triggers>
                    <EventTrigger RoutedEvent="Rectangle.MouseDown">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation From="30" To="300" Duration="00:00:3" 
                                 Storyboard.TargetName="myRectangle" 
                                 Storyboard.TargetProperty="Height">
                                    <DoubleAnimation.EasingFunction>

                                        <!-- You get the EasingMode property for free on your custom
                                             easing function.-->
                                        <CustomEase:CustomSeventhPowerEasingFunction EasingMode="EaseIn"/>
                                    </DoubleAnimation.EasingFunction>
                                </DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Rectangle.Triggers>

            </Rectangle>

        </StackPanel>
    </StackPanel>

</Window>






Path Animations Overview


This topic introduces path animations, which enable you to use a geometric path to generate output values. Path animations are useful for moving and rotating objects along complex paths.

Prerequisites

To understand this topic, you should be familiar with WPF animations features. For an introduction to animation features, see the Animation Overview

Because you use a PathGeometry object to define a path animation, you should also be familiar with PathGeometry and the different types ofPathSegment objects. For more information, see the Geometry Overview.

What Is a Path Animation?

A path animation is a type of AnimationTimeline that uses a PathGeometry as its input. Instead of setting a From, To, or By property (as you do for a From/To/By animation) or using key frames (as you use for a key-frame animation), you define a geometric path and use it to set the PathGeometryproperty of the path animation. As the path animation progresses, it reads the x, y, and angle information from the path and uses that information to generate its output.

Path animations are very useful for animating an object along a complex path. One way to move an object along a path is to use a MatrixTransformand a MatrixAnimationUsingPath to transform an object along a complex path. The following example demonstrates this technique by using theMatrixAnimationUsingPath object to animate the Matrix property of a MatrixTransform. The MatrixTransform is applied to a button and causes it to move along a curved path. Because the DoesRotateWithTangent property is set to true, the rectangle rotates along the tangent of the path.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" 
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="PresentationOptions" Margin="20">
  <Canvas Width="400" Height="400">

    <!-- The Button that is animated across the screen by animating
         the MatrixTransform applied to the button. -->
    <Button MinWidth="100" Content="A Button">
      <Button.RenderTransform>
        <MatrixTransform x:Name="ButtonMatrixTransform">
          <MatrixTransform.Matrix >
            <Matrix />
          </MatrixTransform.Matrix>
        </MatrixTransform>
      </Button.RenderTransform>
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Loaded">
          <BeginStoryboard>
            <Storyboard>
              <MatrixAnimationUsingPath
              Storyboard.TargetName="ButtonMatrixTransform"
              Storyboard.TargetProperty="Matrix"
              DoesRotateWithTangent="True"
              Duration="0:0:5" 
              RepeatBehavior="Forever" >
                <MatrixAnimationUsingPath.PathGeometry>
                  <PathGeometry 
                    Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100" 
                    PresentationOptions:Freeze="True" />
                </MatrixAnimationUsingPath.PathGeometry>
              </MatrixAnimationUsingPath>
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>
    </Button>
  </Canvas>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;


namespace SDKSample
{

    /// <summary>
    /// Shows how to animate an object along
    /// a geometric path.
    /// </summary>
    public class MatrixAnimationUsingPathDoesRotateWithTangentExample : Page
    {

        public MatrixAnimationUsingPathDoesRotateWithTangentExample()
        {
            this.Margin = new Thickness(20);

            // Create a NameScope for the page so that
            // we can use Storyboards.
            NameScope.SetNameScope(this, new NameScope());

            // Create a button.
            Button aButton = new Button();
            aButton.MinWidth = 100;
            aButton.Content = "A Button";

            // Create a MatrixTransform. This transform
            // will be used to move the button.
            MatrixTransform buttonMatrixTransform = new MatrixTransform();
            aButton.RenderTransform = buttonMatrixTransform;

            // Register the transform's name with the page
            // so that it can be targeted by a Storyboard.
            this.RegisterName("ButtonMatrixTransform", buttonMatrixTransform);

            // Create a Canvas to contain the button
            // and add it to the page.
            // Although this example uses a Canvas,
            // any type of panel will work.
            Canvas mainPanel = new Canvas();
            mainPanel.Width = 400;
            mainPanel.Height = 400;
            mainPanel.Children.Add(aButton);
            this.Content = mainPanel;

            // Create the animation path.
            PathGeometry animationPath = new PathGeometry();
            PathFigure pFigure = new PathFigure();
            pFigure.StartPoint = new Point(10, 100);
            PolyBezierSegment pBezierSegment = new PolyBezierSegment();
            pBezierSegment.Points.Add(new Point(35, 0));
            pBezierSegment.Points.Add(new Point(135, 0));
            pBezierSegment.Points.Add(new Point(160, 100));
            pBezierSegment.Points.Add(new Point(180, 190));
            pBezierSegment.Points.Add(new Point(285, 200));
            pBezierSegment.Points.Add(new Point(310, 100));
            pFigure.Segments.Add(pBezierSegment);
            animationPath.Figures.Add(pFigure);

            // Freeze the PathGeometry for performance benefits.
            animationPath.Freeze();

            // Create a MatrixAnimationUsingPath to move the
            // button along the path by animating
            // its MatrixTransform.
            MatrixAnimationUsingPath matrixAnimation =
                new MatrixAnimationUsingPath();
            matrixAnimation.PathGeometry = animationPath;
            matrixAnimation.Duration = TimeSpan.FromSeconds(5);
            matrixAnimation.RepeatBehavior = RepeatBehavior.Forever;

            // Set the animation's DoesRotateWithTangent property
            // to true so that rotates the rectangle in addition
            // to moving it.
            matrixAnimation.DoesRotateWithTangent = true;

            // Set the animation to target the Matrix property
            // of the MatrixTransform named "ButtonMatrixTransform".
            Storyboard.SetTargetName(matrixAnimation, "ButtonMatrixTransform");
            Storyboard.SetTargetProperty(matrixAnimation, 
                new PropertyPath(MatrixTransform.MatrixProperty));

            // Create a Storyboard to contain and apply the animation.
            Storyboard pathAnimationStoryboard = new Storyboard();
            pathAnimationStoryboard.Children.Add(matrixAnimation);

            // Start the storyboard when the button is loaded.
            aButton.Loaded += delegate(object sender, RoutedEventArgs e)
            {
                // Start the storyboard.
                pathAnimationStoryboard.Begin(this);
            };



        }  
    }
}

For more information about the path syntax that is used in the XAML example, see the Path Markup Syntax overview. For the complete sample, seePath Animation Sample.

You can apply a path animation to a property by using a Storyboard in XAML and code, or by using the BeginAnimation method in code. You can also use a path animation to create an AnimationClock and apply it to one or more properties. For more information about the different methods for applying animations, see Property Animation Techniques Overview.

Path Animation Types

Because animations generate property values, there are different animation types for different property types. To animate a property that takes aDouble (such as the X property of a TranslateTransform), you use an animation that produces Double values. To animate a property that takes a Point, you use an animation that produces Point values, and so on.

Path animation classes belong to the System.Windows.Media.Animation namespace and use the following naming convention:

<Type>AnimationUsingPath

Where <Type> is the type of value that the class animates.

WPF provides the following path animation classes.

MatrixAnimationUsingPath generates Matrix values from its PathGeometry. When used with a MatrixTransform, a MatrixAnimationUsingPath can move an object along a path. If you set the DoesRotateWithTangent property of the MatrixAnimationUsingPath to true, it also rotates the object along the curves of the path.

PointAnimationUsingPath generates Point values from the x- and y-coordinates of its PathGeometry. By using a PointAnimationUsingPath to animate a property that takes Point values, you can move an object along a path. A PointAnimationUsingPath cannot rotate objects.

DoubleAnimationUsingPath generates Double values from its PathGeometry. By setting the Source property, you can specify whether theDoubleAnimationUsingPath uses the x-coordinate, y-coordinate, or angle of the path as its output. You can use a DoubleAnimationUsingPath to rotate an object or move it along the x-axis or y-axis.

Path Animation Input

Each path animation class provides a PathGeometry property for specifying its input. The path animation uses the PathGeometry to generate its output values. The PathGeometry class lets you describe multiple complex figures that are composed of arcs, curves, and lines.

At the heart of a PathGeometry is a collection of PathFigure objects; these objects are so named because each figure describes a discrete shape in the PathGeometry. Each PathFigure consists of one or more PathSegment objects, each of which describes a segment of the figure.

There are many types of segments.

Segment Type

Description

ArcSegment

Creates an elliptical arc between two points.

BezierSegment

Creates a cubic Bezier curve between two points.

LineSegment

Creates a line between two points.

PolyBezierSegment

Creates a series of cubic Bezier curves.

PolyLineSegment

Creates a series of lines.

PolyQuadraticBezierSegment

Creates a series of quadratic Bezier curves.

QuadraticBezierSegment

Creates a quadratic Bezier curve.

The segments in a PathFigure are combined into a single geometric shape, which uses the end point of a segment as the start point of the next segment. The StartPoint property of a PathFigure specifies the point from which the first segment is drawn. Each subsequent segment starts at the end point of the previous segment. For example, a vertical line from 10,50 to 10,150 can be defined by setting the StartPoint property to 10,50 and creating a LineSegment with a Point property setting of 10,150.

For more information about PathGeometry objects, see the Geometry Overview.

In XAML, you can also use a special abbreviated syntax to set the Figures property of a PathGeometry. For more information, see  Path Markup Syntax overview.

For more information about the path syntax that is used in the XAML example, see the Path Markup Syntax overview.






Property Animation Techniques Overview


This topic describes the different approaches for animating properties: storyboards, local animations, clocks, and per-frame animations.

Prerequisites

To understand this topic, you should be familiar with the basic animation features described in the Animation Overview.

Different Ways to Animate

Because there are many different scenarios for animating properties, WPF provides several approaches for animating properties.

For each approach, the following table indicates whether it can be used per-instance, in styles, in control templates, or in data templates; whether it can be used in XAML; and whether the approach enables you to interactively control the animation.  "Per-Instance" refers to the technique of applying an animation or storyboard directly to instances of an object, rather than in a style, control template, or data template.

Animation technique

Scenarios

Supports XAML

Interactively controllable

Storyboard animation

Per-instance, StyleControlTemplateDataTemplate

Yes

Yes

Local animation

Per-instance

No

No

Clock animation

Per-instance

No

Yes

Per-frame animation

Per-instance

No

N/A

Storyboard Animations

Use a Storyboard when you want to define and apply your animations in XAML, interactively control your animations after they start, create a complex tree of animations, or animate in a StyleControlTemplate or DataTemplate. For an object to be animated by a Storyboard, it must be a FrameworkElement or FrameworkContentElement, or it must be used to set a FrameworkElement or FrameworkContentElement. For more details, see the Storyboards Overview.

Storyboard is a special type of container Timeline that provides targeting information for the animations it contains. To animate with a Storyboard, you complete the following three steps.

  1. Declare a Storyboard and one or more animations.

  2. Use the TargetName and TargetProperty attached properties to specify the target object and property of each animation.

  3. (Code only) Define a NameScope for a FrameworkElement or FrameworkContentElement. Register the names of the objects to animate with that FrameworkElement or FrameworkContentElement.

  4. Begin the Storyboard.

Beginning a Storyboard applies animations to the properties they animate and starts them. There are two ways to begin a Storyboard: you can use the Begin method provided by the Storyboard class, or you can use a BeginStoryboard action. The only way to animate in XAML is to use a BeginStoryboard action. A BeginStoryboard action can be used in an EventTrigger, property Trigger, or a DataTrigger.

The following table shows the different places where each Storyboard begin technique is supported: per-instance, style, control template, and data template.

For more information about Storyboard objects, see the Storyboards Overview.

Local Animations

Local animations provide a convenient way to animate a dependency property of any Animatable object. Use local animations when you want to apply a single animation to a property and you don't need to interactively control the animation after it starts. Unlike a Storyboard animation, a local animation can animate an object that isn't associated with a FrameworkElement or a FrameworkContentElement. You also don't have to define a NameScope for this type of animation.

Local animations may only be used in code, and cannot be defined in styles, control templates, or data templates. A local animation cannot be interactively controlled after it is started.

To animate using a local animation, complete the following steps.

  1. Create an AnimationTimeline object.

  2. Use the BeginAnimation method of the object that you want to animate to apply the AnimationTimeline to the property that you specify.

The following example shows how to animate the width and background color of a Button.

/*

   This sample demonstrates how to apply non-storyboard animations to a property.
   To animate in markup, you must use storyboards.

*/

using System;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls;

namespace Microsoft.Samples.Animation.LocalAnimations
{

    // Create the demonstration.
    public class LocalAnimationExample : Page 
    {




        public LocalAnimationExample()
        {


            WindowTitle = "Local Animation Example";
            StackPanel myStackPanel = new StackPanel();
            myStackPanel.Margin = new Thickness(20);                     


            // Create and set the Button.
            Button aButton = new Button();
            aButton.Content = "A Button";

            // Animate the Button's Width.
            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 75;
            myDoubleAnimation.To = 300;
            myDoubleAnimation.Duration =  new Duration(TimeSpan.FromSeconds(5));
            myDoubleAnimation.AutoReverse = true;
            myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

            // Apply the animation to the button's Width property.
            aButton.BeginAnimation(Button.WidthProperty, myDoubleAnimation);       

            // Create and animate a Brush to set the button's Background.
            SolidColorBrush myBrush = new SolidColorBrush();
            myBrush.Color = Colors.Blue;            

            ColorAnimation myColorAnimation = new ColorAnimation();
            myColorAnimation.From = Colors.Blue;
            myColorAnimation.To = Colors.Red;
            myColorAnimation.Duration =  new Duration(TimeSpan.FromMilliseconds(7000));
            myColorAnimation.AutoReverse = true;
            myColorAnimation.RepeatBehavior = RepeatBehavior.Forever;

            // Apply the animation to the brush's Color property.
            myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation);           
            aButton.Background = myBrush;

            // Add the Button to the panel.
            myStackPanel.Children.Add(aButton);
            this.Content = myStackPanel;
        }
    }

}

Clock Animations

Use Clock objects when you want to animate without using a Storyboard and you want to create complex timing trees or interactively control animations after they start. You can use Clock objects to animate a dependency property of any Animatable object.

You cannot use Clock objects directly to animate in styles, control templates, or data templates. (The animation and timing system actually does use Clock objects to animate in styles, control templates, and data templates, but it must create those Clock objects for you from a Storyboard. For more information about the relationship between Storyboard objects and Clock objects, see the Animation and Timing System Overview.)

To apply a single Clock to a property, you complete the following steps.

  1. Create an AnimationTimeline object.

  2. Use the CreateClock method of the AnimationTimeline to create an AnimationClock.

  3. Use the ApplyAnimationClock method of the object that you want to animate to apply the AnimationClock to the property you specify.

The following example shows how to create an AnimationClock and apply it to two similar properties.

/*
    This example shows how to create and apply
    an AnimationClock.
*/

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Animation;


namespace Microsoft.Samples.Animation.TimingBehaviors
{
    public class AnimationClockExample : Page
    {

        ScaleTransform myScaleTransform;

        public AnimationClockExample()
        {

            this.WindowTitle = "Opacity Animation Example";
            this.Background = Brushes.White;
            StackPanel myStackPanel = new StackPanel();
            myStackPanel.Margin = new Thickness(20);

            // Create a button that with a ScaleTransform.
            // The ScaleTransform will animate when the
            // button is clicked.
            Button myButton = new Button();
            myButton.Margin = new Thickness(50);
            myButton.HorizontalAlignment = HorizontalAlignment.Left;
            myButton.Content = "Click Me";           
            myScaleTransform = new ScaleTransform(1,1);
            myButton.RenderTransform = myScaleTransform;


            // Associate an event handler with the
            // button's Click event.
            myButton.Click += new RoutedEventHandler(myButton_Clicked);

            myStackPanel.Children.Add(myButton);
            this.Content = myStackPanel;
        }

        // Create and apply and animation when the button is clicked.
        private void myButton_Clicked(object sender, RoutedEventArgs e)
        {

            // Create a DoubleAnimation to animate the
            // ScaleTransform.
            DoubleAnimation myAnimation = 
                new DoubleAnimation(
                    1, // "From" value
                    5, // "To" value 
                    new Duration(TimeSpan.FromSeconds(5))
                );
            myAnimation.AutoReverse = true;

            // Create a clock the for the animation.
            AnimationClock myClock = myAnimation.CreateClock();            

            // Associate the clock the ScaleX and
            // ScaleY properties of the button's
            // ScaleTransform.
            myScaleTransform.ApplyAnimationClock(
                ScaleTransform.ScaleXProperty, myClock);
            myScaleTransform.ApplyAnimationClock(
                ScaleTransform.ScaleYProperty, myClock);
        }
    }
}

To create a timing tree and use it animate properties, you complete the following steps.

  1. Use ParallelTimeline and AnimationTimeline objects to create the timing tree.

  2. Use the CreateClock of the root ParallelTimeline to create a ClockGroup.

  3. Iterate through the Children of the ClockGroup and apply its child Clock objects. For each AnimationClock child, use the ApplyAnimationClock method of the object that you want to animate to apply the AnimationClock to the property you specify

For more information about Clock objects, see the Animation and Timing System Overview.

Per-Frame Animation: Bypass the Animation and Timing System

Use this approach when you need to completely bypass the WPF animation system. One scenario for this approach is physics animations, where each step in the animation requires objects to be recomputed based on the last set of object interactions.

Per-frame animations cannot be defined inside styles, control templates, or data templates.

To animate frame-by-frame, you register for the Rendering event of the object that contains the objects you want to animate. This event handler method gets called once per frame. Each time that WPF marshals the persisted rendering data in the visual tree across to the composition tree, your event handler method is called.

In your event handler, perform whatever calculations are necessary for your animation effect and set the properties of the objects you want to animate with these values.

To obtain the presentation time for the current frame, the EventArgs associated with this event can be cast as RenderingEventArgs, which provide a RenderingTime property that you can use to obtain the current frame's rendering time.

For more information, see the Rendering page.






Storyboards Overview


This topic shows how to use Storyboard objects to organize and apply animations. It describes how to interactively manipulate Storyboard objects and describes indirect property targeting syntax.

Prerequisites

To understand this topic, you should be familiar with the different animation types and their basic features. For an introduction to animation, see the Animation Overview. You should also know how to use attached properties. For more information about attached properties, see the Attached Properties Overview.

What Is a Storyboard?

Animations are not the only useful type of timeline. Other timeline classes are provided to help you organize sets of timelines, and to apply timelines to properties. Container timelines derive from the TimelineGroup class, and include ParallelTimeline and Storyboard.

Storyboard is a type of container timeline that provides targeting information for the timelines it contains. A Storyboard can contain any type of Timeline, including other container timelines and animations. Storyboard objects enable you to combine timelines that affect a variety of objects and properties into a single timeline tree, making it easy to organize and control complex timing behaviors. For example, suppose you want a button that does these three things.

  • Grow and change color when the user selects the button.

  • Shrink away and then grow back to its original size when clicked.

  • Shrink and fade to 50 percent opacity when it becomes disabled.

In this case, you have multiple sets of animations that apply to the same object, and you want to play at different times, dependent on the state of the button. Storyboard objects enable you to organize animations and apply them in groups to one or more objects.

Where Can You Use a Storyboard?

Storyboard can be used to animate dependency properties of animatable classes (for more information about what makes a class animatable, see the Animation Overview). However, because storyboarding is a framework-level feature, the object must belong to the NameScope of a FrameworkElement or a FrameworkContentElement.

For example, you could use a Storyboard to do the following:

However, you could not use a Storyboard to animate a SolidColorBrush that did not register its name with a FrameworkElement or FrameworkContentElement, or was not used to set a property of a FrameworkElement or FrameworkContentElement.

How to Apply Animations with a Storyboard

To use a Storyboard to organize and apply animations, you add the animations as child timelines of the Storyboard. The Storyboard class provides the Storyboard.TargetName and Storyboard.TargetProperty attached properties. You set these properties on an animation to specify its target object and property.

To apply animations to their targets, you begin the Storyboard using a trigger action or a method. In XAML, you use a BeginStoryboard object with an EventTriggerTrigger, or DataTrigger. In code, you can also use the Begin method.

The following table shows the different places where each Storyboard begin technique is supported: per-instance, style, control template, and data template. "Per-Instance" refers to the technique of applying an animation or storyboard directly to instances of an object, rather than in a style, control template, or data template.

The following example uses a Storyboard to animate the Width of a Rectangle element and the Color of a SolidColorBrush used to paint that Rectangle.

<!-- This example shows how to animate with a storyboard.-->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="Microsoft.Samples.Animation.StoryboardsExample" 
  WindowTitle="Storyboards Example">
  <StackPanel Margin="20">

    <Rectangle Name="MyRectangle"
      Width="100"
      Height="100">
      <Rectangle.Fill>
        <SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
      </Rectangle.Fill>
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.MouseEnter">
          <BeginStoryboard>
            <Storyboard>
              <DoubleAnimation 
                Storyboard.TargetName="MyRectangle"
                Storyboard.TargetProperty="Width"
                From="100" To="200" Duration="0:0:1" />

              <ColorAnimation 
                Storyboard.TargetName="MySolidColorBrush"
                Storyboard.TargetProperty="Color"
                From="Blue" To="Red" Duration="0:0:1" />  
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers>
    </Rectangle> 
  </StackPanel>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Data;
using System.Windows.Shapes;
using System.Windows.Input;


namespace Microsoft.Samples.Animation
{
    public class StoryboardsExample : Page
    {      
        public StoryboardsExample()
        {
            this.WindowTitle = "Storyboards Example";
            StackPanel myStackPanel = new StackPanel();
            myStackPanel.Margin = new Thickness(20);

            Rectangle myRectangle = new Rectangle();
            myRectangle.Name = "MyRectangle";

            // Create a name scope for the page.
            NameScope.SetNameScope(this, new NameScope());            

            this.RegisterName(myRectangle.Name, myRectangle);
            myRectangle.Width = 100;
            myRectangle.Height = 100;
            SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
            this.RegisterName("MySolidColorBrush", mySolidColorBrush);
            myRectangle.Fill = mySolidColorBrush;

            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 100;
            myDoubleAnimation.To = 200;
            myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
            Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
            Storyboard.SetTargetProperty(myDoubleAnimation, 
                new PropertyPath(Rectangle.WidthProperty));

            ColorAnimation myColorAnimation = new ColorAnimation();
            myColorAnimation.From = Colors.Blue;
            myColorAnimation.To = Colors.Red;
            myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
            Storyboard.SetTargetName(myColorAnimation, "MySolidColorBrush");
            Storyboard.SetTargetProperty(myColorAnimation, 
                new PropertyPath(SolidColorBrush.ColorProperty)); 
            Storyboard myStoryboard = new Storyboard();
            myStoryboard.Children.Add(myDoubleAnimation);
            myStoryboard.Children.Add(myColorAnimation);

            myRectangle.MouseEnter += delegate(object sender, MouseEventArgs e)
            {
                myStoryboard.Begin(this);
            };

            myStackPanel.Children.Add(myRectangle);
            this.Content = myStackPanel;
        } 
    }
}

The following sections describe the TargetName and TargetProperty attached properties in more detail.

Targeting Framework Elements, Framework Content Elements, and Freezables

The previous section mentioned that, for an animation to find its target, it must know the target's name and the property to animate. Specifying the property to animate is straight forward: simply set Storyboard.TargetProperty with the name of the property to animate. You specify the name of the object whose property you want to animate by setting the Storyboard.TargetName property on the animation.

For the TargetName property to work, the targeted object must have a name. Assigning a name to a FrameworkElement or a FrameworkContentElement in XAML is different than assigning a name to a Freezable object.

Framework elements are those classes that inherit from the FrameworkElement class. Examples of framework elements include WindowDockPanelButton, and Rectangle. Essentially all windows, panels, and controls are elements. Framework content elements are those classes that inherit from the FrameworkContentElement class. Examples of framework content elements include FlowDocument and Paragraph. If you're not sure whether a type is a framework element or a framework content element, check to see whether it has a Name property. If it does, it's probably a framework element or a framework content element. To be sure, check the Inheritance Hierarchy section of its type page.

To enable the targeting of a framework element or a framework content element in XAML, you set its Name property. In code, you also need to use the RegisterName method to register the element's name with the element for which you've created a NameScope.

The following example, taken from the preceding example, assigns the name MyRectangle a Rectangle, a type of FrameworkElement.

<Rectangle Name="MyRectangle"
  Width="100"
  Height="100">
Rectangle myRectangle = new Rectangle();
myRectangle.Name = "MyRectangle";

// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());            

this.RegisterName(myRectangle.Name, myRectangle);

After it has a name, you can animate a property of that element.

<DoubleAnimation 
  Storyboard.TargetName="MyRectangle"
  Storyboard.TargetProperty="Width"
  From="100" To="200" Duration="0:0:1" />
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, 
    new PropertyPath(Rectangle.WidthProperty));

Freezable types are those classes that inherit from the Freezable class. Examples of Freezable include SolidColorBrushRotateTransform, and GradientStop.

To enable the targeting of a Freezable by an animation in XAML, you use the x:Name Directive to assign it a name. In code, you use theRegisterName method to register its name with the element for which you've created a NameScope.

The following example assigns a name to a Freezable object.

<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);

The object can then be targeted by an animation.

<ColorAnimation 
  Storyboard.TargetName="MySolidColorBrush"
  Storyboard.TargetProperty="Color"
  From="Blue" To="Red" Duration="0:0:1" />  
Storyboard.SetTargetName(myColorAnimation, "MySolidColorBrush");
Storyboard.SetTargetProperty(myColorAnimation, 
    new PropertyPath(SolidColorBrush.ColorProperty)); 

Storyboard objects use name scopes to resolve the TargetName property. For more information about WPF name scopes, see WPF XAML Namescopes. If the TargetName property is omitted, the animation targets the element on which it is defined, or, in the case of styles, the styled element.

Sometimes a name can't be assigned to a Freezable object. For example, if a Freezable is declared as a resource or used to set a property value in a style, it can't be given a name. Because it doesn't have a name, it can't be targeted directly—but it can be targeted indirectly. The following sections describe how to use indirect targeting.

Indirect Targeting

There are times a Freezable can't be targeted directly by an animation, such as when the Freezable is declared as a resource or used to set a property value in a style. In these cases, even though you can't target it directly, you can still animate the Freezable object. Instead of setting the TargetNameproperty with the name of the Freezable, you give it the name of the element to which the Freezable "belongs." For example, a SolidColorBrush used to set the Fill of a rectangle element belongs to that rectangle. To animate the brush, you would set the animation's TargetProperty with a chain of properties that starts at the property of the framework element or framework content element the Freezable was used to set and ends with theFreezable property to animate.

<ColorAnimation 
  Storyboard.TargetName="Rectangle01"
  Storyboard.TargetProperty="Fill.Color"
  From="Blue" To="AliceBlue" Duration="0:0:1" />
DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myColorAnimation, myPropertyPath);

Note that, if the Freezable is frozen, a clone will be made, and that clone will be animated. When this happens, the original object'sHasAnimatedProperties property continues to return false, because the original object is not actually animated. For more information about cloning, see the Freezable Objects Overview.

Also note that, when using indirect property targeting, it's possible to target objects that don't exist. For example, you might assume that theBackground of a particular button was set with a SolidColorBrush and try to animate its Color, when in fact a LinearGradientBrush was used to set the button's Background. In these cases, no exception is thrown; the animation fails to have a visible effect because LinearGradientBrush does not react to changes to the Color property.

The following sections describe indirect property targeting syntax in more detail.

Indirectly Targeting a Property of a Freezable in XAML

To target a property of a freezable in XAML, use the following syntax.

ElementPropertyName.FreezablePropertyName

Where

  • ElementPropertyName is the property of the FrameworkElement which the Freezable is used to set, and

  • FreezablePropertyName is the property of the Freezable to animate.

The following code shows how to animate the Color of a SolidColorBrush used to set the

Fill of a rectangle element.

<Rectangle
  Name="Rectangle01"
  Height="100"
  Width="100"
  Fill="{StaticResource MySolidColorBrushResource}">
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.MouseEnter">
      <BeginStoryboard>
        <Storyboard>
          <ColorAnimation 
            Storyboard.TargetName="Rectangle01"
            Storyboard.TargetProperty="Fill.Color"
            From="Blue" To="AliceBlue" Duration="0:0:1" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

Sometimes you need to target a freezable contained in a collection or array.

To target a freezable contained in a collection, you use the following path syntax.

ElementPropertyName.Children[CollectionIndex].FreezablePropertyName

Where CollectionIndex is the index of the object in its array or collection.

For example, suppose that a rectangle has a TransformGroup resource applied to its RenderTransform property, and you want to animate one of the transforms it contains.

<TransformGroup x:Key="MyTransformGroupResource"
  x:Shared="False">
  <ScaleTransform />
  <RotateTransform />
</TransformGroup>

The following code shows how to animate the Angle property of the RotateTransform shown in the previous example.

<Rectangle
  Name="Rectangle02"
  Height="100"
  Width="100"
  Fill="Blue"
  RenderTransform="{StaticResource MyTransformGroupResource}">
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.MouseEnter">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimation 
            Storyboard.TargetName="Rectangle02"
            Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
            From="0" To="360" Duration="0:0:1" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>  

Indirectly Targeting a Property of a Freezable in Code

In code, you create a PropertyPath object. When you create the PropertyPath, you specify a Path and PathParameters.

To create PathParameters, you create an array of type DependencyProperty that contains a list of dependency property identifier fields. The first identifier field is for the property of the FrameworkElement or FrameworkContentElement that the Freezable is used to set. The next identifier field represents the property of the Freezable to target. Think of it as a chain of properties that connects the Freezable to the FrameworkElement object.

The following is an example of a dependency property chain that targets the Color of a SolidColorBrush used to set the Fill of a rectangle element.

DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {Rectangle.FillProperty, SolidColorBrush.ColorProperty};

You also need to specify a Path. A Path is a String that tells the Path how to interpret its PathParameters. It uses the following syntax.

(OwnerPropertyArrayIndex).(FreezablePropertyArrayIndex)

Where

  • OwnerPropertyArrayIndex is the index of the DependencyProperty array that contains the identifier of the FrameworkElement object's property that the Freezable is used to set, and

  • FreezablePropertyArrayIndex is the index of the DependencyProperty array that contains the identifier of property to target.

The following example shows the Path that would accompany the PathParameters defined in the preceding example .

DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";

The following example combines the code in the previous examples to animate the Color of a SolidColorBrush used to set the Fill of a rectangle element.

// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope()); 

Rectangle rectangle01 = new Rectangle();
rectangle01.Name = "Rectangle01";   
this.RegisterName(rectangle01.Name, rectangle01);
rectangle01.Width = 100;
rectangle01.Height = 100;
rectangle01.Fill = 
    (SolidColorBrush)this.Resources["MySolidColorBrushResource"];

ColorAnimation myColorAnimation = new ColorAnimation();
myColorAnimation.From = Colors.Blue;
myColorAnimation.To = Colors.AliceBlue;
myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myColorAnimation, rectangle01.Name);

DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myColorAnimation, myPropertyPath);

Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myColorAnimation);
BeginStoryboard myBeginStoryboard = new BeginStoryboard();
myBeginStoryboard.Storyboard = myStoryboard;
EventTrigger myMouseEnterTrigger = new EventTrigger();
myMouseEnterTrigger.RoutedEvent = Rectangle.MouseEnterEvent;
myMouseEnterTrigger.Actions.Add(myBeginStoryboard);
rectangle01.Triggers.Add(myMouseEnterTrigger);

Sometimes you need to target a freezable contained in a collection or array. For example, suppose that a rectangle has a TransformGroup resource applied to its RenderTransform property, and you want to animate one of the transforms it contains.

<TransformGroup x:Key="MyTransformGroupResource"
  x:Shared="False">
  <ScaleTransform />
  <RotateTransform />
</TransformGroup>  

To target a Freezable contained in a collection, you use the following path syntax.

(OwnerPropertyArrayIndex).(CollectionChildrenPropertyArrayIndex)[CollectionIndex].(FreezablePropertyArrayIndex)

Where CollectionIndex is the index of the object in its array or collection.

To target the Angle property of the RotateTransform, the second transform in the TransformGroup, you would use the following Path andPathParameters.

DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {
            Rectangle.RenderTransformProperty, 
            TransformGroup.ChildrenProperty,
            RotateTransform.AngleProperty
        };
string thePath = "(0).(1)[1].(2)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myDoubleAnimation, myPropertyPath);

The following example shows the complete code for animating the Angle of a RotateTransform contained within a TransformGroup.

Rectangle rectangle02 = new Rectangle();
rectangle02.Name = "Rectangle02";
this.RegisterName(rectangle02.Name, rectangle02);
rectangle02.Width = 100;
rectangle02.Height = 100;
rectangle02.Fill = Brushes.Blue;
rectangle02.RenderTransform = 
    (TransformGroup)this.Resources["MyTransformGroupResource"];

DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 0;
myDoubleAnimation.To = 360;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myDoubleAnimation, rectangle02.Name);

DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {
            Rectangle.RenderTransformProperty, 
            TransformGroup.ChildrenProperty,
            RotateTransform.AngleProperty
        };
string thePath = "(0).(1)[1].(2)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myDoubleAnimation, myPropertyPath);

Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
BeginStoryboard myBeginStoryboard = new BeginStoryboard();
myBeginStoryboard.Storyboard = myStoryboard;
EventTrigger myMouseEnterTrigger = new EventTrigger();
myMouseEnterTrigger.RoutedEvent = Rectangle.MouseEnterEvent;
myMouseEnterTrigger.Actions.Add(myBeginStoryboard);
rectangle02.Triggers.Add(myMouseEnterTrigger);

Indirectly Targeting with a Freezable as the Starting Point

The previous sections described how to indirectly target a Freezable by starting with a FrameworkElement or FrameworkContentElement and creating a property chain to a Freezable sub-property. You can also use a Freezable as a starting point and indirectly target one of its Freezablesub-properties. One additional restriction applies when using a Freezable as a starting point for indirect targeting: the starting Freezable and everyFreezable between it and the indirectly targeted sub-property must not be frozen.

Interactively Controlling a Storyboard in XAML

To start a storyboard in Extensible Application Markup Language (XAML), you use a BeginStoryboard trigger action. BeginStoryboard distributes the animations to the objects and properties they animate, and starts the storyboard. (For details about this process, see the Animation and Timing System Overview.) If you give the BeginStoryboard a name by specifying its Name property, you make it a controllable storyboard. You can then interactively control the storyboard after it's started. The following is a list of controllable storyboard actions that you use with event triggers to control a storyboard.

In the following example, controllable storyboard actions are used to interactively control a storyboard.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="Microsoft.SDK.Animation.ControllableStoryboardExample"
  WindowTitle="Fading Rectangle Example">
  <StackPanel Margin="10">

    <Rectangle
      Name="MyRectangle"
      Width="100" 
      Height="100"
      Fill="Blue">
    </Rectangle>

    <Button Name="BeginButton">Begin</Button>
    <Button Name="PauseButton">Pause</Button>
    <Button Name="ResumeButton">Resume</Button>
    <Button Name="SkipToFillButton">Skip To Fill</Button>
    <Button Name="StopButton">Stop</Button>

    <StackPanel.Triggers>
      <EventTrigger RoutedEvent="Button.Click" SourceName="BeginButton">
        <BeginStoryboard Name="MyBeginStoryboard">
          <Storyboard>
            <DoubleAnimation
              Storyboard.TargetName="MyRectangle" 
              Storyboard.TargetProperty="(Rectangle.Opacity)"
              From="1.0" To="0.0" Duration="0:0:5" />
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger>
      <EventTrigger RoutedEvent="Button.Click" SourceName="PauseButton">
        <PauseStoryboard BeginStoryboardName="MyBeginStoryboard" />
      </EventTrigger>
      <EventTrigger RoutedEvent="Button.Click" SourceName="ResumeButton">
        <ResumeStoryboard BeginStoryboardName="MyBeginStoryboard" />
      </EventTrigger>
      <EventTrigger RoutedEvent="Button.Click" SourceName="SkipToFillButton">
        <SkipStoryboardToFill BeginStoryboardName="MyBeginStoryboard" />
      </EventTrigger>
      <EventTrigger RoutedEvent="Button.Click" SourceName="StopButton">
        <StopStoryboard BeginStoryboardName="MyBeginStoryboard" />
      </EventTrigger>
    </StackPanel.Triggers>
  </StackPanel>
</Page>

Interactively Controlling a Storyboard by Using Code

The previous examples have shown how to animate using trigger actions. In code, you may also control a storyboard using interactive methods of the Storyboard class. For a Storyboard to be made interactive in code, you must use the appropriate overload of the storyboard's Begin method and specify true to make it controllable. See the Begin(FrameworkElement, Boolean) page for more information.

The following list shows the methods that can be used to manipulate a Storyboard after it has started:

The advantage to using these methods is that you don't need to create Trigger or TriggerAction objects; you just need a reference to the controllableStoryboard you want to manipulate.

Note: All interactive actions taken on a Clock, and therefore also on a Storyboard will occur on the next tick of the timing engine which will happen shortly before the next render. For example, if you use the Seek method to jump to another point in an animation, the property value does not change instantly, rather, the value changes on the next tick of the timing engine.

The following example shows how to apply and control animations using the interactive methods of the Storyboard class.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace SDKSample
{

    public class ControllableStoryboardExample : Page
    {
        private Storyboard myStoryboard;

        public ControllableStoryboardExample()
        {

            // Create a name scope for the page.

            NameScope.SetNameScope(this, new NameScope()); 

            this.WindowTitle = "Controllable Storyboard Example";
            StackPanel myStackPanel = new StackPanel();
            myStackPanel.Margin = new Thickness(10);

            // Create a rectangle.
            Rectangle myRectangle = new Rectangle();
            myRectangle.Name = "myRectangle";

            // Assign the rectangle a name by 
            // registering it with the page, so that
            // it can be targeted by storyboard
            // animations.
            this.RegisterName(myRectangle.Name, myRectangle);
            myRectangle.Width = 100;
            myRectangle.Height = 100;
            myRectangle.Fill = Brushes.Blue;
            myStackPanel.Children.Add(myRectangle);

            //
            // Create an animation and a storyboard to animate the
            // rectangle.
            //
            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 1.0;
            myDoubleAnimation.To = 0.0;
            myDoubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(5000));
            myDoubleAnimation.AutoReverse = true;

            // Create the storyboard.
            myStoryboard = new Storyboard();
            myStoryboard.Children.Add(myDoubleAnimation);
            Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
            Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.OpacityProperty));

            //
            // Create some buttons to control the storyboard
            // and a panel to contain them.
            //
            StackPanel buttonPanel = new StackPanel();
            buttonPanel.Orientation = Orientation.Horizontal;
            Button beginButton = new Button();
            beginButton.Content = "Begin";
            beginButton.Click += new RoutedEventHandler(beginButton_Clicked);
            buttonPanel.Children.Add(beginButton);
            Button pauseButton = new Button();
            pauseButton.Content = "Pause";
            pauseButton.Click += new RoutedEventHandler(pauseButton_Clicked);
            buttonPanel.Children.Add(pauseButton);
            Button resumeButton = new Button();
            resumeButton.Content = "Resume";
            resumeButton.Click += new RoutedEventHandler(resumeButton_Clicked);
            buttonPanel.Children.Add(resumeButton);
            Button skipToFillButton = new Button();
            skipToFillButton.Content = "Skip to Fill";
            skipToFillButton.Click += new RoutedEventHandler(skipToFillButton_Clicked);
            buttonPanel.Children.Add(skipToFillButton);
            Button setSpeedRatioButton = new Button();
            setSpeedRatioButton.Content = "Triple Speed";
            setSpeedRatioButton.Click += new RoutedEventHandler(setSpeedRatioButton_Clicked);
            buttonPanel.Children.Add(setSpeedRatioButton);
            Button stopButton = new Button();
            stopButton.Content = "Stop";
            stopButton.Click += new RoutedEventHandler(stopButton_Clicked);
            buttonPanel.Children.Add(stopButton);
            myStackPanel.Children.Add(buttonPanel);
            this.Content = myStackPanel;        


        }

        // Begins the storyboard.
        private void beginButton_Clicked(object sender, RoutedEventArgs args)
        {
            // Specifying "true" as the second Begin parameter
            // makes this storyboard controllable.
            myStoryboard.Begin(this, true);

        }

        // Pauses the storyboard.
        private void pauseButton_Clicked(object sender, RoutedEventArgs args)
        {
            myStoryboard.Pause(this);

        }

        // Resumes the storyboard.
        private void resumeButton_Clicked(object sender, RoutedEventArgs args)
        {
            myStoryboard.Resume(this);

        }

        // Advances the storyboard to its fill period.
        private void skipToFillButton_Clicked(object sender, RoutedEventArgs args)
        {
            myStoryboard.SkipToFill(this);

        }

        // Updates the storyboard's speed.
        private void setSpeedRatioButton_Clicked(object sender, RoutedEventArgs args)
        {
            // Makes the storyboard progress three times as fast as normal.
            myStoryboard.SetSpeedRatio(this, 3);

        }

        // Stops the storyboard.
        private void stopButton_Clicked(object sender, RoutedEventArgs args)
        {
            myStoryboard.Stop(this);

        }         

    }

}

Animate in a Style

You can use Storyboard objects to define animations in a Style. Animating with a Storyboard in a Style is similar to using a Storyboard elsewhere, with the following three exceptions:

  • You don't specify a TargetName; the Storyboard always targets the element to which the Style is applied. To target Freezable objects, you must use indirect targeting. For more information about indirect targeting, see the Indirect Targeting section.

  • You can't specify a SourceName for an EventTrigger or a Trigger.

  • You can't use dynamic resource references or data binding expressions to set Storyboard or animation property values. That's because everything inside a Style must be thread-safe, and the timing system must FreezeStoryboard objects to make them thread-safe. A Storyboard cannot be frozen if it or its child timelines contain dynamic resource references or data binding expressions. For more information about freezing and other Freezable features, see the Freezable Objects Overview.

  • In XAML, you can't declare event handlers for Storyboard or animation events.

For an example showing how to define a storyboard in a style, see the How to: Animate in a Style example.

Animate in a ControlTemplate

You can use Storyboard objects to define animations in a ControlTemplate. Animating with a Storyboard in a ControlTemplate is similar to using aStoryboard elsewhere, with the following two exceptions:

For an example showing how to define a storyboard in a ControlTemplate, see the How to: Animate in a ControlTemplate example.

Animate When a Property Value Changes

In styles and control templates, you can use Trigger objects to start a storyboard when a property changes. For examples, see How to: Trigger an Animation When a Property Value Changes and How to: Animate in a ControlTemplate.

Animations applied by property Trigger objects behave in a more complex fashion than EventTrigger animations or animations started usingStoryboard methods. They "handoff" with animations defined by other Trigger objects, but compose with EventTrigger and method-triggered animations.






Timing Behaviors Overview


This topic describes the timing behaviors of animations and other Timeline objects.

Prerequisites

To understand this topic, you should be familiar with basic animation features. For more information, see the Animation Overview.

Timeline Types

Timeline represents a segment of time. It provides properties that enable you to specify the length of that segment, when it should start, how many times it will repeat, how fast time progresses in that segment, and more.

Classes that inherit from the timeline class provide additional functionality, such as animation and media playback. WPF provides the followingTimeline types.

Timeline type

Description

AnimationTimeline

Abstract base class for Timeline objects that generate output values for animating properties.

MediaTimeline

Generates output from a media file.

ParallelTimeline

A type of TimelineGroup that groups and controls child Timeline objects.

Storyboard

A type of ParallelTimeline that provides targeting information for the Timeline objects it contains.

Timeline

Abstract base class that defines timing behaviors.

TimelineGroup

Abstract class for Timeline objects that can contain other Timeline objects.

Properties that Control the Length of a Timeline

Timeline represents a segment of time, and the length of a timeline can be described in different ways. The following table defines several terms for describing the length of a timeline.

Term

Description

Properties

Simple duration

The length of time a timeline takes to make a single forward iteration.

Duration

One repetition

The length of time it takes for a timeline to play forward once and, if the AutoReverse property is true, play backwards once.

Duration,AutoReverse

Active period

The length of time it takes for a timeline to complete all the repetitions specified by its RepeatBehaviorproperty.

Duration,AutoReverse,RepeatBehavior

The Duration Property

As previously mentioned, a timeline represents a segment of time. The length of that segment is determined by the timeline's Duration. When a timeline reaches the end of its duration, it stops playing. If the timeline has child timelines, they stop playing as well. In the case of an animation, the Duration specifies how long the animation takes to transition from its starting value to its ending value. A timeline's duration is sometimes called its simple duration, to distinguish between the duration of a single iteration and the total length of time the animation plays including repetitions. You can specify a duration using a finite time value or the special values Automatic or Forever. An animation's duration should resolve to a TimeSpan value, so it can transition between values.

The following example shows a DoubleAnimation with a Duration of five seconds.

<DoubleAnimation 
  Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
  From="0" To="100" Duration="0:0:5"  />

Container timelines, such as Storyboard and ParallelTimeline, have a default duration of Automatic, which means they automatically end when their last child stops playing. The following example shows a Storyboard whose Duration resolves to five seconds, the length of time it takes all its child DoubleAnimation objects to complete.

<Storyboard >

  <DoubleAnimation 
    Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
    From="0" To="100" Duration="0:0:5"  />

  <DoubleAnimation 
    Storyboard.TargetName="MyOtherRectangle" Storyboard.TargetProperty="Width"
    From="0" To="100" Duration="0:0:3"  />

</Storyboard>

By setting the Duration of a container timeline to a TimeSpan value, you can force to play longer or shorter than its child Timeline objects would play. If you set the Duration to a value that's smaller than the length of the container timeline's child Timeline objects, the child Timeline objects stop playing when the container timeline does. The following example sets the Duration of the Storyboard from the preceding examples to three seconds. As a result, the first DoubleAnimation stops progressing after three seconds, when it has animated the target rectangle's width to 60.

<Storyboard Duration="0:0:3">

  <DoubleAnimation 
    Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
    From="0" To="100" Duration="0:0:5"  />

  <DoubleAnimation 
    Storyboard.TargetName="MyOtherRectangle" Storyboard.TargetProperty="Width"
    From="0" To="100" Duration="0:0:3"  />

</Storyboard>

The RepeatBehavior Property

The RepeatBehavior property of a Timeline controls how many times it repeats its simple duration. Using the RepeatBehavior property, you can specify how many times the timeline plays (an iteration Count) or the total length of time it should play (a repeat Duration). In either case, the animation goes through as many beginning-to-end runs as necessary to fill the requested count or duration. By default, timelines have an iteration count of 1.0, which means they play once and do not repeat at all.

The following example uses the RepeatBehavior property to make a DoubleAnimation play for twice its simple duration by specifying an iteration count.

<DoubleAnimation 
  Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
  From="0" To="100" Duration="0:0:5" 
  RepeatBehavior="2x" />

The next example uses the RepeatBehavior property to make the DoubleAnimation play for half its simple duration.

<DoubleAnimation 
  Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
  From="0" To="100" Duration="0:0:5" 
  RepeatBehavior="0.5x" />

If you set the RepeatBehavior property of a Timeline to Forever, the Timeline repeats until stopped interactively or by the timing system. The following example uses the RepeatBehavior property to make the DoubleAnimation play indefinitely.

<DoubleAnimation 
  Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
  From="0" To="100" Duration="0:0:5" 
  RepeatBehavior="Forever" />

For an additional example, see How to: Repeat an Animation.

The AutoReverse Property

The AutoReverse property specifies whether a Timeline will play backwards at the end of each forward iteration. The following example sets to theAutoReverse property of a DoubleAnimation to true; as a result, it animates from zero to 100, and then from 100 to zero. It plays for a total of 10 seconds.

<DoubleAnimation 
  Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
  From="0" To="100" Duration="0:0:5" 
  AutoReverse="True" />

When you use a Count value to specify the RepeatBehavior of a Timeline and the AutoReverse property of that Timeline is true, a single repetition consists of one forward iteration followed by one backwards iteration. The following example sets the RepeatBehavior of the DoubleAnimationfrom the preceding example to a Count of two. As a result, the DoubleAnimation plays for 20 seconds: forward for five seconds, backwards for five seconds, forward for 5 seconds again, and then backwards for five seconds.

<DoubleAnimation 
  Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
  From="0" To="100" Duration="0:0:5" 
  RepeatBehavior="2" 
  AutoReverse="True" />

If a container timeline has child Timeline objects, they reverse when the container timeline does. For additional examples, see How to: Specify Whether a Timeline Automatically Reverses.

The BeginTime Property

The BeginTime property enables you to specify when a timeline starts. A timeline's begin time is relative to its parent timeline. A begin time of zero seconds means the timeline starts as soon as it parent starts; any other value creates an offset between when the parent timeline starts playing and when the child timeline plays. For example, a begin time of two seconds means the timeline starts playing when its parent has reached a time of two seconds. By default, all timelines have a begin time of zero seconds. You may also set a timeline's begin time to null, which prevents the timeline from starting. In WPF, you specify null using the x:Null Markup Extension.

Note that the begin time is not applied each time a timeline repeats because of its RepeatBehavior setting. If you were to create an animation with aBeginTime of 10 seconds and a RepeatBehavior of Forever, there would be a 10-second delay before the animation played for the first time, but not for each successive repetition. However, if the animation's parent timeline were to restart or repeat, the 10-second delay would occur.

The BeginTime property is useful for staggering timelines. The following example creates a Storyboard that has two child DoubleAnimation objects. The first animation has a Duration of five seconds, and the second has a Duration of 3 seconds. The example sets the BeginTime of the secondDoubleAnimation to 5 seconds, so that it begins playing after the first DoubleAnimation ends.

<Storyboard>

  <DoubleAnimation 
    Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
    From="0" To="100" Duration="0:0:5" 
    BeginTime="0:0:0" />


  <DoubleAnimation 
    Storyboard.TargetName="MyOtherRectangle" Storyboard.TargetProperty="Width"
    From="0" To="100" Duration="0:0:3"  
    BeginTime="0:0:5" />

</Storyboard>

The FillBehavior Property

When a Timeline reaches the end of its total active duration, the FillBehavior property specifies whether it stops or holds its last value. An animation with a FillBehavior of HoldEnd "holds" its output value: the property being animated retains the last value of the animation. A value of Stop causes that the animation stop affecting its target property after it ends.

The following example creates a Storyboard that has two child DoubleAnimation objects. Both DoubleAnimation objects animate the Width of aRectangle from 0 to 100. The Rectangle elements have non-animated Width values of 500 device independent pixels.

<Rectangle Name="MyRectangle" 
 Width="500" Height="100"
 Opacity="1" Fill="Red">
</Rectangle>

<Rectangle Name="MyOtherRectangle" 
 Width="500" Height="100"
 Opacity="1" Fill="Orange">
</Rectangle>

<Button Content="Start FillBehavior Example">
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimation 
            Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
            From="0" To="100" Duration="0:0:5" 
            FillBehavior="HoldEnd" />
          <DoubleAnimation 
            Storyboard.TargetName="MyOtherRectangle" Storyboard.TargetProperty="Width"
            From="0" To="100" Duration="0:0:5"  
            FillBehavior="Stop" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

Properties that Control the Speed of a Timeline

The Timeline class provides three properties for specifying its speed:






Timing Events Overview


This topic describes how to use the five timing events available on Timeline and Clock objects.

Prerequisites

To understand this topic, you should understand how to create and use animations. To get started with animation, see the Animation Overview.

There are multiple ways to animate properties in WPF:

Because you can use them in markup and code, the examples in this overview use Storyboard objects. However, the concepts described can be applied to the other methods of animating properties.

What is a clock?

A timeline, by itself, doesn't actually do anything other than describe a segment of time. It's the timeline's Clock object that does the real work: it maintains timing-related run-time state for the timeline. In most cases, such as when using storyboards, a clock is created automatically for your timeline. You can also create a Clock explicitly by using the CreateClock method. For more information about Clock objects, see the Animation and Timing System Overview.

Why Use Events?

With the exception of one (seek aligned to last tick), all interactive timing operations are asynchronous. There is no way for you to know exactly when they will execute. That can be a problem when you have other code that's dependent upon your timing operation. Suppose that you wanted to stop a timeline that animated a rectangle. After the timeline stops, you change the color of the rectangle.

myStoryboard.Stop(myRectangle);

// This statement might execute
// before the storyboard has stopped.
myRectangle.Fill = Brushes.Blue;

In the previous example, the second line of code might execute before the storyboard stops. That's because stopping is an asynchronous operation. Telling a timeline or clock to stop creates a "stop request" of sorts that isn't processed until the timing engine's next tick.

To execute commands after a timeline completes, use timing events. In the following example, an event handler is used to change the color of a rectangle after the storyboard stops playing.

// Register for the CurrentStateInvalidated timing event.
myStoryboard.CurrentStateInvalidated += new EventHandler(myStoryboard_CurrentStateInvalidated);
// Change the rectangle's color after the storyboard stops. 
void myStoryboard_CurrentStateInvalidated(object sender, EventArgs e)
{
    Clock myStoryboardClock = (Clock)sender;
    if (myStoryboardClock.CurrentState == ClockState.Stopped)
    {
        myRectangle.Fill = Brushes.Blue;
    }
}

For a more complete example, see How to: Receive Notification When a Clock's State Changes.

Public Events

The Timeline and Clock classes both provide five timing events. The following table lists these events and the conditions that trigger them.

Event

Triggering interactive operation

Other triggers

Completed

Skip to fill

The clock completes.

CurrentGlobalSpeedInvalidated

Pause, resume, seek, set speed ratio, skip to fill, stop

The clock reverses, accelerates, starts, or stops.

CurrentStateInvalidated

Begin, skip to fill, stop

The clock starts, stops, or fills.

CurrentTimeInvalidated

Begin, seek, skip to fill, stop

The clock progresses.

RemoveRequested

Remove

Ticking and Event Consolidation

When you animate objects in WPF, it’s the timing engine that manages your animations. The timing engine tracks the progression of time and computes the state of each animation. It makes many such evaluation passes in a second. These evaluation passes are known as "ticks."

While ticks occur frequently, it's possible for a lot of things to happen between ticks. For example, a timeline might be stopped, started, and stopped again, in which case its current state will have changed three times. In theory, the event could be raised multiple times in a single tick; however, the timing engine consolidates events, so that each event can be raised at most once per tick.

Registering for Events

There are two ways to register for timing events: you can register with the timeline or with the clock created from the timeline. Registering for an event directly with a clock is fairly straightforward, although it can only be done from code. You can register for events with a timeline from markup or code. The next section describes how to register for clock events with a timeline.

Registering for Clock Events with a Timeline

Although a timeline's CompletedCurrentGlobalSpeedInvalidatedCurrentStateInvalidatedCurrentTimeInvalidated, and RemoveRequested events appear to be associated with the timeline, registering for these events actually associates an event handler with the Clock created for the timeline.

When you register for the Completed event on a timeline, for example, you're actually telling the system to register for the Completed event of each clock that is created for the timeline. In code, you must register for this event before the Clock is created for this timeline; otherwise, you won't receive notification. This happens automatically in XAML; the parser automatically registers for the event before the Clock is created.




How-to Topics



How to: Accelerate or Decelerate an Animation


This example demonstrates how to make an animation accelerate and decelerate over time. In the following example, several rectangles are animated by animations with different AccelerationRatio and DecelerationRatio settings.

                

Example

<!-- This example shows how to use the AccelerationRatio and 
     DecelerationRatio properties of timelines
     to make animations speed up or slow down as they progress. -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:SampleControls="SampleControls"
  WindowTitle="Acceleration and Deceleration Example">
  <StackPanel Margin="20">

    <Rectangle Name="nonAcceleratedOrDeceleratedRectangle" Fill="#9933FF" 
      Width="10" Height="20" HorizontalAlignment="Left" />

    <Rectangle Name="acceleratedRectangle" Fill="#3333FF" 
      Width="10" Height="20" HorizontalAlignment="Left" />

    <Rectangle Name="deceleratedRectangle" Fill="#33FF66" 
      Width="10" Height="20" HorizontalAlignment="Left" />

    <Rectangle Name="acceleratedAndDeceleratedRectangle" Fill="#CCFF33" 
      Width="10" Height="20" HorizontalAlignment="Left" />

    <!-- Create a button to start the animations. -->
    <Button Margin="0,30,0,0" HorizontalAlignment="Left"
      Content="Start Animations">
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard>
            <Storyboard>

              <!-- Creates an animation without acceleration or deceleration for comparison. -->
              <DoubleAnimation         
                Storyboard.TargetName="nonAcceleratedOrDeceleratedRectangle" 
                Storyboard.TargetProperty="(Rectangle.Width)"
                Duration="0:0:10" From="20" To="400" />              

              <!-- Creates an animation that accelerates through 40% of its duration. -->
              <DoubleAnimation 
                Storyboard.TargetName="acceleratedRectangle" 
                Storyboard.TargetProperty="(Rectangle.Width)"
                AccelerationRatio="0.4" Duration="0:0:10" From="20" To="400" />

              <!-- Creates an animation that decelerates through 60% of its duration. -->
              <DoubleAnimation 
                Storyboard.TargetName="deceleratedRectangle" 
                Storyboard.TargetProperty="(Rectangle.Width)"
                DecelerationRatio="0.6" Duration="0:0:10" From="20" To="400" />

              <!-- Creates an animation that accelerates through 40% of its duration and
                   decelerates through the 60% of its duration. -->
              <DoubleAnimation 
                Storyboard.TargetName="acceleratedAndDeceleratedRectangle" 
                Storyboard.TargetProperty="(Rectangle.Width)"
                AccelerationRatio="0.4" DecelerationRatio="0.6" Duration="0:0:10" From="20" To="400" />      
            </Storyboard>  
          </BeginStoryboard>
        </EventTrigger>      
      </Button.Triggers>         
    </Button>
  </StackPanel> 
</Page>

Code has been omitted from this example. For the complete code, see the Animation Timing Behavior Sample.






How to: Accumulate Animation Values During Repeat Cycles


This example shows how to use the IsCumulative property to accumulate animation values across repeating cycles.

Example

Use the IsCumulative property to accumulate base values of an animation across repeating cycles. For example, if you set an animation to repeat 9 times (RepeatBehavior = "9x") and you set the property to animate between 10 and 15 (From = 10 To = 15), the property animates from 10 to 15 during the first cycle, from 15 to 20 during the second cycle, from 20 to 25 during the third cycle, and so on. Hence, each animation cycle uses the ending animation value from the previous animation cycle as its base value.

You can use the IsCumulative property with most basic animations and most key frame animations. For more information, see Animation Overview and Key-Frame Animations Overview.

The following example shows this behavior by animating the width of four rectangles. The example:

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <StackPanel Margin="20" >

    <!-- This rectangle is animated with DoubleAnimation and IsCumulative set to "True". -->
    <Rectangle Name="withIsCumulative"
      Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

    <!-- This rectangle is animated with DoubleAnimation and IsCumulative set to "False". -->
    <Rectangle Name="withoutIsCumulative"
      Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

    <!-- This rectangle is animated with DoubleAnimationUsingKeyFrames and IsCumulative set to "True". -->
    <Rectangle Name="withIsCumulativeUsingKeyFrames"
      Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

    <!-- This rectangle is animated with DoubleAnimationUsingKeyFrames and IsCumulative set to "False". -->
    <Rectangle Name="withoutIsCumulativeUsingKeyFrames"
      Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

    <!-- Create a button to restart the animations. -->
    <Button Margin="0,30,0,0" HorizontalAlignment="Left">
      Restart Animations
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard>
            <Storyboard>

              <!-- DoubleAnimation with IsCumulative set to "True". Because IsCumulative is set to "True", 
                   the base values of the animation will accumulate over repeat cycles. In this example, the
                   first iteration will be from 100 to 200, the second will be from 200 to 300, the third from
                   300 to 400, etc. -->
              <DoubleAnimation 
                Storyboard.TargetName="withIsCumulative" 
                Storyboard.TargetProperty="Width" 
                RepeatBehavior="4x"
                AutoReverse="True"
                IsCumulative="True"
                Duration="0:0:3" From="100" To="200" />

              <!-- DoubleAnimation with IsCumulative set to "False". The starting value 100 pixels and repeat 
                   cycles do not build on earlier ones. -->
              <DoubleAnimation 
                Storyboard.TargetName="withoutIsCumulative" 
                Storyboard.TargetProperty="Width" 
                RepeatBehavior="4x"
                AutoReverse="True"
                IsCumulative="False"
                Duration="0:0:3" From="100" To="200" />

              <!-- DoubleAnimationUsingKeyFrames with IsCumulative set to "True". Similar to the DoubleAnimation
                   above, the base value of each cycle builds on the last one. Note that the output value
                   is the total output value from all the key frames for a total output of 100 pixels. -->
              <DoubleAnimationUsingKeyFrames
                Storyboard.TargetName="withIsCumulativeUsingKeyFrames"
                Storyboard.TargetProperty="Width"
                RepeatBehavior="4x"
                AutoReverse="True"
                IsCumulative="True" >
                <DoubleAnimationUsingKeyFrames.KeyFrames>
                  <LinearDoubleKeyFrame Value="100" KeyTime="0:0:0" />
                  <LinearDoubleKeyFrame Value="130" KeyTime="0:0:1" />
                  <SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="200" KeyTime="0:0:3" />
                </DoubleAnimationUsingKeyFrames.KeyFrames>
              </DoubleAnimationUsingKeyFrames>

              <!-- DoubleAnimationUsingKeyFrames with IsCumulative set to "False". The base value of each cycle
                   does not build on the last one. -->
              <DoubleAnimationUsingKeyFrames
                Storyboard.TargetName="withoutIsCumulativeUsingKeyFrames"
                Storyboard.TargetProperty="Width"
                RepeatBehavior="4x"
                AutoReverse="True"
                IsCumulative="False" >
                <DoubleAnimationUsingKeyFrames.KeyFrames>
                  <LinearDoubleKeyFrame Value="100" KeyTime="0:0:0" />
                  <LinearDoubleKeyFrame Value="130" KeyTime="0:0:1" />
                  <SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="200" KeyTime="0:0:3" />
                </DoubleAnimationUsingKeyFrames.KeyFrames>
              </DoubleAnimationUsingKeyFrames>

            </Storyboard>

          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>
    </Button>
  </StackPanel>
</Page>





How to: Add an Animation Output Value to an Animation Starting Value


This example shows how to add an animation output value to an animation starting value.

Example

The IsAdditive property specifies whether you want the output value of an animation added to the starting value (base value) of an animated property. You can use the IsAdditive property with most basic animations and most key frame animations. For more information, see Animation Overview and Key-Frame Animations Overview.

The following example shows the effect of using the DoubleAnimation.IsAdditive property with DoubleAnimation and using the DoubleAnimationUsingKeyFrames.IsAdditive property with DoubleAnimationUsingKeyFrames.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <StackPanel Margin="20" >

    <!-- This rectangle is animated with DoubleAnimation and IsAdditive set to "True". -->
    <Rectangle Name="withIsAdditive"
      Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

    <!-- This rectangle is animated with DoubleAnimation and IsAdditive set to "False". -->
    <Rectangle Name="withoutIsAdditive"
      Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

    <!-- This rectangle is animated with DoubleAnimationUsingKeyFrames and IsAdditive set to "True". -->
    <Rectangle Name="withIsAdditiveUsingKeyFrames"
      Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

    <!-- This rectangle is animated with DoubleAnimationUsingKeyFrames and IsAdditive set to "False". -->
    <Rectangle Name="withoutIsAdditiveUsingKeyFrames"
      Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

    <!-- Create a button to restart the animations. -->
    <Button Margin="0,30,0,0" HorizontalAlignment="Left">
      Restart Animations
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard>
            <Storyboard>

              <!-- DoubleAnimation with IsAdditive set to "True". Because IsAdditive is set to "True" the 
                   actual starting value of the animation is equal to the sum of the default starting 
                   value of 100 (From="100)and the animation output value of 100 (From="100" To="200") Therefore
                   the animation begins at 200 pixels. Notice that each time the button is clicked and the 
                   animation is initiated, the animation starting value builds upon the preceeding ending value. -->
              <DoubleAnimation 
                Storyboard.TargetName="withIsAdditive" 
                Storyboard.TargetProperty="Width" 
                Duration="0:0:3" From="100" To="200" IsAdditive="True" />

              <!-- DoubleAnimation with IsAdditive set to "False". The starting value is the default starting
                   value of 100 pixels and subsequent animations do not build on earlier ones. -->
              <DoubleAnimation 
                Storyboard.TargetName="withoutIsAdditive" 
                Storyboard.TargetProperty="Width" 
                Duration="0:0:3" From="100" To="200" IsAdditive="False" />

              <!-- DoubleAnimationUsingKeyFrames with IsAdditive set to "True". Similar to the DoubleAnimation
                   above, this animation adds its output value to its starting value. Note that the output value
                   is the total output value from all the key frames for a total output of 100 pixels. -->
              <DoubleAnimationUsingKeyFrames
                 Storyboard.TargetName="withIsAdditiveUsingKeyFrames"
                 Storyboard.TargetProperty="Width"
                 IsAdditive="True" >
                <DoubleAnimationUsingKeyFrames.KeyFrames>
                  <LinearDoubleKeyFrame Value="100" KeyTime="0:0:0" />
                  <LinearDoubleKeyFrame Value="130" KeyTime="0:0:1" />
                  <SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="200" KeyTime="0:0:3" />
                </DoubleAnimationUsingKeyFrames.KeyFrames>
              </DoubleAnimationUsingKeyFrames>

              <!-- DoubleAnimationUsingKeyFrames with IsAdditive set to "False". The starting value is the 
                   default starting value of 100 pixels and subsequent animations do not build on earlier ones. -->
              <DoubleAnimationUsingKeyFrames
                 Storyboard.TargetName="withoutIsAdditiveUsingKeyFrames"
                 Storyboard.TargetProperty="Width"
                 IsAdditive="False" >
                <DoubleAnimationUsingKeyFrames.KeyFrames>
                  <LinearDoubleKeyFrame Value="100" KeyTime="0:0:0" />
                  <LinearDoubleKeyFrame Value="130" KeyTime="0:0:1" />
                  <SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="200" KeyTime="0:0:3" />
                </DoubleAnimationUsingKeyFrames.KeyFrames>
              </DoubleAnimationUsingKeyFrames>

            </Storyboard>

          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>
    </Button>
  </StackPanel>
</Page>





How to: Animate a Property by Using a Storyboard


This example shows how to use a Storyboard to animate properties. To animate a property by using a Storyboard, create an animation for each property that you want to animate and also create a Storyboard to contain the animations.

The type of property determines the type of animation to use. For example, to animate a property that takes Double values, use a DoubleAnimation. The TargetName and TargetProperty attached properties specify the object and property to which the animation is applied.

To start a storyboard in Extensible Application Markup Language (XAML), use a BeginStoryboard action and an EventTrigger. The EventTrigger begins the BeginStoryboard action when the event that is specified by its RoutedEvent property occurs. The BeginStoryboard action starts the Storyboard.

The following example uses Storyboard objects to animate two Button controls. To make the first button change in size, its Width is animated. To make the second button change color, the Color property of the SolidColorBrush is used to set the Background of the button that is animated.

Example

<!-- StoryboardExample.xaml
     Uses storyboards to animate properties. -->
<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  WindowTitle="Animate Properties with Storyboards">

  <Border Background="White">
    <StackPanel Margin="30" HorizontalAlignment="Left" MinWidth="500">

      <TextBlock>Storyboard Animation Example</TextBlock>

      <!-- The width of this button is animated. -->
      <Button Name="myWidthAnimatedButton"
        Height="30" Width="200" HorizontalAlignment="Left">
        A Button   
        <Button.Triggers>

          <!-- Animates the width of the first button 
               from 200 to 300. -->         
          <EventTrigger RoutedEvent="Button.Click">
            <BeginStoryboard>
              <Storyboard>           
                <DoubleAnimation Storyboard.TargetName="myWidthAnimatedButton"
                  Storyboard.TargetProperty="Width"
                  From="200" To="300" Duration="0:0:3" />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger>
        </Button.Triggers>
      </Button>

      <!-- The color of the brush used to paint this button is animated. -->
      <Button Height="30" Width="200" 
        HorizontalAlignment="Left">Another Button
        <Button.Background>
          <SolidColorBrush x:Name="myAnimatedBrush" Color="Blue" />
        </Button.Background>
        <Button.Triggers>

        <!-- Animates the color of the brush used to paint 
             the second button from red to blue . -->             
          <EventTrigger RoutedEvent="Button.Click">    
            <BeginStoryboard>
              <Storyboard>
                <ColorAnimation 
                  Storyboard.TargetName="myAnimatedBrush"
                  Storyboard.TargetProperty="Color"
                  From="Red" To="Blue" Duration="0:0:7" />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger>
        </Button.Triggers>
      </Button>
    </StackPanel>
  </Border>
</Page>
System_CAPS_noteNote

Although animations can target both a FrameworkElement object, such as a Control or Panel, and a Freezable object, such as a Brush or Transform, only framework elements have a Name property. To assign a name to a freezable so that it can be targeted by an animation, use the x:Name Directive, as the previous example shows.

If you use code, you must create a NameScope for a FrameworkElement and register the names of the objects to animate with that FrameworkElement. To start the animations in code, use a BeginStoryboard action with an EventTrigger. Optionally, you can use an event handler and the Begin method of Storyboard. The following example shows how to use the Begin method.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace Microsoft.Samples.Animation.AnimatingWithStoryboards
{


    // Uses a storyboard to animate the properties
    // of two buttons.
    public class StoryboardExample : Page
    {

        public StoryboardExample()
        {
            // Create a name scope for the page.
            NameScope.SetNameScope(this, new NameScope());

            this.WindowTitle = "Animate Properties using Storyboards";
            StackPanel myStackPanel = new StackPanel();
            myStackPanel.MinWidth = 500;
            myStackPanel.Margin = new Thickness(30);
            myStackPanel.HorizontalAlignment = HorizontalAlignment.Left;
            TextBlock myTextBlock = new TextBlock();
            myTextBlock.Text = "Storyboard Animation Example";
            myStackPanel.Children.Add(myTextBlock);

            //
            // Create and animate the first button.
            //

            // Create a button.
            Button myWidthAnimatedButton = new Button();
            myWidthAnimatedButton.Height = 30;
            myWidthAnimatedButton.Width = 200;
            myWidthAnimatedButton.HorizontalAlignment = HorizontalAlignment.Left;
            myWidthAnimatedButton.Content = "A Button";

            // Set the Name of the button so that it can be referred
            // to in the storyboard that's created later.
            // The ID doesn't have to match the variable name;
            // it can be any unique identifier.
            myWidthAnimatedButton.Name = "myWidthAnimatedButton";

            // Register the name with the page to which the button belongs.
            this.RegisterName(myWidthAnimatedButton.Name, myWidthAnimatedButton);

            // Create a DoubleAnimation to animate the width of the button.
            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 200;
            myDoubleAnimation.To = 300;
            myDoubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(3000));          

            // Configure the animation to target the button's Width property.
            Storyboard.SetTargetName(myDoubleAnimation, myWidthAnimatedButton.Name); 
            Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Button.WidthProperty));

            // Create a storyboard to contain the animation.
            Storyboard myWidthAnimatedButtonStoryboard = new Storyboard();
            myWidthAnimatedButtonStoryboard.Children.Add(myDoubleAnimation);

            // Animate the button width when it's clicked.
            myWidthAnimatedButton.Click += delegate(object sender, RoutedEventArgs args)
                {
                    myWidthAnimatedButtonStoryboard.Begin(myWidthAnimatedButton);
                };


            myStackPanel.Children.Add(myWidthAnimatedButton);

            //
            // Create and animate the second button.
            //

            // Create a second button.
            Button myColorAnimatedButton = new Button();
            myColorAnimatedButton.Height = 30;
            myColorAnimatedButton.Width = 200;
            myColorAnimatedButton.HorizontalAlignment = HorizontalAlignment.Left;
            myColorAnimatedButton.Content = "Another Button";

            // Create a SolidColorBrush to paint the button's background.
            SolidColorBrush myBackgroundBrush = new SolidColorBrush();
            myBackgroundBrush.Color = Colors.Blue;

            // Because a Brush isn't a FrameworkElement, it doesn't
            // have a Name property to set. Instead, you just
            // register a name for the SolidColorBrush with
            // the page where it's used.
            this.RegisterName("myAnimatedBrush", myBackgroundBrush);

            // Use the brush to paint the background of the button.
            myColorAnimatedButton.Background = myBackgroundBrush;

            // Create a ColorAnimation to animate the button's background.
            ColorAnimation myColorAnimation = new ColorAnimation();
            myColorAnimation.From = Colors.Red;
            myColorAnimation.To = Colors.Blue;
            myColorAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(7000));    

            // Configure the animation to target the brush's Color property.
            Storyboard.SetTargetName(myColorAnimation, "myAnimatedBrush");                        
            Storyboard.SetTargetProperty(myColorAnimation, new PropertyPath(SolidColorBrush.ColorProperty));    

            // Create a storyboard to contain the animation.
            Storyboard myColorAnimatedButtonStoryboard = new Storyboard();
            myColorAnimatedButtonStoryboard.Children.Add(myColorAnimation);

            // Animate the button background color when it's clicked.
            myColorAnimatedButton.Click += delegate(object sender, RoutedEventArgs args)
                {
                    myColorAnimatedButtonStoryboard.Begin(myColorAnimatedButton);
                };


            myStackPanel.Children.Add(myColorAnimatedButton);
            this.Content = myStackPanel;

        }
    }
}

For more information about animation and storyboards, see Animation Overview.

If you use code, you are not limited to using Storyboard objects in order to animate properties. For more information and examples, see How to: Animate a Property Without Using a Storyboard and How to: Animate a Property by Using an AnimationClock.





How to: Animate in a ControlTemplate


This example shows how to use StoryboardEventTrigger, and Trigger objects to animate within a ControlTemplate.

Example

<!-- ControlStoryboardExample.xaml
     Uses storyboards to animate properties with a ControlTemplate. -->
<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  WindowTitle="Animate Properties with Storyboards">

  <Page.Resources>
    <ControlTemplate x:Key="MyControlTemplate" 
      TargetType="{x:Type ContentControl}">
      <Border 
        Margin="{TemplateBinding Padding}"
        BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="{TemplateBinding BorderThickness}"
        Background="{TemplateBinding Background}">
        <Border Name="innerBorder" Padding="10">
          <Border.Background>
            <SolidColorBrush x:Name="innerBorderBackgroundBrush"
              Color="White" />
          </Border.Background>
          <Grid Name="contentPanel">
            <Grid.Background>
              <SolidColorBrush x:Name="contentPanelBrush" Color="White" />
            </Grid.Background>
            <ContentPresenter 
              Margin="10" 
              Content="{TemplateBinding  Content}" 
              TextBlock.Foreground="{TemplateBinding Foreground}" />
          </Grid>
        </Border>
      </Border>
      <ControlTemplate.Triggers>

        <!-- Event Trigger Example -->
        <EventTrigger RoutedEvent="Border.MouseEnter" SourceName="innerBorder">
          <BeginStoryboard>
            <Storyboard>
              <ColorAnimation
                Storyboard.TargetName="innerBorderBackgroundBrush"
                Storyboard.TargetProperty="Color"
                From="White" To="#CCCCFF"
                Duration="0:0:3" AutoReverse="True" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>

        <!-- Property Trigger Example -->
        <Trigger Property="IsMouseOver" Value="True" SourceName="contentPanel">
          <Trigger.EnterActions>
            <BeginStoryboard>
              <Storyboard>
                <ColorAnimation 
                  Storyboard.TargetName="contentPanelBrush" 
                  Storyboard.TargetProperty="Color"
                  To="Purple" Duration="0:0:1" />
              </Storyboard>
            </BeginStoryboard>
          </Trigger.EnterActions>
          <Trigger.ExitActions>
            <BeginStoryboard>
              <Storyboard>
                <ColorAnimation 
                  Storyboard.TargetName="contentPanelBrush" 
                  Storyboard.TargetProperty="Color"
                  To="White" Duration="0:0:1" />
              </Storyboard>
            </BeginStoryboard>
          </Trigger.ExitActions>
        </Trigger>
      </ControlTemplate.Triggers>
    </ControlTemplate>

  </Page.Resources>

  <Border Background="White">
    <StackPanel Margin="30" HorizontalAlignment="Left" MinWidth="500">

      <ContentControl Template="{StaticResource MyControlTemplate}"
        Content="Hello, World" />

    </StackPanel>
  </Border>
</Page>

For more information about animating properties with storyboards, see Storyboards Overview.





How to: Animate in a Style


This example shows how to animate properties within a style. When animating within a style, only the framework element for which the style is defined can be targeted directly. To target a freezable object, you must "dot down" from a property of the styled element.

In the following example, several animations are defined within a style and applied to a Button. When the user moves the mouse over the button, it fades from opaque to partially translucent and back again, repeatedly. When the user moves the mouse off the button, it becomes completely opaque. When the button is clicked, its background color changes from orange to white and back again. Because the SolidColorBrush used to paint the button can't be targeted directly, it is accessed by dotting down from the button's Background property.

Example

<!-- StyleStoryboardsExample.xaml
     This example shows how to create storyboards in a style. -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  WindowTitle="Storyboards in Styles Example" Background="White">
  <Page.Resources>

    <!-- Defines a Button style. -->
    <Style TargetType="{x:Type Button}" x:Key="MyButtonStyle">
      <Setter Property="Button.Background">
        <Setter.Value>
          <SolidColorBrush Color="Orange" />
        </Setter.Value>
      </Setter>
      <Style.Triggers>

        <!-- Animates the button's opacity on mouse over. -->
        <EventTrigger RoutedEvent="Button.MouseEnter">
          <EventTrigger.Actions>
            <BeginStoryboard>
              <Storyboard>
                <DoubleAnimation
                  Storyboard.TargetProperty="(Button.Opacity)"
                  From="1.0" To="0.5" Duration="0:0:0.5" AutoReverse="True"
                  RepeatBehavior="Forever" />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger.Actions>
        </EventTrigger>  

        <!-- Returns the button's opacity to 1 when the mouse leaves. -->
        <EventTrigger RoutedEvent="Button.MouseLeave">
          <EventTrigger.Actions>
            <BeginStoryboard>
              <Storyboard>
                <DoubleAnimation
                  Storyboard.TargetProperty="(Button.Opacity)"
                  To="1" Duration="0:0:0.1" />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger.Actions>
        </EventTrigger>   

        <!-- Changes the button's color when clicked. 
             Notice that the animation can't target the
             SolidColorBrush used to paint the button's background
             directly. The brush must be accessed through the button's
             Background property. -->
        <EventTrigger RoutedEvent="Button.Click">
          <EventTrigger.Actions>
            <BeginStoryboard>
              <Storyboard>
                <ColorAnimation 
                  Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)"
                  From="Orange" To="White" Duration="0:0:0.1" AutoReverse="True" />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger.Actions>
        </EventTrigger>  
      </Style.Triggers>
    </Style>
  </Page.Resources>

  <StackPanel Margin="20">
    <Button Style="{StaticResource MyButtonStyle}">Click Me</Button>
  </StackPanel>
</Page>

Note that when animating within a style, it's possible to target objects that don't exist. For example, suppose your style uses a SolidColorBrush to set a Button's background property, but at some point the style is overridden and the button's background is set with a LinearGradientBrush. Trying to animate the SolidColorBrush won't throw an exception; the animation will simply fail silently.

Fore more information about storyboard targeting syntax, see the Storyboards Overview. For more information about animation, see the Animation Overview. For more information about styles, see the Styling and Templating.





How to: Animate the Opacity of an Element or Brush


To make a framework element fade in and out of view, you can animate its Opacity property or you can animate the Opacity property of the Brush (or brushes) used to paint it. Animating the element's opacity makes it and its children fade in and out of view, but animating the brush used to paint the element enables you to be more selective about which portion of the element fades. For example, you could animate the opacity of a brush used to paint a button's background. This would cause the button's background to fade in and out of view, while leaving its text fully opaque.

System_CAPS_noteNote

Animating the Opacity of a Brush provides performance benefits over animating the Opacity property of an element.

  

In the following example, two buttons are animated so that they fade in and out of view. The Opacity of the first Button is animated from 1.0 to 0.0over a Duration of five seconds. The second button is also animated, but the Opacity of the SolidColorBrush used to paint its Background is animated rather than the opacity of the entire button. When the example is run, the first button completely fades in and out of view, while only the background of the second button fades in and out of view. Its text and border remain fully opaque.

Example

<!-- OpacityAnimationExample.xaml
     This example shows how to animate the opacity of objects, 
     making them fade in and out of view. -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  WindowTitle="Opacity Animation Example" Background="White">
  <StackPanel Margin="20">

    <!-- Clicking this button animates its opacity. -->
    <Button Name="opacityAnimatedButton">
      A Button
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard>
            <Storyboard>
              <DoubleAnimation 
                Storyboard.TargetName="opacityAnimatedButton"
                Storyboard.TargetProperty="(Button.Opacity)" 
                From="1" To="0" Duration="0:0:5" AutoReverse="True"  /> 
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>
    </Button>

    <!-- Clicking this button animates the opacity of the brush
         used to paint its background. -->
    <Button>
      A Button
      <Button.Background>
        <SolidColorBrush x:Name="MyAnimatedBrush" Color="Orange" />
      </Button.Background>
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard>
            <Storyboard>
              <DoubleAnimation 
                Storyboard.TargetName="MyAnimatedBrush"
                Storyboard.TargetProperty="(Brush.Opacity)" 
                From="1" To="0" Duration="0:0:5" AutoReverse="True"  />  
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>         
    </Button>
  </StackPanel>
</Page>

Code has been omitted from this example. The full sample also shows how to animate the opacity of a Color within a LinearGradientBrush. For the full sample, see the Animating the Opacity of an Element Sample.





How to: Change the Speed of a Clock Without Changing the Speed of Its Timeline


ClockController object's SpeedRatio property enables you to change the speed of a Clock without altering the SpeedRatio of the clock's Timeline. In the following example, a ClockController is used to interactively modify the SpeedRatio of a clock. The CurrentGlobalSpeedInvalidated event and the clock's CurrentGlobalSpeed property are used to display the clock's current global speed each time its interactive SpeedRatio is changed.

Example

/*
  This example shows how to interactively control 
  the speed of a clock
*/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace Microsoft.Samples.Animation.TimingBehaviors
{
    public class ClockControllerSpeedRatioExample : Page
    {

        private AnimationClock myControllableClock;
        private Button speedRatioButton;
        private TextBox speedRatioSettingTextBox;
        private double doubleParseResult = 1;
        private TextBlock currentGlobalSpeedTextBlock;

        public ClockControllerSpeedRatioExample()
        {
            StackPanel mainPanel = new StackPanel();

            // Create a rectangle to animate.
            Rectangle animatedRectangle = new Rectangle();
            animatedRectangle.Width = 100;
            animatedRectangle.Height = 100;
            animatedRectangle.Fill = Brushes.Orange;
            mainPanel.Children.Add(animatedRectangle);
            // Create a DoubleAnimation to
            // animate its width.
            DoubleAnimation widthAnimation = 
                new DoubleAnimation(
                    100,
                    500, 
                    new Duration(TimeSpan.FromSeconds(5)));
            //widthAnimation.RepeatBehavior = RepeatBehavior.Forever;
            widthAnimation.AutoReverse = true;
            widthAnimation.SpeedRatio = 0.5;

            // Create a clock from the animation.
            myControllableClock = widthAnimation.CreateClock();

            // Apply the clock to the rectangle's Width property.
            animatedRectangle.ApplyAnimationClock(
                Rectangle.WidthProperty, myControllableClock);    

            //
            // Create some controls the enable the user to
            // interactively control the SpeedRatio of the clock. 
            //            
            StackPanel speedRatioDetailsPanel = new StackPanel();
            speedRatioDetailsPanel.Margin = new Thickness(0,20,0,20);
            speedRatioDetailsPanel.Orientation = Orientation.Horizontal;
            Label speedRatioLabel = new Label();
            speedRatioLabel.Content = "Speed Ratio:";
            speedRatioDetailsPanel.Children.Add(speedRatioLabel);

            // Create a text box so that the user can
            // specify the amount by which to seek.
            speedRatioSettingTextBox = new TextBox();
            speedRatioSettingTextBox.Text = 
                myControllableClock.Controller.SpeedRatio.ToString();
            speedRatioSettingTextBox.VerticalAlignment = VerticalAlignment.Top;
            speedRatioSettingTextBox.TextChanged += 
                new TextChangedEventHandler(seekAmountTextBox_TextChanged);
            speedRatioDetailsPanel.Children.Add(speedRatioSettingTextBox);          

            // Create a button to apply SpeedRatio changes.
            speedRatioButton = new Button();
            speedRatioButton.Content = "Apply Speed Ratio";
            speedRatioButton.Click += new RoutedEventHandler(speedRatioButton_Clicked);  
            speedRatioDetailsPanel.Children.Add(speedRatioButton);

            mainPanel.Children.Add(speedRatioDetailsPanel);

            // Display the clock's global speed information.
            Label myLabel = new Label();
            myLabel.Content = "CurrentGlobalSpeed ";
            mainPanel.Children.Add(myLabel);
            currentGlobalSpeedTextBlock = new TextBlock();
            currentGlobalSpeedTextBlock.Text = 
                myControllableClock.CurrentGlobalSpeed.ToString();
            mainPanel.Children.Add(currentGlobalSpeedTextBlock);

            // List for speed changes.
            myControllableClock.CurrentGlobalSpeedInvalidated += 
                new EventHandler(myControllableClock_currentGlobalSpeedInvalidated);

            this.Content = mainPanel;
        }


        // Updates the clock's SpeedRatio.
        private void speedRatioButton_Clicked(object sender, RoutedEventArgs e)
        {

            // This statement triggers a CurrentGlobalSpeedInvalidated
            // event.
            myControllableClock.Controller.SpeedRatio = doubleParseResult; 

        }

        // Displays the current global speed.
        private void myControllableClock_currentGlobalSpeedInvalidated(object sender, EventArgs e)
        {

            currentGlobalSpeedTextBlock.Text = 
                myControllableClock.CurrentGlobalSpeed.ToString()
                + " Event triggered at: " 
                + DateTime.Now.ToString();   

        }        

        // Verifies that speedRatioSettingTextBox has valid text content.
        // If it doesn't, the speedRatioButton is disabled.
        private void seekAmountTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {

            TextBox theTextBox = (TextBox)e.Source;
            if (theTextBox.Text == null || theTextBox.Text.Length < 1
                || Double.TryParse(theTextBox.Text, 
                    System.Globalization.NumberStyles.Any, 
                    null, out doubleParseResult) == false)
                speedRatioButton.IsEnabled = false;
            else 
                speedRatioButton.IsEnabled = true;

        }

    }
}





How to: Control a Storyboard After It Starts Using Its Interactive Methods


This example shows how to use code to control a Storyboard after it has started. To control a storyboard in XAML, use Trigger and TriggerAction objects; for an example, see How to: Use Event Triggers to Control a Storyboard After It Starts.

To start a storyboard, you use its Begin method, which distributes the storyboard's animations to the properties they animate and starts the storyboard.

To make a storyboard controllable, you use the Begin method and specify true as the second parameter. You can then use the storyboard's interactive methods to pause, resume, seek, stop, speed up, or slow down the storyboard, or advance it to its fill period. The following is a list of the storyboard's interactive methods:

  • Pause: Pauses the storyboard.

  • Resume: Resumes a paused storyboard.

  • SetSpeedRatio: Sets the storyboard's interactive speed.

  • Seek: Seeks the storyboard the specified location.

  • SeekAlignedToLastTick: Seeks the storyboard to the specified location. Unlike the Seek method, this operation is processed before the next tick.

  • SkipToFill: Advances the storyboard to its fill period, if it has one.

  • Stop: Stops the storyboard.

In the following example, several storyboard methods are used to interactively control a storyboard.

Note: To see an example of controlling a storyboard using triggers with XAML, see How to: Use Event Triggers to Control a Storyboard After It Starts.

Example

/*
    This example shows how to control
    a storyboard after it has started.

*/

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Animation;


namespace Microsoft.Samples.Animation.TimingBehaviors
{
    public partial class ControlStoryboardExample : Page
    {

        private Storyboard myStoryboard;

        public ControlStoryboardExample()
        {

            // Create a name scope for the page.
            NameScope.SetNameScope(this, new NameScope());        

            this.WindowTitle = "Controlling a Storyboard";
            this.Background = Brushes.White;

            StackPanel myStackPanel = new StackPanel();
            myStackPanel.Margin = new Thickness(20);

            // Create a rectangle.
            Rectangle myRectangle = new Rectangle();
            myRectangle.Width = 100;
            myRectangle.Height = 20;
            myRectangle.Margin = new Thickness(12,0,0,5);
            myRectangle.Fill = new SolidColorBrush(Color.FromArgb(170, 51, 51, 255));
            myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
            myStackPanel.Children.Add(myRectangle);

            // Assign the rectangle a name by 
            // registering it with the page, so that
            // it can be targeted by storyboard
            // animations.
            this.RegisterName("myRectangle", myRectangle);           

            //
            // Create an animation and a storyboard to animate the
            // rectangle.
            //
            DoubleAnimation myDoubleAnimation = 
                new DoubleAnimation(100, 500, new Duration(TimeSpan.FromSeconds(5)));            
            Storyboard.SetTargetName(myDoubleAnimation, "myRectangle");
            Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.WidthProperty));
            myStoryboard = new Storyboard();
            myStoryboard.Children.Add(myDoubleAnimation);

            //
            // Create some buttons to control the storyboard
            // and a panel to contain them.
            //
            StackPanel buttonPanel = new StackPanel();
            buttonPanel.Orientation = Orientation.Horizontal;
            Button beginButton = new Button();
            beginButton.Content = "Begin";
            beginButton.Click += new RoutedEventHandler(beginButton_Clicked);            
            buttonPanel.Children.Add(beginButton);
            Button pauseButton = new Button();
            pauseButton.Content = "Pause";
            pauseButton.Click +=new RoutedEventHandler(pauseButton_Clicked);
            buttonPanel.Children.Add(pauseButton);
            Button resumeButton = new Button();
            resumeButton.Content = "Resume";
            resumeButton.Click +=new RoutedEventHandler(resumeButton_Clicked);
            buttonPanel.Children.Add(resumeButton);
            Button skipToFillButton = new Button();
            skipToFillButton.Content = "Skip to Fill";
            skipToFillButton.Click +=new RoutedEventHandler(skipToFillButton_Clicked);
            buttonPanel.Children.Add(skipToFillButton);
            Button setSpeedRatioButton = new Button();
            setSpeedRatioButton.Content = "Triple Speed";
            setSpeedRatioButton.Click +=new RoutedEventHandler(setSpeedRatioButton_Clicked);
            buttonPanel.Children.Add(setSpeedRatioButton);
            Button stopButton = new Button();
            stopButton.Content = "Stop";
            stopButton.Click +=new RoutedEventHandler(stopButton_Clicked);
            buttonPanel.Children.Add(stopButton);
            myStackPanel.Children.Add(buttonPanel);           
            this.Content = myStackPanel;            
        }

        // Begins the storyboard.
        private void beginButton_Clicked(object sender, RoutedEventArgs args)
        {
            // Specifying "true" as the second Begin parameter
            // makes this storyboard controllable.
            myStoryboard.Begin(this, true);          

        }

        // Pauses the storyboard.
        private void pauseButton_Clicked(object sender, RoutedEventArgs args)
        {
             myStoryboard.Pause(this);          

        }

        // Resumes the storyboard.
        private void resumeButton_Clicked(object sender, RoutedEventArgs args)
        {
             myStoryboard.Resume(this);          

        }     

        // Advances the storyboard to its fill period.
        private void skipToFillButton_Clicked(object sender, RoutedEventArgs args)
        {
             myStoryboard.SkipToFill(this);          

        } 

        // Updates the storyboard's speed.
        private void setSpeedRatioButton_Clicked(object sender, RoutedEventArgs args)
        {
            // Makes the storyboard progress three times as fast as normal.
            myStoryboard.SetSpeedRatio(this, 3);          

        }           

        // Stops the storyboard.
        private void stopButton_Clicked(object sender, RoutedEventArgs args)
        {
             myStoryboard.Stop(this);          

        }         



    }
}





How to: Control an Animation using From, To, and By


A "From/To/By" or "basic animation" creates a transition between two target values (see Animation Overview for an introduction to different types of animations). To set the target values of a basic animation, use its FromTo, and By properties. The following table summarizes how the FromTo, and By properties may be used together or separately to determine an animation's target values.

Properties specified

Resulting behavior

From

The animation progresses from the value specified by the From property to the base value of the property being animated or to a previous animation's output value, depending on how the previous animation is configured.

From and To

The animation progresses from the value specified by the From property to the value specified by the To property.

From and By

The animation progresses from the value specified by the From property to the value specified by the sum of the From and Byproperties.

To

The animation progresses from the animated property's base value or a previous animation's output value to the value specified by the To property.

By

The animation progresses from the base value of the property being animated or a previous animation's output value to the sum of that value and the value specified by the By property.

System_CAPS_noteNote

Do not set both the To property and the By property on the same animation.

To use other interpolation methods or animate between more than two target values, use a key frame animation. See Key-Frame Animations Overview for more information.

For information about applying multiple animations to a single property, see Key-Frame Animations Overview.

The example below shows the different effects of setting ToBy, and From properties on animations.

Example

<!-- This example shows the different effects of setting
   To, By, and From properties on animations.  -->
<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

  <StackPanel Margin="20">

    <!-- Demonstrates the From and To properties used together. -->
    <Rectangle Name="fromToAnimatedRectangle" Height="10" Width="100" 
      HorizontalAlignment="Left" Margin="10" Fill="#99FF9900" />

    <!-- Demonstrates the use of the To property. -->
    <Rectangle Name="toAnimatedRectangle" Height="10" Width="100" 
      HorizontalAlignment="Left" Margin="10" Fill="#99FF9900" />

    <!-- Demonstrates the use of the By property. -->
    <Rectangle Name="byAnimatedRectangle" Height="10" Width="100" 
      HorizontalAlignment="Left" Margin="10" Fill="#99FF9900" />

    <!-- Demonstrates the use of the From and By properties. -->
    <Rectangle Name="fromByAnimatedRectangle" Height="10" Width="100" 
      HorizontalAlignment="Left" Margin="10" Fill="#99FF9900" />

    <!-- Demonstrates the use of the From property. -->
    <Rectangle Name="fromAnimatedRectangle" Height="10" Width="100" 
      HorizontalAlignment="Left" Margin="10" Fill="#99FF9900" />
    <Button>
      Start Animations
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard>
            <Storyboard FillBehavior="Stop">

              <!-- Demonstrates the From and To properties used together.
                 Animates the rectangle's Width property from 50 to 300 over 10 seconds. -->
              <DoubleAnimation 
                Storyboard.TargetName="fromToAnimatedRectangle" 
                Storyboard.TargetProperty="(Rectangle.Width)"
                From="50" To="300" Duration="0:0:10" />

              <!-- Demonstrates the To property used by itself.
                 Animates the Rectangle's Width property from its base value
                 (100) to 300 over 10 seconds. -->
              <DoubleAnimation 
                Storyboard.TargetName="toAnimatedRectangle" Storyboard.TargetProperty="(Rectangle.Width)"
                To="300" Duration="0:0:10" />

              <!-- Demonstrates the By property used by itself.
                 Increments the Rectangle's Width property by 300 over 10 seconds.
                 As a result, the Width property is animated from its base value
                 (100) to 400 (100 + 300) over 10 seconds. -->
              <DoubleAnimation 
                Storyboard.TargetName="byAnimatedRectangle" Storyboard.TargetProperty="(Rectangle.Width)" 
                By="300" Duration="0:0:10" />

              <!-- Demonstrates the From and By properties used together.
                 Increments the Rectangle's Width property by 300 over 10 seconds.
                 As a result, the Width property is animated from 50
                 to 350 (50 + 300) over 10 seconds. -->
              <DoubleAnimation 
                Storyboard.TargetName="fromByAnimatedRectangle" Storyboard.TargetProperty="(Rectangle.Width)" 
                From="50" By="300" Duration="0:0:10"  />

              <!-- Demonstrates the From property used by itself.
                 Animates the rectangle's Width property from 50 to its base value (100)
                 over 10 seconds. -->
              <DoubleAnimation 
                Storyboard.TargetName="fromAnimatedRectangle" Storyboard.TargetProperty="(Rectangle.Width)"
                From="50" Duration="0:0:10"  />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>
    </Button>
  </StackPanel>
</Page>





How to: Define a Name Scope


To animate with Storyboard in code, you must create a NameScope and register the target objects' names with the element that owns that name scope. In the following example, a NameScope is created for myMainPanel. Two buttons, button1 and button2, are added to the panel, and their names registered. Several animations and a Storyboard are created. The storyboard's Begin method is used to start the animations.

Because button1button2, and myMainPanel all share the same name scope, any one of them can be used with the Storyboard Begin method to start the animations.

Example

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Microsoft.Samples.Animation.AnimatingWithStoryboards
{




    public class ScopeExample : Page
    {

        private Storyboard myStoryboard;
        private StackPanel myMainPanel;
        private Button button1, button2;

        public ScopeExample()
        {

            this.Background = Brushes.White; 
            myMainPanel = new StackPanel();

            // Create a name scope for the stackpanel. 
            NameScope.SetNameScope(myMainPanel, new NameScope());

            myMainPanel.Background = Brushes.Orange;

            button1 = new Button();
            button1.Name = "Button1";

            // Register button1's name with myMainPanel.
            myMainPanel.RegisterName(button1.Name, button1);
            button1.Content = "Button 1";
            button1.Click += new RoutedEventHandler(button1Clicked);
            myMainPanel.Children.Add(button1);

            button2 = new Button();
            button2.Name = "Button2";

            // Register button2's name with myMainPanel.
            myMainPanel.RegisterName(button2.Name, button2);
            button2.Content = "Button 2";
            button2.Click += new RoutedEventHandler(button2Clicked);
            myMainPanel.Children.Add(button2);


            // Create some animations and a storyboard.
            DoubleAnimation button1WidthAnimation = 
                new DoubleAnimation(300, 200, new Duration(TimeSpan.FromSeconds(5)));
            Storyboard.SetTargetName(button1WidthAnimation, button1.Name);
            Storyboard.SetTargetProperty(button1WidthAnimation, new PropertyPath(Button.WidthProperty));

            DoubleAnimation button2WidthAnimation = 
                new DoubleAnimation(300, 200, new Duration(TimeSpan.FromSeconds(5)));
            Storyboard.SetTargetName(button2WidthAnimation, button2.Name);
            Storyboard.SetTargetProperty(button2WidthAnimation, new PropertyPath(Button.WidthProperty));

            DoubleAnimation heightAnimationWithoutTarget = 
                new DoubleAnimation(300, 200, new Duration(TimeSpan.FromSeconds(5)));
            Storyboard.SetTargetProperty(heightAnimationWithoutTarget, new PropertyPath(FrameworkElement.HeightProperty));                

            myStoryboard = new Storyboard();
            myStoryboard.Children.Add(button1WidthAnimation);
            myStoryboard.Children.Add(button2WidthAnimation);
            myStoryboard.Children.Add(heightAnimationWithoutTarget);

            this.Content = myMainPanel;

        }  


        private void button1Clicked(object sender, RoutedEventArgs args)
        {

            // Starts the animations. The animation without a specified 
            // target name, heightAnimationWithoutTarget, is applied to
            // myMainPanel.
            myStoryboard.Begin(myMainPanel);

        }

        private void button2Clicked(object sender, RoutedEventArgs args)
        {

            // Starts the animations. The animation without a specified 
            // target name, heightAnimationWithoutTarget, is applied to
            // button2.
            myStoryboard.Begin(button2);

        }        

    }


}





How to: Receive Notification When a Clock's State Changes


A clock's CurrentStateInvalidated event occurs when its CurrentState becomes invalid, such as when the clock starts or stops. You can register for this event with directly using a Clock, or you can register using a Timeline.

In the following example, a Storyboard and two DoubleAnimation objects are used to animate the width of two rectangles. The CurrentStateInvalidated event is used to listen for clock state changes.

Example

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  x:Class="Microsoft.Samples.Animation.TimingBehaviors.StateExample"
  Background="LightGray">
  <StackPanel Margin="20">

    <TextBlock 
      Name="ParentTimelineStateTextBlock"></TextBlock>
    <TextBlock 
      Name="Animation1StateTextBlock"></TextBlock>
    <Rectangle 
      Name="Rectangle01"
      Width="100" Height="50" Fill="Orange" />    
    <TextBlock Name="Animation2StateTextBlock"></TextBlock>
    <Rectangle 
      Name="Rectangle02"
      Width="100" Height="50" Fill="Gray" />  

    <Button Content="Start Animations" Margin="20">
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard>
            <Storyboard RepeatBehavior="2x" AutoReverse="True"
              CurrentStateInvalidated="parentTimelineStateInvalidated" >
              <DoubleAnimation
                Storyboard.TargetName="Rectangle01"
                Storyboard.TargetProperty="Width"
                From="10" To="200" Duration="0:0:9"
                BeginTime="0:0:1" 
                CurrentStateInvalidated="animation1StateInvalidated"/>
              <DoubleAnimation
                Storyboard.TargetName="Rectangle02"
                Storyboard.TargetProperty="Width"
                From="10" To="200" Duration="0:0:8"
                BeginTime="0:0:1" 
                CurrentStateInvalidated="animation2StateInvalidated" />            
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>
    </Button>


  </StackPanel>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace Microsoft.Samples.Animation.TimingBehaviors
{

    public partial class StateExample : Page
    {        

        private void parentTimelineStateInvalidated(object sender, EventArgs args)
        {
            Clock myClock = (Clock)sender;
            ParentTimelineStateTextBlock.Text += 
                myClock.CurrentTime.ToString() + ":" 
                + myClock.CurrentState.ToString() + " ";        
        }

        private void animation1StateInvalidated(object sender, EventArgs args)
        {

            Clock myClock = (Clock)sender;

            Animation1StateTextBlock.Text += 
                myClock.Parent.CurrentTime.ToString() + ":" 
                + myClock.CurrentState.ToString() + " ";     
        }

        private void animation2StateInvalidated(object sender, EventArgs args)
        {

            Clock myClock = (Clock)sender;
            Animation2StateTextBlock.Text += 
                myClock.Parent.CurrentTime.ToString() + ":" 
                + myClock.CurrentState.ToString() + " ";                 
        }
    }
}

The following illustration shows the different states the animations enter as the parent timeline (Storyboard) progresses.

Clock states for a Storyboard with two animations

The following table shows the times at which Animation1's CurrentStateInvalidated event fires:

Time (Seconds)

1

10

19

21

30

39

State

Active

Active

Stopped

Active

Active

Stopped

The following table shows the times at which Animation2's CurrentStateInvalidated event fires:

Time (Seconds)

1

9

11

19

21

29

31

39

State

Active

Filling

Active

Stopped

Active

Filling

Active

Stopped

Notice that Animation1's CurrentStateInvalidated event fires at 10 seconds, even though its state remains Active. That's because its state changed at 10 seconds, but it changed from Active to Filling and then back to Active in the same tick.





How to: Repeat an Animation


This example shows how to use the RepeatBehavior property of a Timeline in order to control the repeat behavior of an animation.

Example

The RepeatBehavior property of a Timeline controls how many times an animation repeats its simple duration. By using RepeatBehavior, you can specify that a Timeline repeats for a certain number of times (an iteration count) or for a specified time period. In either case, the animation goes through as many beginning-to-end runs that it needs in order to fill the requested count or duration.

By default, timelines have a repeat count of 1.0, which means they play one time and do not repeat. However, if you set the RepeatBehavior property of a Timeline to Forever, the timeline repeats indefinitely.

The following example shows how to use the RepeatBehavior property to control the repeat behavior of an animation. The example animates the Width property of five rectangles with each rectangle using a different type of repeat behavior.

<!-- RepeatBehaviorExample.xaml
     This example shows how to use the RepeatBehavior property to make a timeline repeat. -->
<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  WindowTitle="RepeatBehavior Example">

  <Border HorizontalAlignment="Stretch">
    <StackPanel Margin="20">

      <!-- Create several rectangles to animate. -->
      <Rectangle Name="ForeverRepeatingRectangle" 
        Fill="Orange" Width="50" Height="20" />
      <Rectangle Name="FourSecondsRepeatingRectangle" 
        Fill="Orange" Width="50" Height="20" />
      <Rectangle Name="TwiceRepeatingRectangle" 
        Fill="Orange" Width="50" Height="20" />
      <Rectangle Name="HalfRepeatingRectangle" 
        Fill="Orange" Width="50" Height="20" />
      <Rectangle Name="OneSecondRepeatingRectangle" 
        Fill="Orange" Width="50" Height="20" />


      <!-- Create buttons to restart and stop the animations. -->
      <StackPanel Orientation="Horizontal" Margin="0,20,0,0">
        <Button Name="restartButton">Start Animations</Button>
        <Button Name="stopButton" Background="#669900FF">Stop</Button>

        <StackPanel.Triggers>
          <EventTrigger SourceName="restartButton" RoutedEvent="Button.Click">
            <BeginStoryboard Name="myBeginStoryboard">
              <Storyboard>

                <!-- Create an animation that repeats indefinitely. -->
                <DoubleAnimation 
                  Storyboard.TargetName="ForeverRepeatingRectangle" 
                  Storyboard.TargetProperty="Width" 
                  From="50" To="300" Duration="0:0:2" RepeatBehavior="Forever" />

                <!-- Create an animation that repeats for four seconds. As a result, the
                     animation repeats twice. -->          
                <DoubleAnimation 
                  Storyboard.TargetName="FourSecondsRepeatingRectangle" 
                  Storyboard.TargetProperty="Width"
                  From="50" To="300" Duration="0:0:2" RepeatBehavior="0:0:4" />

                <!-- Create an animation that repeats twice. -->
                <DoubleAnimation 
                  Storyboard.TargetName="TwiceRepeatingRectangle" 
                  Storyboard.TargetProperty="Width" 
                  From="50" To="300" Duration="0:0:2" RepeatBehavior="2x" />     

                <!-- Create an animation that repeats 0.5 times. The resulting animation
                     plays for one second, half of its Duration. It animates from 50 to 150. -->
                <DoubleAnimation 
                  Storyboard.TargetName="HalfRepeatingRectangle" 
                  Storyboard.TargetProperty="Width" 
                  From="50" To="300" Duration="0:0:2" RepeatBehavior="0.5x" />

                <!-- Create an animation that repeats for one second. The resulting animation
                     plays for one second, half of its Duration. It animates from 50 to 150. -->
                <DoubleAnimation 
                  Storyboard.TargetName="OneSecondRepeatingRectangle" 
                  Storyboard.TargetProperty="Width" 
                  From="50" To="300" Duration="0:0:2" RepeatBehavior="0:0:1" />          
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger>        
          <EventTrigger SourceName="stopButton" RoutedEvent="Button.Click">
            <StopStoryboard BeginStoryboardName="myBeginStoryboard" />
          </EventTrigger>
        </StackPanel.Triggers>
      </StackPanel>
    </StackPanel>
  </Border>
</Page> 

For the complete sample, see Animation Timing Behavior Sample.




How to: Seek a Storyboard


The following example shows how to use the Seek method of a Storyboard to jump to any position in a storyboard animation.

Example

Below is the XAML markup for the sample.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  	x:Class="SDKSample.SeekStoryboardExample">
  <StackPanel Margin="20" >

    <Rectangle Name="myRectangle"
      Width="10" Height="20" Fill="#AA3333FF" HorizontalAlignment="Left" >
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.Loaded">
          <BeginStoryboard Name="myBeginStoryboard">
            <Storyboard Name="myStoryboard" Duration="0:0:4">
              <DoubleAnimation 
                Storyboard.TargetName="myRectangle" 
                Storyboard.TargetProperty="Width" 
                Duration="0:0:4" From="10" To="500"/>
            </Storyboard>

          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers>
    </Rectangle>

    <!-- Use this slider to seek to different points of the Storyboard Duration 
         (in milliseconds). -->
    <Slider Name="SeekSlider" ValueChanged="OnSliderValueChanged" Height="Auto" 
    Width="500" Minimum="0" Maximum="4000" HorizontalAlignment="Left" />

  </StackPanel>
</Page>

Example

Below is the code used with the XAML code above.

using System;
using System.Media;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;

namespace SDKSample
{

    public partial class SeekStoryboardExample : Page
    {
        private void OnSliderValueChanged(object sender, RoutedEventArgs e)
        {
            int sliderValue = (int)SeekSlider.Value;

            // Use the value of the slider to seek to a duration value of the Storyboard (in milliseconds).
            myStoryboard.Seek(myRectangle, new TimeSpan(0, 0, 0, 0, sliderValue), TimeSeekOrigin.BeginTime);
        }
    }

}





How to: Seek a Storyboard Synchronously


The following example shows how to use the SeekAlignedToLastTick method of a Storyboard to seek to any position in a storyboard animation synchronously.

Example

The following is the XAML markup for the sample.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  	x:Class="SDKSample.SeekStoryboardSynchronouslyExample">
  <StackPanel Margin="20" >

    <Rectangle Name="myRectangle"
      Width="10" Height="20" Fill="#AA3333FF" HorizontalAlignment="Left" >
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.Loaded">
          <BeginStoryboard Name="myBeginStoryboard">
            <Storyboard Name="myStoryboard" Duration="0:0:4">
              <DoubleAnimation 
                Storyboard.TargetName="myRectangle" 
                Storyboard.TargetProperty="Width" 
                Duration="0:0:4" From="10" To="500"/>
            </Storyboard>

          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers>
    </Rectangle>

    <!-- Use this slider to seek to different points of the Storyboard Duration 
         (in milliseconds). -->
    <Slider Name="SeekSlider" ValueChanged="OnSliderValueChanged" Height="Auto" 
    Width="500" Minimum="0" Maximum="4000" HorizontalAlignment="Left" />

    <!-- TextBlock displays the current time position of the Storyboard in milliseconds. -->
    <TextBlock Name="PositionTextBlock"/>
  </StackPanel>
</Page>

Example

The following is the code used with the XAML code above.

using System;
using System.Media;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;

namespace SDKSample
{

    public partial class SeekStoryboardSynchronouslyExample : Page
    {
        private void OnSliderValueChanged(object sender, RoutedEventArgs e)
        {
            int sliderValue = (int)SeekSlider.Value;

            // The SeekAlignedToLastTick method should be used to seek a Storyboard synchronously.
            myStoryboard.SeekAlignedToLastTick(myRectangle, new TimeSpan(0, 0, 0, 0, sliderValue), TimeSeekOrigin.BeginTime);
            PositionTextBlock.Text = sliderValue.ToString();
        }
    }

}





How to: Set a Duration for an Animation


Timeline represents a segment of time and the length of that segment is determined by the timeline's Duration. When a Timeline reaches the end of its duration, it stops playing. If the Timeline has child timelines, they stop playing as well. In the case of an animation, the Duration specifies how long the animation takes to transition from its starting value to its ending value.

You can specify a Duration with a specific, finite time or the special values Automatic or Forever. An animation's duration must always be a time value, because an animation must always have a defined, finite length—otherwise, the animation would not know how to transition between its target values. Container timelines (TimelineGroup objects), such as Storyboard and ParallelTimeline, have a default duration of Automatic, which means they automatically end when their last child stops playing.

In the following example, the width, height and fill color of a Rectangle is animated. Durations are set on animation and container timelines resulting in animation effects including controlling the perceived speed of an animation and overriding the duration of child timelines with the duration of a container timeline.

Example

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <StackPanel Margin="20">

    <Rectangle Width="100" Height="100" Name="myRectangle">
      <Rectangle.Fill>
        <SolidColorBrush x:Name="MyAnimatedBrush" Color="Black" />
      </Rectangle.Fill>
      <Rectangle.Triggers>

        <!-- Animates the rectangle fill to yellow and width to 300. -->
        <EventTrigger RoutedEvent="Rectangle.Loaded">
          <BeginStoryboard>

            <!-- By default, TimelineGroup objects like Storyboard and ParallelTimeline have 
            a Duration of "Automatic". A TimelineGroup's automatic duration encompasses its 
            last-ending child. In this example, there is only one child of the Storyboard, the
            ParallelTimeline, so when the ParallelTimeline ends, the Storyboard duration will
            automatically end. -->
            <Storyboard>

              <!-- This ParallelTimeline has overriden its default duration of "Automatic" with
              a finite duration of half a second. This will force this Timeline to end after half a
              second even though its child Timelines have a longer duration (2 and 4 seconds respectively). 
              This cuts off the animation prematurely and the rectangle's fill will not go all the way to 
              yellow nor will the rectangle width get all the way to 300. Again, the default duration of a
              ParallelTimeline is "Automatic" so if you remove the finite duration, the ParallelTimeline
              will wait for its child timelines to end before it ends. -->

              <!-- Note: To specify a finite time in XAML, use the syntax of "days:hours:seconds". As mentioned,
              this ParallelTimeline has a duration of half a second. -->
              <ParallelTimeline Duration="0:0:0.5">

                <!-- For Animation Timelines like DoubleAnimation, the duration is one factor that
                determines the rate at which an animation appears to progress. For example, the DoubleAnimation
                below that animates the rectangle height will complete in only one second while the animation
                that animates the width willwill complete in 2 seconds which is relatively fast compared to the DoubleAnimation
                which animates the rectangle width over 4 seconds. -->
                <DoubleAnimation
                  Storyboard.TargetName="myRectangle"
                  Storyboard.TargetProperty="Height"
                  To="300" Duration="0:0:1" />

                <DoubleAnimation
                  Storyboard.TargetName="myRectangle"
                  Storyboard.TargetProperty="Width"
                  To="300" Duration="0:0:4" />

                <ColorAnimation
                  Storyboard.TargetName="MyAnimatedBrush"
                  Storyboard.TargetProperty="Color"
                  To="Yellow" Duration="0:0:2" />

              </ParallelTimeline>
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>

      </Rectangle.Triggers>
    </Rectangle>
  </StackPanel>
</Page>





How to: Set a Property After Animating It with a Storyboard


In some cases, it might appear that you can't change the value of a property after it has been animated.

Example

In the following example, a Storyboard is used to animate the color of a SolidColorBrush. The storyboard is triggered when the button is clicked. The Completed event is handled so that the program is notified when the ColorAnimation completes.

<Button
  Content="Animate and Then Set Example 1">
  <Button.Background>
    <SolidColorBrush x:Name="Button1BackgroundBrush"
      Color="Red" />
  </Button.Background>
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
      <BeginStoryboard>
        <Storyboard>
          <ColorAnimation
            Storyboard.TargetName="Button1BackgroundBrush"
            Storyboard.TargetProperty="Color"
            From="Red" To="Yellow" Duration="0:0:5"
            FillBehavior="HoldEnd"
            Completed="setButton1BackgroundBrushColor" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

Example

After the ColorAnimation completes, the program attempts to change the brush's color to blue.

private void setButton1BackgroundBrushColor(object sender, EventArgs e)
{

    // Does not appear to have any effect:
    // the brush remains yellow.
    Button1BackgroundBrush.Color = Colors.Blue;
}

The previous code doesn't appear to do anything: the brush remains yellow, which is the value supplied by the ColorAnimation that animated the brush. The underlying property value (the base value) is actually changed to blue. However, the effective, or current, value remains yellow because the ColorAnimation is still overriding the base value. If you want the base value to become the effective value again, you must stop the animation from influencing the property. There are three ways to do this with storyboard animations:

  • Set the animation's FillBehavior property to Stop 

  • Remove the entire Storyboard.

  • Remove the animation from the individual property.

Set the animation's FillBehavior property to Stop

By setting FillBehavior to Stop, you tell the animation to stop affecting its target property after it reaches the end of its active period.

<Button
  Content="Animate and Then Set Example 2">
  <Button.Background>
    <SolidColorBrush x:Name="Button2BackgroundBrush"
      Color="Red" />
  </Button.Background>
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
      <BeginStoryboard>
        <Storyboard>
          <ColorAnimation
            Storyboard.TargetName="Button2BackgroundBrush"
            Storyboard.TargetProperty="Color"
            From="Red" To="Yellow" Duration="0:0:5"
            FillBehavior="Stop"
            Completed="setButton2BackgroundBrushColor" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

private void setButton2BackgroundBrushColor(object sender, EventArgs e)
{

    // This appears to work:
    // the brush changes to blue.
    Button2BackgroundBrush.Color = Colors.Blue;
}

Remove the entire storyboard

By using a RemoveStoryboard trigger or the Storyboard.Remove method, you tell the storyboard animations to stop affecting their target properties. The difference between this approach and setting the FillBehavior property is that you can remove the storyboard at anytime, while the FillBehavior property only has an effect when the animation reaches the end of its active period.

<Button
  Name="Button3"
  Content="Animate and Then Set Example 3">
  <Button.Background>
    <SolidColorBrush x:Name="Button3BackgroundBrush"
      Color="Red" />
  </Button.Background>
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
      <BeginStoryboard Name="MyBeginStoryboard">
        <Storyboard x:Name="MyStoryboard">
          <ColorAnimation
            Storyboard.TargetName="Button3BackgroundBrush"
            Storyboard.TargetProperty="Color"
            From="Red" To="Yellow" Duration="0:0:5"
            FillBehavior="HoldEnd"
            Completed="setButton3BackgroundBrushColor" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

private void setButton3BackgroundBrushColor(object sender, EventArgs e)
{

     // This appears to work:
    // the brush changes to blue.
    MyStoryboard.Remove(Button3);
    Button3BackgroundBrush.Color = Colors.Blue;
}    

Remove an animation from an individual property

Another technique to stop an animation from affecting a property is to use the BeginAnimation(DependencyProperty, AnimationTimeline) method of the object being animated. Specify the property being animated as the first parameter and null as the second.

<Button
  Name="Button4"
  Content="Animate and Then Set Example 4">
  <Button.Background>
    <SolidColorBrush x:Name="Button4BackgroundBrush"
      Color="Red" />
  </Button.Background>
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
      <BeginStoryboard>
        <Storyboard>
          <ColorAnimation
            Storyboard.TargetName="Button4BackgroundBrush"
            Storyboard.TargetProperty="Color"
            From="Red" To="Yellow" Duration="0:0:5"
            FillBehavior="HoldEnd"
            Completed="setButton4BackgroundBrushColor" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

private void setButton4BackgroundBrushColor(object sender, EventArgs e)
{

     // This appears to work:
    // the brush changes to blue.
    Button4BackgroundBrush.BeginAnimation(SolidColorBrush.ColorProperty, null);
    Button4BackgroundBrush.Color = Colors.Blue;
}     

This technique also works for non-storyboard animations.





How to: Simplify Animations by Using Child Timelines


This example shows how to simplify animations by using child ParallelTimeline objects. A Storyboard is a type of Timeline that provides targeting information for the timelines it contains. Use a Storyboard to provide timeline targeting information, including object and property information.

To begin an animation, use one or more ParallelTimeline objects as nested child elements of a Storyboard. These ParallelTimeline objects can contain other animations and therefore, can better encapsulate the timing sequences in complex animations. For example, if you are animating a TextBlock and several shapes in the same Storyboard, you can separate the animations for the TextBlock and the shapes, putting each into a separate ParallelTimeline. Because each ParallelTimeline has its own BeginTime and all child elements of the ParallelTimeline begin relative to this BeginTime, timing is better encapsulated.

The following example animates two pieces of text ( TextBlock objects) from within the same Storyboard. A ParallelTimeline encapsulates the animations of one of the TextBlock objects.

Performance Note: Although you can nest Storyboard timelines inside each other, ParallelTimelines are more suitable for nesting because they require less overhead. (The Storyboard class inherits from the ParallelTimeline class.)

Example

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Canvas >

    <!-- TextBlock with text "ParallelTimelines are..." that gets animated. -->
    <TextBlock Name="FirstTextBlock" Canvas.Top="30" Canvas.Left="300" FontSize="24" >
      ParallelTimelines are...
      <TextBlock.RenderTransform>
        <TransformGroup>
          <SkewTransform x:Name="FirstTextBlockSkew" CenterX="25" CenterY="25" AngleX="0" AngleY="0" />
        </TransformGroup>
      </TextBlock.RenderTransform>
    </TextBlock>

    <!-- TextBlock with text "Useful" that gets animated. -->
    <TextBlock Name="SecondTextBlock" Opacity="0" Canvas.Top="30" Canvas.Left="585" FontSize="24" >
      Useful
      <TextBlock.RenderTransform>
        <TransformGroup>
          <SkewTransform x:Name="SecondTextBlockSkew" CenterX="25" CenterY="25" AngleX="0" AngleY="0" />
          <ScaleTransform x:Name="SecondTextBlockScale" CenterX="0" CenterY="24" />
        </TransformGroup>
      </TextBlock.RenderTransform>
    </TextBlock>

    <!-- Event Trigger that controls all animations on the page. -->
    <Canvas.Triggers>
      <EventTrigger RoutedEvent="Canvas.Loaded">
        <BeginStoryboard>
          <Storyboard>

            <!-- "ParallelTimelines are..." fades into view. -->
            <DoubleAnimation Storyboard.TargetName="FirstTextBlock"
            Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="0" To="1" />

            <!-- "ParallelTimelines are..." skews to the left. -->
            <DoubleAnimation Storyboard.TargetName="FirstTextBlockSkew"
            Storyboard.TargetProperty="AngleX" Duration="0:0:1" BeginTime="0:0:2" From="0" To="45" />

            <!-- This ParallelTimeline contains all the animations for the TextBlock with the text
            "Useful" in it. This ParallelTimeline begins 4 seconds after the Storyboard timeline begins and all child
            animations begin relative to this parent timeline. -->
            <ParallelTimeline BeginTime="0:0:4">

              <!-- "Useful" fades into view. -->
              <DoubleAnimation Storyboard.TargetName="SecondTextBlock"
              Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="0" To="1" />

              <!-- "Useful" slides in from the right. -->
              <DoubleAnimation Storyboard.TargetName="SecondTextBlockSkew"
              Storyboard.TargetProperty="AngleX" Duration="0:0:2" From="90" To="180" />

              <!-- "Useful" skews to the right. -->
              <DoubleAnimation Storyboard.TargetName="SecondTextBlockSkew"
              Storyboard.TargetProperty="AngleX" BeginTime="0:0:3" Duration="0:0:0.2" From="0" To="-60" />

              <!-- "Useful" Gets taller. -->
              <DoubleAnimation Storyboard.TargetName="SecondTextBlockScale"
              Storyboard.TargetProperty="ScaleY" BeginTime="0:0:3" Duration="0:0:0.2" From="1" To="3" />
            </ParallelTimeline>
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger>
    </Canvas.Triggers>
  </Canvas>
</Page>





How to: Specify HandoffBehavior Between Storyboard Animations


This example shows how to specify handoff behavior between storyboard animations. The HandoffBehavior property of BeginStoryboard specifies how new animations interact with any existing ones that are already applied to a property.

Example

The following example creates two buttons that enlarge when the mouse cursor moves over them and become smaller when the cursor moves away. If you mouse over a button and then quickly remove the cursor, the second animation will be applied before the first one is finished. It is when two animations overlap like this that you can see the difference between the HandoffBehavior values of Compose and SnapshotAndReplace. A value of Compose combines the overlapping animations causing a smoother transition between animations while a value of SnapshotAndReplace causes the new animation to immediately replace the earlier overlapping animation.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Page.Resources>
    <!-- This Style specifies mouseover and mouseout behaviors. The button gets larger when
    the cursor moves over it and smaller when the cursor moves away. Note that the same Properties
    (ScaleX and ScaleY) are being targeted by both animations. The BeginStoryboard for each animation
    uses a HandoffBehavior of "Compose" which causes the old animation to interpolate more gradually into
    the new one. -->
    <Style x:Key="ButtonWithCompose" TargetType="{x:Type Button}">
      <Setter Property="Button.RenderTransform">
        <Setter.Value>
          <ScaleTransform CenterX="50" CenterY="50" ScaleX="1" ScaleY="1" />
        </Setter.Value>
      </Setter>
      <Style.Triggers>
        <EventTrigger RoutedEvent="Mouse.MouseEnter">
          <EventTrigger.Actions>
            <BeginStoryboard >
              <Storyboard>
                <DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleX" To="3"  />
                <DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleY" To="3"  />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger.Actions>
        </EventTrigger>
        <EventTrigger RoutedEvent="Mouse.MouseLeave">
          <EventTrigger.Actions>
            <BeginStoryboard HandoffBehavior="Compose">
              <Storyboard>
                <DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleX" />
                <DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleY" />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger.Actions>
        </EventTrigger>
      </Style.Triggers>
    </Style>
    <!-- For this button style, BeginStoryboard uses the default HandoffBehavior of "SnapShotAndReplace" -->
    <Style x:Key="ButtonWithSnapShotAndReplace" TargetType="{x:Type Button}">
      <Setter Property="Button.RenderTransform">
        <Setter.Value>
          <ScaleTransform CenterX="50" CenterY="50" ScaleX="1" ScaleY="1" />
        </Setter.Value>
      </Setter>
      <Style.Triggers>
        <EventTrigger RoutedEvent="Mouse.MouseEnter">
          <EventTrigger.Actions>
            <BeginStoryboard >
              <Storyboard>
                <DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleX" To="3"  />
                <DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleY" To="3"  />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger.Actions>
        </EventTrigger>
        <EventTrigger RoutedEvent="Mouse.MouseLeave">
          <EventTrigger.Actions>
            <BeginStoryboard>
              <Storyboard>
                <DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleX" />
                <DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleY" />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger.Actions>
        </EventTrigger>
      </Style.Triggers>
    </Style>
  </Page.Resources>
  <Canvas>
    <Button Style="{StaticResource ButtonWithSnapShotAndReplace}" Canvas.Top="200" Canvas.Left="200" Width="100" Height="100">
      SnapShotAndReplace
    </Button>
    <Button Style="{StaticResource ButtonWithCompose}" Canvas.Top="200" Canvas.Left="400" Width="100" Height="100">
      Compose
    </Button>
  </Canvas>
</Page>





How to: Specify the FillBehavior for a Timeline that has Reached the End of Its Active Period


This example shows how to specify the FillBehavior for the inactive Timeline of an animated property.

Example

The FillBehavior property of a Timeline determines what happens to the value of an animated property when it is not being animated, that is, when the Timeline is inactive but its parent Timeline is inside its active or hold period. For example, does an animated property remain at its end value after the animation ends or does it revert back to the value it had before the animation started?

The following example uses a DoubleAnimation to animate the Width of two rectangles. Each rectangle uses a different Timeline object.

One Timeline has a FillBehavior that is set to Stop, which causes the width of the rectangle to revert back to its non-animated value when the Timeline ends. The other Timeline has a FillBehavior of HoldEnd, which causes the width to remain at its end value when the Timeline ends.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
  <StackPanel Margin="20">
    <Border Background="#99FFFFFF">
      <TextBlock Margin="20">
              This example shows how the FillBehavior property determines how an animation behaves
              after it reaches the end of its duration.
      </TextBlock>
    </Border>

    <TextBlock>FillBehavior="Deactivate"</TextBlock>
    <Rectangle Name="deactiveAnimationRectangle" Width="20" Height="20" Fill="#AA3333FF" HorizontalAlignment="Left" >
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.Loaded">
          <BeginStoryboard>
            <Storyboard>

              <!-- The animated rectangle's width reverts back to its non-animated value
                   after the animation ends. -->
              <DoubleAnimation 
                Storyboard.TargetName="deactiveAnimationRectangle" 
                Storyboard.TargetProperty="Width" 
                From="100" To="400" Duration="0:0:2" FillBehavior="Stop" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers>
    </Rectangle>

    <TextBlock Margin="0,20,0,0">FillBehavior="HoldEnd" </TextBlock>
    <Rectangle Name="holdEndAnimationRectangle" Width="20" Height="20" Fill="#AA3333FF" HorizontalAlignment="Left" >
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.Loaded">
          <BeginStoryboard>
            <Storyboard>

              <!-- The animated rectangle's width remains at its end value after the 
                   animation ends. -->
              <DoubleAnimation Storyboard.TargetName="holdEndAnimationRectangle" 
                Storyboard.TargetProperty="Width"  
                From="100" To="400" Duration="0:0:2" FillBehavior="HoldEnd" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers>
    </Rectangle>
  </StackPanel>
</Page>

For the complete sample, see Animation Example Gallery.





How to: Specify Whether a Timeline Automatically Reverses


A timeline's AutoReverse property determines whether it plays in reverse after it completes a forward iteration. The following example shows several animations with identical duration and target values, but with different AutoReverse settings. To demonstrate how the AutoReverse property behaves with different RepeatBehavior settings, some animations are set to repeat. The last animation shows how the AutoReverse property works on nested timelines.

Example

<!-- AutoReverseExample.xaml
     This example shows how to use the AutoReverse property to make a timeline 
     play backwards at the end of each iteration. 
     Several rectangles are animated by DoubleAnimations with 
     identical durations and target values, but with different
     AutoReverse and RepeatBehavior settings.-->

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  WindowTitle="AutoReverse Example">
  <StackPanel Margin="20">

    <!-- Create some rectangles to animate. -->
    <Rectangle Name="withoutAutoReverseRectangle"
      Width="100" Height="20" Fill="Blue" />  

    <Rectangle Name="autoReverseRectangle"
      Width="100" Height="20" Fill="Blue" />

    <Rectangle Name="autoReverseRectangleWithRepeats"
      Width="100" Height="20" Fill="Blue" />

    <Rectangle Name="complexAutoReverseExample"
      Width="100" Height="20" Fill="Blue"  />

    <!-- Use a button to restart the animations. -->
    <Button Margin="30" Content="Start Animations">
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard>
            <Storyboard>

              <!-- Create an animation that does not automatically play in reverse.
                   This animation plays for a total of 2 seconds. -->
              <DoubleAnimation 
                Storyboard.TargetName="withoutAutoReverseRectangle" 
                Storyboard.TargetProperty="Width" 
                Duration="0:0:2" From="100" To="400" AutoReverse="False" />   

              <!-- Create an animation that automatically reverses at the end of each iteration.
                   This animation plays for a total of 4 seconds. -->
              <DoubleAnimation Storyboard.TargetName="autoReverseRectangle" 
                Storyboard.TargetProperty="Width"
                Duration="0:0:2" From="100" To="400" AutoReverse="True" />

              <!-- Create an animation that automatically reverses at the end of each iteration.
                   Set the animation to repeat twice. As a result, then animation plays forward,
                   the backward, then forward, and then backward again. 
                   This animation plays for a total of 8 seconds. -->
              <DoubleAnimation Storyboard.TargetName="autoReverseRectangleWithRepeats" 
                Storyboard.TargetProperty="Width"
                Duration="0:0:2" From="100" To="400" AutoReverse="True" RepeatBehavior="2x" />  

              <!-- Set the parent timeline's AutoReverse property to True and set the animation's
                   RepeatBehavior to 2x. As a result, the animation plays forward twice and then
                   backwards twice. 
                   This animation plays for a total of 8 seconds. -->                
              <ParallelTimeline AutoReverse="True">
                <DoubleAnimation 
                  Storyboard.TargetName="complexAutoReverseExample" 
                  Storyboard.TargetProperty="Width"
                  Duration="0:0:2" From="100" To="400" RepeatBehavior="2x"  />  
              </ParallelTimeline>
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>
    </Button>
  </StackPanel>
</Page>





How to: Trigger an Animation When a Property Value Changes


This example shows how to use a Trigger to start a Storyboard when a property value changes. You can use a Trigger inside a StyleControlTemplate, or DataTemplate.

Example

The following example uses a Trigger to animate the Opacity of a Button when its IsMouseOver property becomes true.

<!-- PropertyTriggerExample.xaml
     Shows how to use property triggers to start animations. -->
<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  WindowTitle="Animate Properties with Storyboards">
  <Page.Resources>

    <Style x:Key="PropertyTriggerExampleButtonStyle" TargetType="{x:Type Button}">

      <Setter Property="Opacity" Value="0.25" />

      <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">

          <Trigger.EnterActions>
            <BeginStoryboard>
              <Storyboard>
                <DoubleAnimation Storyboard.TargetProperty="Opacity"
                  To="1" Duration="0:0:1" />
              </Storyboard>
            </BeginStoryboard>
          </Trigger.EnterActions>
          <Trigger.ExitActions>
            <BeginStoryboard>
              <Storyboard>
                <DoubleAnimation Storyboard.TargetProperty="Opacity"
                  To="0.25" Duration="0:0:1" />
              </Storyboard>
            </BeginStoryboard>
          </Trigger.ExitActions>          
        </Trigger>               
      </Style.Triggers>    
    </Style>
  </Page.Resources>

  <StackPanel Margin="20">

    <Button Style="{StaticResource PropertyTriggerExampleButtonStyle}">
      Move the mouse over me.
    </Button>

  </StackPanel>
</Page>

Animations applied by property Trigger objects behave in a more complex fashion than EventTrigger animations or animations started using Storyboard methods. They "handoff" with animations defined by other Trigger objects, but compose with EventTrigger and method-triggered animations.





How to: Use Event Triggers to Control a Storyboard After It Starts


This example shows how to control a Storyboard after it starts. To start a Storyboard by using XAML, use BeginStoryboard, which distributes the animations to the objects and properties they animate and then starts the storyboard. If you give BeginStoryboard a name by specifying its Name property, you make it a controllable storyboard. You can then interactively control the storyboard after it starts.

Use the following storyboard actions together with EventTrigger objects to control a storyboard.

Example

The following example uses controllable storyboard actions to interactively control a storyboard.

Note: To see an example of controlling a storyboard by using code, see How to: Control a Storyboard After It Starts.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  WindowTitle="Controlling a Storyboard" >
  <StackPanel Margin="20" >

    <!-- This rectangle is animated. -->
    <Rectangle Name="myRectangle"
      Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

    <!-- This StackPanel contains all the Buttons. -->
    <StackPanel Orientation="Horizontal" Margin="0,30,0,0">

      <Button Name="BeginButton">Begin</Button>
      <Button Name="PauseButton">Pause</Button>
      <Button Name="ResumeButton">Resume</Button>
      <Button Name="SeekButton">Seek</Button>
      <Button Name="SkipToFillButton">Skip To Fill</Button>
      <Button Name="SetSpeedRatioButton">Triple Speed</Button>
      <Button Name="StopButton">Stop</Button>

      <StackPanel.Triggers>

        <!-- Begin the Storyboard -->
        <EventTrigger RoutedEvent="Button.Click" SourceName="BeginButton">
          <BeginStoryboard Name="MyBeginStoryboard">
            <Storyboard >
              <DoubleAnimation 
                Storyboard.TargetName="myRectangle" 
                Storyboard.TargetProperty="Width" 
                Duration="0:0:5" From="100" To="500" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>

        <!-- Pause the Storyboard -->
        <EventTrigger RoutedEvent="Button.Click" SourceName="PauseButton">
          <PauseStoryboard BeginStoryboardName="MyBeginStoryboard" />
        </EventTrigger>

        <!-- Resume the Storyboard -->
        <EventTrigger RoutedEvent="Button.Click" SourceName="ResumeButton">
          <ResumeStoryboard BeginStoryboardName="MyBeginStoryboard" />
        </EventTrigger>

         <!-- Seek one second into the storyboard's active period. -->
         <EventTrigger RoutedEvent="Button.Click" SourceName="SeekButton">
           <SeekStoryboard 
            BeginStoryboardName="MyBeginStoryboard" 
            Offset="0:0:1" Origin="BeginTime" />
        </EventTrigger>   

        <!-- Skip to Fill -->
        <EventTrigger RoutedEvent="Button.Click" SourceName="SkipToFillButton">
          <SkipStoryboardToFill BeginStoryboardName="MyBeginStoryboard" />
        </EventTrigger>

        <!-- Stop the Storyboard -->
        <EventTrigger RoutedEvent="Button.Click" SourceName="StopButton">
          <StopStoryboard BeginStoryboardName="MyBeginStoryboard" />
        </EventTrigger>

        <!-- Triple the speed of the Storyboard -->
        <EventTrigger RoutedEvent="Button.Click" SourceName="SetSpeedRatioButton">
          <SetStoryboardSpeedRatio SpeedRatio="3" BeginStoryboardName="MyBeginStoryboard" />
        </EventTrigger>
      </StackPanel.Triggers>
    </StackPanel>
  </StackPanel>
</Page>

For additional examples, see the Animation Example Gallery.







Clocks How-to Topics










Key-Frame How-to Topics





Path Animation How-to Topics

























'프로그래밍 > WPF' 카테고리의 다른 글

Graphics and Multimedia - Multimedia, Visual Layer  (0) 2017.01.14
Data Binding  (0) 2017.01.10
Graphics and Multimedia  (0) 2016.11.24
Documents  (0) 2016.11.19
Control Library 3  (0) 2016.11.18
:
Posted by 지훈2
2017. 1. 4. 20:56

클래스 종류 헤드라인 프로그래밍/C#2017. 1. 4. 20:56


  1. Array Class
  2. Enum Class
  3. GC Class
  4. Enumerable Class
  5. IEnumerable<T> Interface



Array Class


https://msdn.microsoft.com/en-us/library/system.array.aspx



Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the base class for all arrays in the common language runtime.

To browse the .NET Framework source code for this type, see the Reference Source.

Namespace:   System
Assembly:  mscorlib (in mscorlib.dll)


Syntax

[SerializableAttribute]
[ComVisibleAttribute(true)]
public abstract class Array : ICloneable, IList, ICollection, 
	IEnumerable, IStructuralComparable, IStructuralEquatable

Properties

NameDescription
System_CAPS_pubpropertyIsFixedSize

Gets a value indicating whether the Array has a fixed size.

System_CAPS_pubpropertyIsReadOnly

Gets a value indicating whether the Array is read-only.

System_CAPS_pubpropertyIsSynchronized

Gets a value indicating whether access to the Array is synchronized (thread safe).

System_CAPS_pubpropertyLength

Gets the total number of elements in all the dimensions of the Array.

System_CAPS_pubpropertyLongLength

Gets a 64-bit integer that represents the total number of elements in all the dimensions of the Array.

System_CAPS_pubpropertyRank

Gets the rank (number of dimensions) of the Array. For example, a one-dimensional array returns 1, a two-dimensional array returns 2, and so on.

System_CAPS_pubpropertySyncRoot

Gets an object that can be used to synchronize access to the Array.

Methods

NameDescription
System_CAPS_pubmethodSystem_CAPS_staticAsReadOnly<T>(T[])

Returns a read-only wrapper for the specified array.

System_CAPS_pubmethodSystem_CAPS_staticBinarySearch(Array, Int32, Int32, Object)

Searches a range of elements in a one-dimensional sorted array for a value, using the IComparable interface implemented by each element of the array and by the specified value.

System_CAPS_pubmethodSystem_CAPS_staticBinarySearch(Array, Int32, Int32, Object, IComparer)

Searches a range of elements in a one-dimensional sorted array for a value, using the specified IComparer interface.

System_CAPS_pubmethodSystem_CAPS_staticBinarySearch(Array, Object)

Searches an entire one-dimensional sorted array for a specific element, using the IComparable interface implemented by each element of the array and by the specified object.

System_CAPS_pubmethodSystem_CAPS_staticBinarySearch(Array, Object, IComparer)

Searches an entire one-dimensional sorted array for a value using the specified IComparer interface.

System_CAPS_pubmethodSystem_CAPS_staticBinarySearch<T>(T[], T)

Searches an entire one-dimensional sorted array for a specific element, using the IComparable<T> generic interface implemented by each element of the Array and by the specified object.

System_CAPS_pubmethodSystem_CAPS_staticBinarySearch<T>(T[], T, IComparer<T>)

Searches an entire one-dimensional sorted array for a value using the specified IComparer<T> generic interface.

System_CAPS_pubmethodSystem_CAPS_staticBinarySearch<T>(T[], Int32, Int32, T)

Searches a range of elements in a one-dimensional sorted array for a value, using the IComparable<T> generic interface implemented by each element of the Array and by the specified value.

System_CAPS_pubmethodSystem_CAPS_staticBinarySearch<T>(T[], Int32, Int32, T, IComparer<T>)

Searches a range of elements in a one-dimensional sorted array for a value, using the specified IComparer<T> generic interface.

System_CAPS_pubmethodSystem_CAPS_staticClear(Array, Int32, Int32)

Sets a range of elements in an array to the default value of each element type.

System_CAPS_pubmethodClone()

Creates a shallow copy of the Array.

System_CAPS_pubmethodSystem_CAPS_staticConstrainedCopy(Array, Int32, Array, Int32, Int32)

Copies a range of elements from an Array starting at the specified source index and pastes them to another Array starting at the specified destination index. Guarantees that all changes are undone if the copy does not succeed completely.

System_CAPS_pubmethodSystem_CAPS_staticConvertAll<TInput, TOutput>(TInput[], Converter<TInput, TOutput>)

Converts an array of one type to an array of another type.

System_CAPS_pubmethodSystem_CAPS_staticCopy(Array, Array, Int32)

Copies a range of elements from an Array starting at the first element and pastes them into another Array starting at the first element. The length is specified as a 32-bit integer.

System_CAPS_pubmethodSystem_CAPS_staticCopy(Array, Array, Int64)

Copies a range of elements from an Array starting at the first element and pastes them into another Array starting at the first element. The length is specified as a 64-bit integer.

System_CAPS_pubmethodSystem_CAPS_staticCopy(Array, Int32, Array, Int32, Int32)

Copies a range of elements from an Array starting at the specified source index and pastes them to another Array starting at the specified destination index. The length and the indexes are specified as 32-bit integers.

System_CAPS_pubmethodSystem_CAPS_staticCopy(Array, Int64, Array, Int64, Int64)

Copies a range of elements from an Array starting at the specified source index and pastes them to another Array starting at the specified destination index. The length and the indexes are specified as 64-bit integers.

System_CAPS_pubmethodCopyTo(Array, Int32)

Copies all the elements of the current one-dimensional array to the specified one-dimensional array starting at the specified destination array index. The index is specified as a 32-bit integer.

System_CAPS_pubmethodCopyTo(Array, Int64)

Copies all the elements of the current one-dimensional array to the specified one-dimensional array starting at the specified destination array index. The index is specified as a 64-bit integer.

System_CAPS_pubmethodSystem_CAPS_staticCreateInstance(Type, Int32)

Creates a one-dimensional Array of the specified Type and length, with zero-based indexing.

System_CAPS_pubmethodSystem_CAPS_staticCreateInstance(Type, Int32, Int32)

Creates a two-dimensional Array of the specified Type and dimension lengths, with zero-based indexing.

System_CAPS_pubmethodSystem_CAPS_staticCreateInstance(Type, Int32, Int32, Int32)

Creates a three-dimensional Array of the specified Type and dimension lengths, with zero-based indexing.

System_CAPS_pubmethodSystem_CAPS_staticCreateInstance(Type, Int32[])

Creates a multidimensional Array of the specified Type and dimension lengths, with zero-based indexing. The dimension lengths are specified in an array of 32-bit integers.

System_CAPS_pubmethodSystem_CAPS_staticCreateInstance(Type, Int32[], Int32[])

Creates a multidimensional Array of the specified Type and dimension lengths, with the specified lower bounds.

System_CAPS_pubmethodSystem_CAPS_staticCreateInstance(Type, Int64[])

Creates a multidimensional Array of the specified Type and dimension lengths, with zero-based indexing. The dimension lengths are specified in an array of 64-bit integers.

System_CAPS_pubmethodSystem_CAPS_staticEmpty<T>()

Returns an empty array.

System_CAPS_pubmethodEquals(Object)

Determines whether the specified object is equal to the current object.(Inherited from Object.)

System_CAPS_pubmethodSystem_CAPS_staticExists<T>(T[], Predicate<T>)

Determines whether the specified array contains elements that match the conditions defined by the specified predicate.

System_CAPS_protmethodFinalize()

Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.(Inherited from Object.)

System_CAPS_pubmethodSystem_CAPS_staticFind<T>(T[], Predicate<T>)

Searches for an element that matches the conditions defined by the specified predicate, and returns the first occurrence within the entire Array.

System_CAPS_pubmethodSystem_CAPS_staticFindAll<T>(T[], Predicate<T>)

Retrieves all the elements that match the conditions defined by the specified predicate.

System_CAPS_pubmethodSystem_CAPS_staticFindIndex<T>(T[], Int32, Int32, Predicate<T>)

Searches for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the first occurrence within the range of elements in the Array that starts at the specified index and contains the specified number of elements.

System_CAPS_pubmethodSystem_CAPS_staticFindIndex<T>(T[], Int32, Predicate<T>)

Searches for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the first occurrence within the range of elements in the Array that extends from the specified index to the last element.

System_CAPS_pubmethodSystem_CAPS_staticFindIndex<T>(T[], Predicate<T>)

Searches for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the first occurrence within the entire Array.

System_CAPS_pubmethodSystem_CAPS_staticFindLast<T>(T[], Predicate<T>)

Searches for an element that matches the conditions defined by the specified predicate, and returns the last occurrence within the entire Array.

System_CAPS_pubmethodSystem_CAPS_staticFindLastIndex<T>(T[], Int32, Int32, Predicate<T>)

Searches for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the last occurrence within the range of elements in the Array that contains the specified number of elements and ends at the specified index.

System_CAPS_pubmethodSystem_CAPS_staticFindLastIndex<T>(T[], Int32, Predicate<T>)

Searches for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the last occurrence within the range of elements in the Array that extends from the first element to the specified index.

System_CAPS_pubmethodSystem_CAPS_staticFindLastIndex<T>(T[], Predicate<T>)

Searches for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the last occurrence within the entire Array.

System_CAPS_pubmethodSystem_CAPS_staticForEach<T>(T[], Action<T>)

Performs the specified action on each element of the specified array.

System_CAPS_pubmethodGetEnumerator()

Returns an IEnumerator for the Array.

System_CAPS_pubmethodGetHashCode()

Serves as the default hash function. (Inherited from Object.)

System_CAPS_pubmethodGetLength(Int32)

Gets a 32-bit integer that represents the number of elements in the specified dimension of the Array.

System_CAPS_pubmethodGetLongLength(Int32)

Gets a 64-bit integer that represents the number of elements in the specified dimension of the Array.

System_CAPS_pubmethodGetLowerBound(Int32)

Gets the index of the first element of the specified dimension in the array.

System_CAPS_pubmethodGetType()

Gets the Type of the current instance.(Inherited from Object.)

System_CAPS_pubmethodGetUpperBound(Int32)

Gets the index of the last element of the specified dimension in the array.

System_CAPS_pubmethodGetValue(Int32)

Gets the value at the specified position in the one-dimensional Array. The index is specified as a 32-bit integer.

System_CAPS_pubmethodGetValue(Int32, Int32)

Gets the value at the specified position in the two-dimensional Array. The indexes are specified as 32-bit integers.

System_CAPS_pubmethodGetValue(Int32, Int32, Int32)

Gets the value at the specified position in the three-dimensional Array. The indexes are specified as 32-bit integers.

System_CAPS_pubmethodGetValue(Int32[])

Gets the value at the specified position in the multidimensional Array. The indexes are specified as an array of 32-bit integers.

System_CAPS_pubmethodGetValue(Int64)

Gets the value at the specified position in the one-dimensional Array. The index is specified as a 64-bit integer.

System_CAPS_pubmethodGetValue(Int64, Int64)

Gets the value at the specified position in the two-dimensional Array. The indexes are specified as 64-bit integers.

System_CAPS_pubmethodGetValue(Int64, Int64, Int64)

Gets the value at the specified position in the three-dimensional Array. The indexes are specified as 64-bit integers.

System_CAPS_pubmethodGetValue(Int64[])

Gets the value at the specified position in the multidimensional Array. The indexes are specified as an array of 64-bit integers.

System_CAPS_pubmethodSystem_CAPS_staticIndexOf(Array, Object)

Searches for the specified object and returns the index of its first occurrence in a one-dimensional array.

System_CAPS_pubmethodSystem_CAPS_staticIndexOf(Array, Object, Int32)

Searches for the specified object in a range of elements of a one-dimensional array, and returns the index of its first occurrence. The range extends from a specified index to the end of the array.

System_CAPS_pubmethodSystem_CAPS_staticIndexOf(Array, Object, Int32, Int32)

Searches for the specified object in a range of elements of a one-dimensional array, and returns the index of ifs first occurrence. The range extends from a specified index for a specified number of elements.

System_CAPS_pubmethodSystem_CAPS_staticIndexOf<T>(T[], T)

Searches for the specified object and returns the index of its first occurrence in a one-dimensional array.

System_CAPS_pubmethodSystem_CAPS_staticIndexOf<T>(T[], T, Int32)

Searches for the specified object in a range of elements of a one dimensional array, and returns the index of its first occurrence. The range extends from a specified index to the end of the array.

System_CAPS_pubmethodSystem_CAPS_staticIndexOf<T>(T[], T, Int32, Int32)

Searches for the specified object in a range of elements of a one-dimensional array, and returns the index of its first occurrence. The range extends from a specified index for a specified number of elements.

System_CAPS_pubmethodInitialize()

Initializes every element of the value-type Array by calling the default constructor of the value type.

System_CAPS_pubmethodSystem_CAPS_staticLastIndexOf(Array, Object)

Searches for the specified object and returns the index of the last occurrence within the entire one-dimensional Array.

System_CAPS_pubmethodSystem_CAPS_staticLastIndexOf(Array, Object, Int32)

Searches for the specified object and returns the index of the last occurrence within the range of elements in the one-dimensional Array that extends from the first element to the specified index.

System_CAPS_pubmethodSystem_CAPS_staticLastIndexOf(Array, Object, Int32, Int32)

Searches for the specified object and returns the index of the last occurrence within the range of elements in the one-dimensional Array that contains the specified number of elements and ends at the specified index.

System_CAPS_pubmethodSystem_CAPS_staticLastIndexOf<T>(T[], T)

Searches for the specified object and returns the index of the last occurrence within the entire Array.

System_CAPS_pubmethodSystem_CAPS_staticLastIndexOf<T>(T[], T, Int32)

Searches for the specified object and returns the index of the last occurrence within the range of elements in the Array that extends from the first element to the specified index.

System_CAPS_pubmethodSystem_CAPS_staticLastIndexOf<T>(T[], T, Int32, Int32)

Searches for the specified object and returns the index of the last occurrence within the range of elements in the Array that contains the specified number of elements and ends at the specified index.

System_CAPS_protmethodMemberwiseClone()

Creates a shallow copy of the current Object.(Inherited from Object.)

System_CAPS_pubmethodSystem_CAPS_staticResize<T>(T[], Int32)

Changes the number of elements of a one-dimensional array to the specified new size.

System_CAPS_pubmethodSystem_CAPS_staticReverse(Array)

Reverses the sequence of the elements in the entire one-dimensional Array.

System_CAPS_pubmethodSystem_CAPS_staticReverse(Array, Int32, Int32)

Reverses the sequence of the elements in a range of elements in the one-dimensional Array.

System_CAPS_pubmethodSetValue(Object, Int32)

Sets a value to the element at the specified position in the one-dimensional Array. The index is specified as a 32-bit integer.

System_CAPS_pubmethodSetValue(Object, Int32, Int32)

Sets a value to the element at the specified position in the two-dimensional Array. The indexes are specified as 32-bit integers.

System_CAPS_pubmethodSetValue(Object, Int32, Int32, Int32)

Sets a value to the element at the specified position in the three-dimensional Array. The indexes are specified as 32-bit integers.

System_CAPS_pubmethodSetValue(Object, Int32[])

Sets a value to the element at the specified position in the multidimensional Array. The indexes are specified as an array of 32-bit integers.

System_CAPS_pubmethodSetValue(Object, Int64)

Sets a value to the element at the specified position in the one-dimensional Array. The index is specified as a 64-bit integer.

System_CAPS_pubmethodSetValue(Object, Int64, Int64)

Sets a value to the element at the specified position in the two-dimensional Array. The indexes are specified as 64-bit integers.

System_CAPS_pubmethodSetValue(Object, Int64, Int64, Int64)

Sets a value to the element at the specified position in the three-dimensional Array. The indexes are specified as 64-bit integers.

System_CAPS_pubmethodSetValue(Object, Int64[])

Sets a value to the element at the specified position in the multidimensional Array. The indexes are specified as an array of 64-bit integers.

System_CAPS_pubmethodSystem_CAPS_staticSort(Array)

Sorts the elements in an entire one-dimensional Array using the IComparable implementation of each element of the Array.

System_CAPS_pubmethodSystem_CAPS_staticSort(Array, Array)

Sorts a pair of one-dimensional Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the IComparable implementation of each key.

System_CAPS_pubmethodSystem_CAPS_staticSort(Array, Array, IComparer)

Sorts a pair of one-dimensional Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the specified IComparer.

System_CAPS_pubmethodSystem_CAPS_staticSort(Array, Array, Int32, Int32)

Sorts a range of elements in a pair of one-dimensional Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the IComparable implementation of each key.

System_CAPS_pubmethodSystem_CAPS_staticSort(Array, Array, Int32, Int32, IComparer)

Sorts a range of elements in a pair of one-dimensional Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the specified IComparer.

System_CAPS_pubmethodSystem_CAPS_staticSort(Array, IComparer)

Sorts the elements in a one-dimensional Array using the specified IComparer.

System_CAPS_pubmethodSystem_CAPS_staticSort(Array, Int32, Int32)

Sorts the elements in a range of elements in a one-dimensional Array using the IComparable implementation of each element of the Array.

System_CAPS_pubmethodSystem_CAPS_staticSort(Array, Int32, Int32, IComparer)

Sorts the elements in a range of elements in a one-dimensional Array using the specified IComparer.

System_CAPS_pubmethodSystem_CAPS_staticSort<T>(T[])

Sorts the elements in an entire Array using the IComparable<T> generic interface implementation of each element of the Array.

System_CAPS_pubmethodSystem_CAPS_staticSort<T>(T[], Comparison<T>)

Sorts the elements in an Array using the specified Comparison<T>.

System_CAPS_pubmethodSystem_CAPS_staticSort<T>(T[], IComparer<T>)

Sorts the elements in an Array using the specified IComparer<T> generic interface.

System_CAPS_pubmethodSystem_CAPS_staticSort<T>(T[], Int32, Int32)

Sorts the elements in a range of elements in an Array using the IComparable<T> generic interface implementation of each element of the Array.

System_CAPS_pubmethodSystem_CAPS_staticSort<T>(T[], Int32, Int32, IComparer<T>)

Sorts the elements in a range of elements in an Array using the specified IComparer<T> generic interface.

System_CAPS_pubmethodSystem_CAPS_staticSort<TKey, TValue>(TKey[], TValue[])

Sorts a pair of Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the IComparable<T> generic interface implementation of each key.

System_CAPS_pubmethodSystem_CAPS_staticSort<TKey, TValue>(TKey[], TValue[], IComparer<TKey>)

Sorts a pair of Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the specified IComparer<T> generic interface.

System_CAPS_pubmethodSystem_CAPS_staticSort<TKey, TValue>(TKey[], TValue[], Int32, Int32)

Sorts a range of elements in a pair of Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the IComparable<T> generic interface implementation of each key.

System_CAPS_pubmethodSystem_CAPS_staticSort<TKey, TValue>(TKey[], TValue[], Int32, Int32, IComparer<TKey>)

Sorts a range of elements in a pair of Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the specified IComparer<T> generic interface.

System_CAPS_pubmethodToString()

Returns a string that represents the current object.(Inherited from Object.)

System_CAPS_pubmethodSystem_CAPS_staticTrueForAll<T>(T[], Predicate<T>)

Determines whether every element in the array matches the conditions defined by the specified predicate.

Explicit Interface Implementations

NameDescription
System_CAPS_pubinterfaceSystem_CAPS_privmethodIList.Add(Object)

Calling this method always throws a NotSupportedException exception.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIList.Clear()

Removes all items from the IList.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIList.Contains(Object)

Determines whether an element is in the IList.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIList.IndexOf(Object)

Determines the index of a specific item in the IList.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIList.Insert(Int32, Object)

Inserts an item to the IList at the specified index.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIList.Remove(Object)

Removes the first occurrence of a specific object from the IList.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIList.RemoveAt(Int32)

Removes the IList item at the specified index.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIStructuralComparable.CompareTo(Object, IComparer)

Determines whether the current collection object precedes, occurs in the same position as, or follows another object in the sort order.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIStructuralEquatable.Equals(Object, IEqualityComparer)

Determines whether an object is equal to the current instance.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIStructuralEquatable.GetHashCode(IEqualityComparer)

Returns a hash code for the current instance.

System_CAPS_pubinterfaceSystem_CAPS_privpropertyICollection.Count

Gets the number of elements contained in the Array.

System_CAPS_pubinterfaceSystem_CAPS_privpropertyIList.Item[Int32]

Gets or sets the element at the specified index.

Extension Methods

NameDescription
System_CAPS_pubmethodAsParallel()

Overloaded. Enables parallelization of a query.(Defined by ParallelEnumerable.)

System_CAPS_pubmethodAsQueryable()

Overloaded. Converts an IEnumerable to an IQueryable.(Defined by Queryable.)

System_CAPS_pubmethodCast<TResult>()

Casts the elements of an IEnumerable to the specified type.(Defined by Enumerable.)

System_CAPS_pubmethodOfType<TResult>()

Filters the elements of an IEnumerable based on a specified type.(Defined by Enumerable.)





Enum Class


https://msdn.microsoft.com/en-us/library/system.enum(v=vs.110).aspx


Provides the base class for enumerations.

Namespace:   System
Assembly:  mscorlib (in mscorlib.dll)


Syntax

[SerializableAttribute]
[ComVisibleAttribute(true)]
public abstract class Enum : ValueType, IComparable, IFormattable, 
	IConvertible

Constructors

NameDescription
System_CAPS_protmethodEnum()

Initializes a new instance of the Enum class.

Methods

NameDescription
System_CAPS_pubmethodCompareTo(Object)

Compares this instance to a specified object and returns an indication of their relative values.

System_CAPS_pubmethodEquals(Object)

Returns a value indicating whether this instance is equal to a specified object.(Overrides ValueType.Equals(Object).)

System_CAPS_protmethodFinalize()

Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.(Inherited from Object.)

System_CAPS_pubmethodSystem_CAPS_staticFormat(Type, Object, String)

Converts the specified value of a specified enumerated type to its equivalent string representation according to the specified format.

System_CAPS_pubmethodGetHashCode()

Returns the hash code for the value of this instance.(Overrides ValueType.GetHashCode().)

System_CAPS_pubmethodSystem_CAPS_staticGetName(Type, Object)

Retrieves the name of the constant in the specified enumeration that has the specified value.

System_CAPS_pubmethodSystem_CAPS_staticGetNames(Type)

Retrieves an array of the names of the constants in a specified enumeration.

System_CAPS_pubmethodGetType()

Gets the Type of the current instance.(Inherited from Object.)

System_CAPS_pubmethodGetTypeCode()

Returns the type code of the underlying type of this enumeration member.

System_CAPS_pubmethodSystem_CAPS_staticGetUnderlyingType(Type)

Returns the underlying type of the specified enumeration.

System_CAPS_pubmethodSystem_CAPS_staticGetValues(Type)

Retrieves an array of the values of the constants in a specified enumeration.

System_CAPS_pubmethodHasFlag(Enum)

Determines whether one or more bit fields are set in the current instance.

System_CAPS_pubmethodSystem_CAPS_staticIsDefined(Type, Object)

Returns an indication whether a constant with a specified value exists in a specified enumeration.

System_CAPS_protmethodMemberwiseClone()

Creates a shallow copy of the current Object.(Inherited from Object.)

System_CAPS_pubmethodSystem_CAPS_staticParse(Type, String)

Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object.

System_CAPS_pubmethodSystem_CAPS_staticParse(Type, String, Boolean)

Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object. A parameter specifies whether the operation is case-insensitive.

System_CAPS_pubmethodSystem_CAPS_staticToObject(Type, Byte)

Converts the specified 8-bit unsigned integer to an enumeration member.

System_CAPS_pubmethodSystem_CAPS_staticToObject(Type, Int16)

Converts the specified 16-bit signed integer to an enumeration member.

System_CAPS_pubmethodSystem_CAPS_staticToObject(Type, Int32)

Converts the specified 32-bit signed integer to an enumeration member.

System_CAPS_pubmethodSystem_CAPS_staticToObject(Type, Int64)

Converts the specified 64-bit signed integer to an enumeration member.

System_CAPS_pubmethodSystem_CAPS_staticToObject(Type, Object)

Converts the specified object with an integer value to an enumeration member.

System_CAPS_pubmethodSystem_CAPS_staticToObject(Type, SByte)

Converts the specified 8-bit signed integer value to an enumeration member.

System_CAPS_pubmethodSystem_CAPS_staticToObject(Type, UInt16)

Converts the specified 16-bit unsigned integer value to an enumeration member.

System_CAPS_pubmethodSystem_CAPS_staticToObject(Type, UInt32)

Converts the specified 32-bit unsigned integer value to an enumeration member.

System_CAPS_pubmethodSystem_CAPS_staticToObject(Type, UInt64)

Converts the specified 64-bit unsigned integer value to an enumeration member.

System_CAPS_pubmethodToString()

Converts the value of this instance to its equivalent string representation.(Overrides ValueType.ToString().)

System_CAPS_pubmethodToString(IFormatProvider)

Obsolete. This method overload is obsolete; use Enum.ToString().

System_CAPS_pubmethodToString(String)

Converts the value of this instance to its equivalent string representation using the specified format.

System_CAPS_pubmethodToString(String, IFormatProvider)

Obsolete. This method overload is obsolete; use Enum.ToString(String).

System_CAPS_pubmethodSystem_CAPS_staticTryParse<TEnum>(String, TEnum)

Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object. The return value indicates whether the conversion succeeded.

System_CAPS_pubmethodSystem_CAPS_staticTryParse<TEnum>(String, Boolean, TEnum)

Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object. A parameter specifies whether the operation is case-sensitive. The return value indicates whether the conversion succeeded.

Explicit Interface Implementations

NameDescription
System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToBoolean(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a Boolean value based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToByte(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to an 8-bit unsigned integer based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToChar(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a Unicode character based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToDateTime(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a DateTime based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToDecimal(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a Decimal based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToDouble(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a double-precision floating point number based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToInt16(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a 16-bit signed integer based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToInt32(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a 32-bit signed integer based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToInt64(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a 64-bit signed integer based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToSByte(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to an 8-bit signed integer based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToSingle(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a single-precision floating-point number based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToType(Type, IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a specified type based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToUInt16(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a 16-bit unsigned integer based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToUInt32(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a 32-bit unsigned integer based on the underlying type.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToUInt64(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Converts the current value to a 64-bit unsigned integer based on the underlying type.






GC Class


https://msdn.microsoft.com/en-us/library/system.gc(v=vs.110).aspx



Controls the system garbage collector, a service that automatically reclaims unused memory.

Namespace:   System
Assembly:  mscorlib (in mscorlib.dll)


Syntax

public static class GC

Properties

NameDescription
System_CAPS_pubpropertySystem_CAPS_staticMaxGeneration

Gets the maximum number of generations that the system currently supports.

Methods

NameDescription
System_CAPS_pubmethodSystem_CAPS_staticAddMemoryPressure(Int64)

Informs the runtime of a large allocation of unmanaged memory that should be taken into account when scheduling garbage collection.

System_CAPS_pubmethodSystem_CAPS_staticCancelFullGCNotification()

Cancels the registration of a garbage collection notification.

System_CAPS_pubmethodSystem_CAPS_staticCollect()

Forces an immediate garbage collection of all generations.

System_CAPS_pubmethodSystem_CAPS_staticCollect(Int32)

Forces an immediate garbage collection from generation 0 through a specified generation.

System_CAPS_pubmethodSystem_CAPS_staticCollect(Int32, GCCollectionMode)

Forces a garbage collection from generation 0 through a specified generation, at a time specified by a GCCollectionMode value.

System_CAPS_pubmethodSystem_CAPS_staticCollect(Int32, GCCollectionMode, Boolean)

Forces a garbage collection from generation 0 through a specified generation, at a time specified by a GCCollectionMode value, with a value specifying whether the collection should be blocking.

System_CAPS_pubmethodSystem_CAPS_staticCollect(Int32, GCCollectionMode, Boolean, Boolean)

Forces a garbage collection from generation 0 through a specified generation, at a time specified by a GCCollectionMode value, with values that specify whether the collection should be blocking and compacting.

System_CAPS_pubmethodSystem_CAPS_staticCollectionCount(Int32)

Returns the number of times garbage collection has occurred for the specified generation of objects.

System_CAPS_pubmethodSystem_CAPS_staticEndNoGCRegion()

Ends the no GC region latency mode.

System_CAPS_pubmethodSystem_CAPS_staticGetGeneration(Object)

Returns the current generation number of the specified object.

System_CAPS_pubmethodSystem_CAPS_staticGetGeneration(WeakReference)

Returns the current generation number of the target of a specified weak reference.

System_CAPS_pubmethodSystem_CAPS_staticGetTotalMemory(Boolean)

Retrieves the number of bytes currently thought to be allocated. A parameter indicates whether this method can wait a short interval before returning, to allow the system to collect garbage and finalize objects.

System_CAPS_pubmethodSystem_CAPS_staticKeepAlive(Object)

References the specified object, which makes it ineligible for garbage collection from the start of the current routine to the point where this method is called.

System_CAPS_pubmethodSystem_CAPS_staticRegisterForFullGCNotification(Int32, Int32)

Specifies that a garbage collection notification should be raised when conditions favor full garbage collection and when the collection has been completed.

System_CAPS_pubmethodSystem_CAPS_staticRemoveMemoryPressure(Int64)

Informs the runtime that unmanaged memory has been released and no longer needs to be taken into account when scheduling garbage collection.

System_CAPS_pubmethodSystem_CAPS_staticReRegisterForFinalize(Object)

Requests that the system call the finalizer for the specified object for which SuppressFinalize has previously been called.

System_CAPS_pubmethodSystem_CAPS_staticSuppressFinalize(Object)

Requests that the common language runtime not call the finalizer for the specified object.

System_CAPS_pubmethodSystem_CAPS_staticTryStartNoGCRegion(Int64)

Attempts to disallow garbage collection during the execution of a critical path if a specified amount of memory is available.

System_CAPS_pubmethodSystem_CAPS_staticTryStartNoGCRegion(Int64, Boolean)

Attempts to disallow garbage collection during the execution of a critical path if a specified amount of memory is available, and controls whether the garbage collector does a full blocking garbage collection if not enough memory is initially available.

System_CAPS_pubmethodSystem_CAPS_staticTryStartNoGCRegion(Int64, Int64)

Attempts to disallow garbage collection during the execution of a critical path if a specified amount of memory is available for the large object heap and the small object heap.

System_CAPS_pubmethodSystem_CAPS_staticTryStartNoGCRegion(Int64, Int64, Boolean)

Attempts to disallow garbage collection during the execution of a critical path if a specified amount of memory is available for the large object heap and the small object heap, and controls whether the garbage collector does a full blocking garbage collection if not enough memory is initially available.

System_CAPS_pubmethodSystem_CAPS_staticWaitForFullGCApproach()

Returns the status of a registered notification for determining whether a full, blocking garbage collection by the common language runtime is imminent.

System_CAPS_pubmethodSystem_CAPS_staticWaitForFullGCApproach(Int32)

Returns, in a specified time-out period, the status of a registered notification for determining whether a full, blocking garbage collection by the common language runtime is imminent.

System_CAPS_pubmethodSystem_CAPS_staticWaitForFullGCComplete()

Returns the status of a registered notification for determining whether a full, blocking garbage collection by the common language runtime has completed.

System_CAPS_pubmethodSystem_CAPS_staticWaitForFullGCComplete(Int32)

Returns, in a specified time-out period, the status of a registered notification for determining whether a full, blocking garbage collection by common language the runtime has completed.

System_CAPS_pubmethodSystem_CAPS_staticWaitForPendingFinalizers()

Suspends the current thread until the thread that is processing the queue of finalizers has emptied that queue.





Enumerable Class


https://msdn.microsoft.com/en-us/library/system.linq.enumerable(v=vs.110).aspx


Provides a set of static (Shared in Visual Basic) methods for querying objects that implement IEnumerable<T>.

Namespace:   System.Linq
Assembly:  System.Core (in System.Core.dll)

Inheritance Hierarchy

System.Object
  System.Linq.Enumerable

Syntax

public static class Enumerable

Methods

NameDescription
System_CAPS_pubmethodSystem_CAPS_staticAggregate<TSource>(IEnumerable<TSource>, Func<TSource, TSource, TSource>)

Applies an accumulator function over a sequence.

System_CAPS_pubmethodSystem_CAPS_staticAggregate<TSource, TAccumulate>(IEnumerable<TSource>, TAccumulate, Func<TAccumulate, TSource, TAccumulate>)

Applies an accumulator function over a sequence. The specified seed value is used as the initial accumulator value.

System_CAPS_pubmethodSystem_CAPS_staticAggregate<TSource, TAccumulate, TResult>(IEnumerable<TSource>, TAccumulate, Func<TAccumulate, TSource, TAccumulate>, Func<TAccumulate, TResult>)

Applies an accumulator function over a sequence. The specified seed value is used as the initial accumulator value, and the specified function is used to select the result value.

System_CAPS_pubmethodSystem_CAPS_staticAll<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Determines whether all elements of a sequence satisfy a condition.

System_CAPS_pubmethodSystem_CAPS_staticAny<TSource>(IEnumerable<TSource>)

Determines whether a sequence contains any elements.

System_CAPS_pubmethodSystem_CAPS_staticAny<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Determines whether any element of a sequence satisfies a condition.

System_CAPS_pubmethodSystem_CAPS_staticAsEnumerable<TSource>(IEnumerable<TSource>)

Returns the input typed as IEnumerable<T>.

System_CAPS_pubmethodSystem_CAPS_staticAverage(IEnumerable<Decimal>)

Computes the average of a sequence of Decimal values.

System_CAPS_pubmethodSystem_CAPS_staticAverage(IEnumerable<Double>)

Computes the average of a sequence of Double values.

System_CAPS_pubmethodSystem_CAPS_staticAverage(IEnumerable<Int32>)

Computes the average of a sequence of Int32 values.

System_CAPS_pubmethodSystem_CAPS_staticAverage(IEnumerable<Int64>)

Computes the average of a sequence of Int64 values.

System_CAPS_pubmethodSystem_CAPS_staticAverage(IEnumerable<Nullable<Decimal>>)

Computes the average of a sequence of nullable Decimal values.

System_CAPS_pubmethodSystem_CAPS_staticAverage(IEnumerable<Nullable<Double>>)

Computes the average of a sequence of nullable Double values.

System_CAPS_pubmethodSystem_CAPS_staticAverage(IEnumerable<Nullable<Int32>>)

Computes the average of a sequence of nullable Int32 values.

System_CAPS_pubmethodSystem_CAPS_staticAverage(IEnumerable<Nullable<Int64>>)

Computes the average of a sequence of nullable Int64 values.

System_CAPS_pubmethodSystem_CAPS_staticAverage(IEnumerable<Nullable<Single>>)

Computes the average of a sequence of nullable Single values.

System_CAPS_pubmethodSystem_CAPS_staticAverage(IEnumerable<Single>)

Computes the average of a sequence of Single values.

System_CAPS_pubmethodSystem_CAPS_staticAverage<TSource>(IEnumerable<TSource>, Func<TSource, Decimal>)

Computes the average of a sequence of Decimal values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticAverage<TSource>(IEnumerable<TSource>, Func<TSource, Double>)

Computes the average of a sequence of Double values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticAverage<TSource>(IEnumerable<TSource>, Func<TSource, Int32>)

Computes the average of a sequence of Int32 values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticAverage<TSource>(IEnumerable<TSource>, Func<TSource, Int64>)

Computes the average of a sequence of Int64 values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticAverage<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Decimal>>)

Computes the average of a sequence of nullable Decimal values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticAverage<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Double>>)

Computes the average of a sequence of nullable Double values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticAverage<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Int32>>)

Computes the average of a sequence of nullable Int32 values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticAverage<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Int64>>)

Computes the average of a sequence of nullable Int64 values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticAverage<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Single>>)

Computes the average of a sequence of nullable Single values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticAverage<TSource>(IEnumerable<TSource>, Func<TSource, Single>)

Computes the average of a sequence of Single values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticCast<TResult>(IEnumerable)

Casts the elements of an IEnumerable to the specified type.

System_CAPS_pubmethodSystem_CAPS_staticConcat<TSource>(IEnumerable<TSource>, IEnumerable<TSource>)

Concatenates two sequences.

System_CAPS_pubmethodSystem_CAPS_staticContains<TSource>(IEnumerable<TSource>, TSource)

Determines whether a sequence contains a specified element by using the default equality comparer.

System_CAPS_pubmethodSystem_CAPS_staticContains<TSource>(IEnumerable<TSource>, TSource, IEqualityComparer<TSource>)

Determines whether a sequence contains a specified element by using a specified IEqualityComparer<T>.

System_CAPS_pubmethodSystem_CAPS_staticCount<TSource>(IEnumerable<TSource>)

Returns the number of elements in a sequence.

System_CAPS_pubmethodSystem_CAPS_staticCount<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Returns a number that represents how many elements in the specified sequence satisfy a condition.

System_CAPS_pubmethodSystem_CAPS_staticDefaultIfEmpty<TSource>(IEnumerable<TSource>)

Returns the elements of the specified sequence or the type parameter's default value in a singleton collection if the sequence is empty.

System_CAPS_pubmethodSystem_CAPS_staticDefaultIfEmpty<TSource>(IEnumerable<TSource>, TSource)

Returns the elements of the specified sequence or the specified value in a singleton collection if the sequence is empty.

System_CAPS_pubmethodSystem_CAPS_staticDistinct<TSource>(IEnumerable<TSource>)

Returns distinct elements from a sequence by using the default equality comparer to compare values.

System_CAPS_pubmethodSystem_CAPS_staticDistinct<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)

Returns distinct elements from a sequence by using a specified IEqualityComparer<T> to compare values.

System_CAPS_pubmethodSystem_CAPS_staticElementAt<TSource>(IEnumerable<TSource>, Int32)

Returns the element at a specified index in a sequence.

System_CAPS_pubmethodSystem_CAPS_staticElementAtOrDefault<TSource>(IEnumerable<TSource>, Int32)

Returns the element at a specified index in a sequence or a default value if the index is out of range.

System_CAPS_pubmethodSystem_CAPS_staticEmpty<TResult>()

Returns an empty IEnumerable<T> that has the specified type argument.

System_CAPS_pubmethodSystem_CAPS_staticExcept<TSource>(IEnumerable<TSource>, IEnumerable<TSource>)

Produces the set difference of two sequences by using the default equality comparer to compare values.

System_CAPS_pubmethodSystem_CAPS_staticExcept<TSource>(IEnumerable<TSource>, IEnumerable<TSource>, IEqualityComparer<TSource>)

Produces the set difference of two sequences by using the specified IEqualityComparer<T> to compare values.

System_CAPS_pubmethodSystem_CAPS_staticFirst<TSource>(IEnumerable<TSource>)

Returns the first element of a sequence.

System_CAPS_pubmethodSystem_CAPS_staticFirst<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Returns the first element in a sequence that satisfies a specified condition.

System_CAPS_pubmethodSystem_CAPS_staticFirstOrDefault<TSource>(IEnumerable<TSource>)

Returns the first element of a sequence, or a default value if the sequence contains no elements.

System_CAPS_pubmethodSystem_CAPS_staticFirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Returns the first element of the sequence that satisfies a condition or a default value if no such element is found.

System_CAPS_pubmethodSystem_CAPS_staticGroupBy<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)

Groups the elements of a sequence according to a specified key selector function.

System_CAPS_pubmethodSystem_CAPS_staticGroupBy<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>, IEqualityComparer<TKey>)

Groups the elements of a sequence according to a specified key selector function and compares the keys by using a specified comparer.

System_CAPS_pubmethodSystem_CAPS_staticGroupBy<TSource, TKey, TElement>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TSource, TElement>)

Groups the elements of a sequence according to a specified key selector function and projects the elements for each group by using a specified function.

System_CAPS_pubmethodSystem_CAPS_staticGroupBy<TSource, TKey, TElement>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TSource, TElement>, IEqualityComparer<TKey>)

Groups the elements of a sequence according to a key selector function. The keys are compared by using a comparer and each group's elements are projected by using a specified function.

System_CAPS_pubmethodSystem_CAPS_staticGroupBy<TSource, TKey, TResult>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TKey, IEnumerable<TSource>, TResult>)

Groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key.

System_CAPS_pubmethodSystem_CAPS_staticGroupBy<TSource, TKey, TResult>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TKey, IEnumerable<TSource>, TResult>, IEqualityComparer<TKey>)

Groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. The keys are compared by using a specified comparer.

System_CAPS_pubmethodSystem_CAPS_staticGroupBy<TSource, TKey, TElement, TResult>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TSource, TElement>, Func<TKey, IEnumerable<TElement>, TResult>)

Groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. The elements of each group are projected by using a specified function.

System_CAPS_pubmethodSystem_CAPS_staticGroupBy<TSource, TKey, TElement, TResult>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TSource, TElement>, Func<TKey, IEnumerable<TElement>, TResult>, IEqualityComparer<TKey>)

Groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. Key values are compared by using a specified comparer, and the elements of each group are projected by using a specified function.

System_CAPS_pubmethodSystem_CAPS_staticGroupJoin<TOuter, TInner, TKey, TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter, TKey>, Func<TInner, TKey>, Func<TOuter, IEnumerable<TInner>, TResult>)

Correlates the elements of two sequences based on equality of keys and groups the results. The default equality comparer is used to compare keys.

System_CAPS_pubmethodSystem_CAPS_staticGroupJoin<TOuter, TInner, TKey, TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter, TKey>, Func<TInner, TKey>, Func<TOuter, IEnumerable<TInner>, TResult>, IEqualityComparer<TKey>)

Correlates the elements of two sequences based on key equality and groups the results. A specified IEqualityComparer<T> is used to compare keys.

System_CAPS_pubmethodSystem_CAPS_staticIntersect<TSource>(IEnumerable<TSource>, IEnumerable<TSource>)

Produces the set intersection of two sequences by using the default equality comparer to compare values.

System_CAPS_pubmethodSystem_CAPS_staticIntersect<TSource>(IEnumerable<TSource>, IEnumerable<TSource>, IEqualityComparer<TSource>)

Produces the set intersection of two sequences by using the specified IEqualityComparer<T> to compare values.

System_CAPS_pubmethodSystem_CAPS_staticJoin<TOuter, TInner, TKey, TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter, TKey>, Func<TInner, TKey>, Func<TOuter, TInner, TResult>)

Correlates the elements of two sequences based on matching keys. The default equality comparer is used to compare keys.

System_CAPS_pubmethodSystem_CAPS_staticJoin<TOuter, TInner, TKey, TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter, TKey>, Func<TInner, TKey>, Func<TOuter, TInner, TResult>, IEqualityComparer<TKey>)

Correlates the elements of two sequences based on matching keys. A specified IEqualityComparer<T> is used to compare keys.

System_CAPS_pubmethodSystem_CAPS_staticLast<TSource>(IEnumerable<TSource>)

Returns the last element of a sequence.

System_CAPS_pubmethodSystem_CAPS_staticLast<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Returns the last element of a sequence that satisfies a specified condition.

System_CAPS_pubmethodSystem_CAPS_staticLastOrDefault<TSource>(IEnumerable<TSource>)

Returns the last element of a sequence, or a default value if the sequence contains no elements.

System_CAPS_pubmethodSystem_CAPS_staticLastOrDefault<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Returns the last element of a sequence that satisfies a condition or a default value if no such element is found.

System_CAPS_pubmethodSystem_CAPS_staticLongCount<TSource>(IEnumerable<TSource>)

Returns an Int64 that represents the total number of elements in a sequence.

System_CAPS_pubmethodSystem_CAPS_staticLongCount<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Returns an Int64 that represents how many elements in a sequence satisfy a condition.

System_CAPS_pubmethodSystem_CAPS_staticMax(IEnumerable<Decimal>)

Returns the maximum value in a sequence of Decimal values.

System_CAPS_pubmethodSystem_CAPS_staticMax(IEnumerable<Double>)

Returns the maximum value in a sequence of Double values.

System_CAPS_pubmethodSystem_CAPS_staticMax(IEnumerable<Int32>)

Returns the maximum value in a sequence of Int32 values.

System_CAPS_pubmethodSystem_CAPS_staticMax(IEnumerable<Int64>)

Returns the maximum value in a sequence of Int64 values.

System_CAPS_pubmethodSystem_CAPS_staticMax(IEnumerable<Nullable<Decimal>>)

Returns the maximum value in a sequence of nullable Decimal values.

System_CAPS_pubmethodSystem_CAPS_staticMax(IEnumerable<Nullable<Double>>)

Returns the maximum value in a sequence of nullable Double values.

System_CAPS_pubmethodSystem_CAPS_staticMax(IEnumerable<Nullable<Int32>>)

Returns the maximum value in a sequence of nullable Int32 values.

System_CAPS_pubmethodSystem_CAPS_staticMax(IEnumerable<Nullable<Int64>>)

Returns the maximum value in a sequence of nullable Int64 values.

System_CAPS_pubmethodSystem_CAPS_staticMax(IEnumerable<Nullable<Single>>)

Returns the maximum value in a sequence of nullable Single values.

System_CAPS_pubmethodSystem_CAPS_staticMax(IEnumerable<Single>)

Returns the maximum value in a sequence of Single values.

System_CAPS_pubmethodSystem_CAPS_staticMax<TSource>(IEnumerable<TSource>)

Returns the maximum value in a generic sequence.

System_CAPS_pubmethodSystem_CAPS_staticMax<TSource>(IEnumerable<TSource>, Func<TSource, Decimal>)

Invokes a transform function on each element of a sequence and returns the maximum Decimal value.

System_CAPS_pubmethodSystem_CAPS_staticMax<TSource>(IEnumerable<TSource>, Func<TSource, Double>)

Invokes a transform function on each element of a sequence and returns the maximum Double value.

System_CAPS_pubmethodSystem_CAPS_staticMax<TSource>(IEnumerable<TSource>, Func<TSource, Int32>)

Invokes a transform function on each element of a sequence and returns the maximum Int32 value.

System_CAPS_pubmethodSystem_CAPS_staticMax<TSource>(IEnumerable<TSource>, Func<TSource, Int64>)

Invokes a transform function on each element of a sequence and returns the maximum Int64 value.

System_CAPS_pubmethodSystem_CAPS_staticMax<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Decimal>>)

Invokes a transform function on each element of a sequence and returns the maximum nullable Decimal value.

System_CAPS_pubmethodSystem_CAPS_staticMax<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Double>>)

Invokes a transform function on each element of a sequence and returns the maximum nullable Double value.

System_CAPS_pubmethodSystem_CAPS_staticMax<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Int32>>)

Invokes a transform function on each element of a sequence and returns the maximum nullable Int32 value.

System_CAPS_pubmethodSystem_CAPS_staticMax<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Int64>>)

Invokes a transform function on each element of a sequence and returns the maximum nullable Int64 value.

System_CAPS_pubmethodSystem_CAPS_staticMax<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Single>>)

Invokes a transform function on each element of a sequence and returns the maximum nullable Single value.

System_CAPS_pubmethodSystem_CAPS_staticMax<TSource>(IEnumerable<TSource>, Func<TSource, Single>)

Invokes a transform function on each element of a sequence and returns the maximum Single value.

System_CAPS_pubmethodSystem_CAPS_staticMax<TSource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>)

Invokes a transform function on each element of a generic sequence and returns the maximum resulting value.

System_CAPS_pubmethodSystem_CAPS_staticMin(IEnumerable<Decimal>)

Returns the minimum value in a sequence of Decimal values.

System_CAPS_pubmethodSystem_CAPS_staticMin(IEnumerable<Double>)

Returns the minimum value in a sequence of Double values.

System_CAPS_pubmethodSystem_CAPS_staticMin(IEnumerable<Int32>)

Returns the minimum value in a sequence of Int32 values.

System_CAPS_pubmethodSystem_CAPS_staticMin(IEnumerable<Int64>)

Returns the minimum value in a sequence of Int64 values.

System_CAPS_pubmethodSystem_CAPS_staticMin(IEnumerable<Nullable<Decimal>>)

Returns the minimum value in a sequence of nullable Decimal values.

System_CAPS_pubmethodSystem_CAPS_staticMin(IEnumerable<Nullable<Double>>)

Returns the minimum value in a sequence of nullable Double values.

System_CAPS_pubmethodSystem_CAPS_staticMin(IEnumerable<Nullable<Int32>>)

Returns the minimum value in a sequence of nullable Int32 values.

System_CAPS_pubmethodSystem_CAPS_staticMin(IEnumerable<Nullable<Int64>>)

Returns the minimum value in a sequence of nullable Int64 values.

System_CAPS_pubmethodSystem_CAPS_staticMin(IEnumerable<Nullable<Single>>)

Returns the minimum value in a sequence of nullable Single values.

System_CAPS_pubmethodSystem_CAPS_staticMin(IEnumerable<Single>)

Returns the minimum value in a sequence of Single values.

System_CAPS_pubmethodSystem_CAPS_staticMin<TSource>(IEnumerable<TSource>)

Returns the minimum value in a generic sequence.

System_CAPS_pubmethodSystem_CAPS_staticMin<TSource>(IEnumerable<TSource>, Func<TSource, Decimal>)

Invokes a transform function on each element of a sequence and returns the minimum Decimal value.

System_CAPS_pubmethodSystem_CAPS_staticMin<TSource>(IEnumerable<TSource>, Func<TSource, Double>)

Invokes a transform function on each element of a sequence and returns the minimum Double value.

System_CAPS_pubmethodSystem_CAPS_staticMin<TSource>(IEnumerable<TSource>, Func<TSource, Int32>)

Invokes a transform function on each element of a sequence and returns the minimum Int32 value.

System_CAPS_pubmethodSystem_CAPS_staticMin<TSource>(IEnumerable<TSource>, Func<TSource, Int64>)

Invokes a transform function on each element of a sequence and returns the minimum Int64 value.

System_CAPS_pubmethodSystem_CAPS_staticMin<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Decimal>>)

Invokes a transform function on each element of a sequence and returns the minimum nullable Decimal value.

System_CAPS_pubmethodSystem_CAPS_staticMin<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Double>>)

Invokes a transform function on each element of a sequence and returns the minimum nullable Double value.

System_CAPS_pubmethodSystem_CAPS_staticMin<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Int32>>)

Invokes a transform function on each element of a sequence and returns the minimum nullable Int32 value.

System_CAPS_pubmethodSystem_CAPS_staticMin<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Int64>>)

Invokes a transform function on each element of a sequence and returns the minimum nullable Int64 value.

System_CAPS_pubmethodSystem_CAPS_staticMin<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Single>>)

Invokes a transform function on each element of a sequence and returns the minimum nullable Single value.

System_CAPS_pubmethodSystem_CAPS_staticMin<TSource>(IEnumerable<TSource>, Func<TSource, Single>)

Invokes a transform function on each element of a sequence and returns the minimum Single value.

System_CAPS_pubmethodSystem_CAPS_staticMin<TSource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>)

Invokes a transform function on each element of a generic sequence and returns the minimum resulting value.

System_CAPS_pubmethodSystem_CAPS_staticOfType<TResult>(IEnumerable)

Filters the elements of an IEnumerable based on a specified type.

System_CAPS_pubmethodSystem_CAPS_staticOrderBy<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)

Sorts the elements of a sequence in ascending order according to a key.

System_CAPS_pubmethodSystem_CAPS_staticOrderBy<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>, IComparer<TKey>)

Sorts the elements of a sequence in ascending order by using a specified comparer.

System_CAPS_pubmethodSystem_CAPS_staticOrderByDescending<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)

Sorts the elements of a sequence in descending order according to a key.

System_CAPS_pubmethodSystem_CAPS_staticOrderByDescending<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>, IComparer<TKey>)

Sorts the elements of a sequence in descending order by using a specified comparer.

System_CAPS_pubmethodSystem_CAPS_staticRange(Int32, Int32)

Generates a sequence of integral numbers within a specified range.

System_CAPS_pubmethodSystem_CAPS_staticRepeat<TResult>(TResult, Int32)

Generates a sequence that contains one repeated value.

System_CAPS_pubmethodSystem_CAPS_staticReverse<TSource>(IEnumerable<TSource>)

Inverts the order of the elements in a sequence.

System_CAPS_pubmethodSystem_CAPS_staticSelect<TSource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>)

Projects each element of a sequence into a new form.

System_CAPS_pubmethodSystem_CAPS_staticSelect<TSource, TResult>(IEnumerable<TSource>, Func<TSource, Int32, TResult>)

Projects each element of a sequence into a new form by incorporating the element's index.

System_CAPS_pubmethodSystem_CAPS_staticSelectMany<TSource, TResult>(IEnumerable<TSource>, Func<TSource, IEnumerable<TResult>>)

Projects each element of a sequence to an IEnumerable<T> and flattens the resulting sequences into one sequence.

System_CAPS_pubmethodSystem_CAPS_staticSelectMany<TSource, TResult>(IEnumerable<TSource>, Func<TSource, Int32, IEnumerable<TResult>>)

Projects each element of a sequence to an IEnumerable<T>, and flattens the resulting sequences into one sequence. The index of each source element is used in the projected form of that element.

System_CAPS_pubmethodSystem_CAPS_staticSelectMany<TSource, TCollection, TResult>(IEnumerable<TSource>, Func<TSource, IEnumerable<TCollection>>, Func<TSource, TCollection, TResult>)

Projects each element of a sequence to an IEnumerable<T>, flattens the resulting sequences into one sequence, and invokes a result selector function on each element therein.

System_CAPS_pubmethodSystem_CAPS_staticSelectMany<TSource, TCollection, TResult>(IEnumerable<TSource>, Func<TSource, Int32, IEnumerable<TCollection>>, Func<TSource, TCollection, TResult>)

Projects each element of a sequence to an IEnumerable<T>, flattens the resulting sequences into one sequence, and invokes a result selector function on each element therein. The index of each source element is used in the intermediate projected form of that element.

System_CAPS_pubmethodSystem_CAPS_staticSequenceEqual<TSource>(IEnumerable<TSource>, IEnumerable<TSource>)

Determines whether two sequences are equal by comparing the elements by using the default equality comparer for their type.

System_CAPS_pubmethodSystem_CAPS_staticSequenceEqual<TSource>(IEnumerable<TSource>, IEnumerable<TSource>, IEqualityComparer<TSource>)

Determines whether two sequences are equal by comparing their elements by using a specified IEqualityComparer<T>.

System_CAPS_pubmethodSystem_CAPS_staticSingle<TSource>(IEnumerable<TSource>)

Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence.

System_CAPS_pubmethodSystem_CAPS_staticSingle<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Returns the only element of a sequence that satisfies a specified condition, and throws an exception if more than one such element exists.

System_CAPS_pubmethodSystem_CAPS_staticSingleOrDefault<TSource>(IEnumerable<TSource>)

Returns the only element of a sequence, or a default value if the sequence is empty; this method throws an exception if there is more than one element in the sequence.

System_CAPS_pubmethodSystem_CAPS_staticSingleOrDefault<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Returns the only element of a sequence that satisfies a specified condition or a default value if no such element exists; this method throws an exception if more than one element satisfies the condition.

System_CAPS_pubmethodSystem_CAPS_staticSkip<TSource>(IEnumerable<TSource>, Int32)

Bypasses a specified number of elements in a sequence and then returns the remaining elements.

System_CAPS_pubmethodSystem_CAPS_staticSkipWhile<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements.

System_CAPS_pubmethodSystem_CAPS_staticSkipWhile<TSource>(IEnumerable<TSource>, Func<TSource, Int32, Boolean>)

Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements. The element's index is used in the logic of the predicate function.

System_CAPS_pubmethodSystem_CAPS_staticSum(IEnumerable<Decimal>)

Computes the sum of a sequence of Decimal values.

System_CAPS_pubmethodSystem_CAPS_staticSum(IEnumerable<Double>)

Computes the sum of a sequence of Double values.

System_CAPS_pubmethodSystem_CAPS_staticSum(IEnumerable<Int32>)

Computes the sum of a sequence of Int32 values.

System_CAPS_pubmethodSystem_CAPS_staticSum(IEnumerable<Int64>)

Computes the sum of a sequence of Int64 values.

System_CAPS_pubmethodSystem_CAPS_staticSum(IEnumerable<Nullable<Decimal>>)

Computes the sum of a sequence of nullable Decimal values.

System_CAPS_pubmethodSystem_CAPS_staticSum(IEnumerable<Nullable<Double>>)

Computes the sum of a sequence of nullable Double values.

System_CAPS_pubmethodSystem_CAPS_staticSum(IEnumerable<Nullable<Int32>>)

Computes the sum of a sequence of nullable Int32 values.

System_CAPS_pubmethodSystem_CAPS_staticSum(IEnumerable<Nullable<Int64>>)

Computes the sum of a sequence of nullable Int64 values.

System_CAPS_pubmethodSystem_CAPS_staticSum(IEnumerable<Nullable<Single>>)

Computes the sum of a sequence of nullable Single values.

System_CAPS_pubmethodSystem_CAPS_staticSum(IEnumerable<Single>)

Computes the sum of a sequence of Single values.

System_CAPS_pubmethodSystem_CAPS_staticSum<TSource>(IEnumerable<TSource>, Func<TSource, Decimal>)

Computes the sum of the sequence of Decimal values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticSum<TSource>(IEnumerable<TSource>, Func<TSource, Double>)

Computes the sum of the sequence of Double values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticSum<TSource>(IEnumerable<TSource>, Func<TSource, Int32>)

Computes the sum of the sequence of Int32 values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticSum<TSource>(IEnumerable<TSource>, Func<TSource, Int64>)

Computes the sum of the sequence of Int64 values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticSum<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Decimal>>)

Computes the sum of the sequence of nullable Decimal values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticSum<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Double>>)

Computes the sum of the sequence of nullable Double values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticSum<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Int32>>)

Computes the sum of the sequence of nullable Int32 values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticSum<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Int64>>)

Computes the sum of the sequence of nullable Int64 values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticSum<TSource>(IEnumerable<TSource>, Func<TSource, Nullable<Single>>)

Computes the sum of the sequence of nullable Single values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticSum<TSource>(IEnumerable<TSource>, Func<TSource, Single>)

Computes the sum of the sequence of Single values that are obtained by invoking a transform function on each element of the input sequence.

System_CAPS_pubmethodSystem_CAPS_staticTake<TSource>(IEnumerable<TSource>, Int32)

Returns a specified number of contiguous elements from the start of a sequence.

System_CAPS_pubmethodSystem_CAPS_staticTakeWhile<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Returns elements from a sequence as long as a specified condition is true.

System_CAPS_pubmethodSystem_CAPS_staticTakeWhile<TSource>(IEnumerable<TSource>, Func<TSource, Int32, Boolean>)

Returns elements from a sequence as long as a specified condition is true. The element's index is used in the logic of the predicate function.

System_CAPS_pubmethodSystem_CAPS_staticThenBy<TSource, TKey>(IOrderedEnumerable<TSource>, Func<TSource, TKey>)

Performs a subsequent ordering of the elements in a sequence in ascending order according to a key.

System_CAPS_pubmethodSystem_CAPS_staticThenBy<TSource, TKey>(IOrderedEnumerable<TSource>, Func<TSource, TKey>, IComparer<TKey>)

Performs a subsequent ordering of the elements in a sequence in ascending order by using a specified comparer.

System_CAPS_pubmethodSystem_CAPS_staticThenByDescending<TSource, TKey>(IOrderedEnumerable<TSource>, Func<TSource, TKey>)

Performs a subsequent ordering of the elements in a sequence in descending order, according to a key.

System_CAPS_pubmethodSystem_CAPS_staticThenByDescending<TSource, TKey>(IOrderedEnumerable<TSource>, Func<TSource, TKey>, IComparer<TKey>)

Performs a subsequent ordering of the elements in a sequence in descending order by using a specified comparer.

System_CAPS_pubmethodSystem_CAPS_staticToArray<TSource>(IEnumerable<TSource>)

Creates an array from a IEnumerable<T>.

System_CAPS_pubmethodSystem_CAPS_staticToDictionary<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)

Creates a Dictionary<TKey, TValue> from an IEnumerable<T> according to a specified key selector function.

System_CAPS_pubmethodSystem_CAPS_staticToDictionary<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>, IEqualityComparer<TKey>)

Creates a Dictionary<TKey, TValue> from an IEnumerable<T> according to a specified key selector function and key comparer.

System_CAPS_pubmethodSystem_CAPS_staticToDictionary<TSource, TKey, TElement>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TSource, TElement>)

Creates a Dictionary<TKey, TValue> from an IEnumerable<T> according to specified key selector and element selector functions.

System_CAPS_pubmethodSystem_CAPS_staticToDictionary<TSource, TKey, TElement>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TSource, TElement>, IEqualityComparer<TKey>)

Creates a Dictionary<TKey, TValue> from an IEnumerable<T> according to a specified key selector function, a comparer, and an element selector function.

System_CAPS_pubmethodSystem_CAPS_staticToList<TSource>(IEnumerable<TSource>)

Creates a List<T> from an IEnumerable<T>.

System_CAPS_pubmethodSystem_CAPS_staticToLookup<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)

Creates a Lookup<TKey, TElement> from an IEnumerable<T> according to a specified key selector function.

System_CAPS_pubmethodSystem_CAPS_staticToLookup<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>, IEqualityComparer<TKey>)

Creates a Lookup<TKey, TElement> from an IEnumerable<T> according to a specified key selector function and key comparer.

System_CAPS_pubmethodSystem_CAPS_staticToLookup<TSource, TKey, TElement>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TSource, TElement>)

Creates a Lookup<TKey, TElement> from an IEnumerable<T> according to specified key selector and element selector functions.

System_CAPS_pubmethodSystem_CAPS_staticToLookup<TSource, TKey, TElement>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TSource, TElement>, IEqualityComparer<TKey>)

Creates a Lookup<TKey, TElement> from an IEnumerable<T> according to a specified key selector function, a comparer and an element selector function.

System_CAPS_pubmethodSystem_CAPS_staticUnion<TSource>(IEnumerable<TSource>, IEnumerable<TSource>)

Produces the set union of two sequences by using the default equality comparer.

System_CAPS_pubmethodSystem_CAPS_staticUnion<TSource>(IEnumerable<TSource>, IEnumerable<TSource>, IEqualityComparer<TSource>)

Produces the set union of two sequences by using a specified IEqualityComparer<T>.

System_CAPS_pubmethodSystem_CAPS_staticWhere<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Filters a sequence of values based on a predicate.

System_CAPS_pubmethodSystem_CAPS_staticWhere<TSource>(IEnumerable<TSource>, Func<TSource, Int32, Boolean>)

Filters a sequence of values based on a predicate. Each element's index is used in the logic of the predicate function.

System_CAPS_pubmethodSystem_CAPS_staticZip<TFirst, TSecond, TResult>(IEnumerable<TFirst>, IEnumerable<TSecond>, Func<TFirst, TSecond, TResult>)

Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results.






IEnumerable<T> Interface


https://msdn.microsoft.com/en-us/library/9eekhta0(v=vs.110).aspx


Exposes the enumerator, which supports a simple iteration over a collection of a specified type.

To browse the .NET Framework source code for this type, see the Reference Source.

Namespace:   System.Collections.Generic
Assembly:  mscorlib (in mscorlib.dll)

Syntax

public interface IEnumerable<out T> : IEnumerable

Type Parameters

outT

The type of objects to enumerate.

Methods

NameDescription
System_CAPS_pubmethodGetEnumerator()

Returns an enumerator that iterates through the collection.

Extension Methods

NameDescription
System_CAPS_pubmethodAggregate<TSource>(Func<TSource, TSource, TSource>)

Overloaded. Applies an accumulator function over a sequence.(Defined by Enumerable.)

System_CAPS_pubmethodAggregate<TSource, TAccumulate>(TAccumulate, Func<TAccumulate, TSource, TAccumulate>)

Overloaded. Applies an accumulator function over a sequence. The specified seed value is used as the initial accumulator value.(Defined by Enumerable.)

System_CAPS_pubmethodAggregate<TSource, TAccumulate, TResult>(TAccumulate, Func<TAccumulate, TSource, TAccumulate>, Func<TAccumulate, TResult>)

Overloaded. Applies an accumulator function over a sequence. The specified seed value is used as the initial accumulator value, and the specified function is used to select the result value.(Defined by Enumerable.)

System_CAPS_pubmethodAll<TSource>(Func<TSource, Boolean>)

Determines whether all elements of a sequence satisfy a condition.(Defined by Enumerable.)

System_CAPS_pubmethodAncestors<T>()

Overloaded. Returns a collection of elements that contains the ancestors of every node in the source collection.(Defined by Extensions.)

System_CAPS_pubmethodAncestors<T>(XName)

Overloaded. Returns a filtered collection of elements that contains the ancestors of every node in the source collection. Only elements that have a matching XName are included in the collection.(Defined by Extensions.)

System_CAPS_pubmethodAny<TSource>()

Overloaded. Determines whether a sequence contains any elements.(Defined by Enumerable.)

System_CAPS_pubmethodAny<TSource>(Func<TSource, Boolean>)

Overloaded. Determines whether any element of a sequence satisfies a condition.(Defined by Enumerable.)

System_CAPS_pubmethodAsEnumerable<TSource>()

Returns the input typed as IEnumerable<T>.(Defined by Enumerable.)

System_CAPS_pubmethodAsParallel<TSource>()

Overloaded. Enables parallelization of a query.(Defined by ParallelEnumerable.)

System_CAPS_pubmethodAsQueryable<TElement>()

Overloaded. Converts a generic IEnumerable<T> to a generic IQueryable<T>.(Defined by Queryable.)

System_CAPS_pubmethodAverage<TSource>(Func<TSource, Decimal>)

Overloaded. Computes the average of a sequence of Decimal values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodAverage<TSource>(Func<TSource, Double>)

Overloaded. Computes the average of a sequence of Double values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodAverage<TSource>(Func<TSource, Int32>)

Overloaded. Computes the average of a sequence of Int32 values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodAverage<TSource>(Func<TSource, Int64>)

Overloaded. Computes the average of a sequence of Int64 values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodAverage<TSource>(Func<TSource, Nullable<Decimal>>)

Overloaded. Computes the average of a sequence of nullable Decimal values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodAverage<TSource>(Func<TSource, Nullable<Double>>)

Overloaded. Computes the average of a sequence of nullable Double values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodAverage<TSource>(Func<TSource, Nullable<Int32>>)

Overloaded. Computes the average of a sequence of nullable Int32 values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodAverage<TSource>(Func<TSource, Nullable<Int64>>)

Overloaded. Computes the average of a sequence of nullable Int64 values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodAverage<TSource>(Func<TSource, Nullable<Single>>)

Overloaded. Computes the average of a sequence of nullable Single values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodAverage<TSource>(Func<TSource, Single>)

Overloaded. Computes the average of a sequence of Single values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodCast<TResult>()

Casts the elements of an IEnumerable to the specified type.(Defined by Enumerable.)

System_CAPS_pubmethodConcat<TSource>(IEnumerable<TSource>)

Concatenates two sequences.(Defined by Enumerable.)

System_CAPS_pubmethodContains<TSource>(TSource)

Overloaded. Determines whether a sequence contains a specified element by using the default equality comparer.(Defined by Enumerable.)

System_CAPS_pubmethodContains<TSource>(TSource, IEqualityComparer<TSource>)

Overloaded. Determines whether a sequence contains a specified element by using a specified IEqualityComparer<T>.(Defined by Enumerable.)

System_CAPS_pubmethodCopyToDataTable<T>()

Overloaded. Returns a DataTable that contains copies of the DataRow objects, given an input IEnumerable<T> object where the generic parameter T is DataRow. (Defined by DataTableExtensions.)

System_CAPS_pubmethodCopyToDataTable<T>(DataTable, LoadOption)

Overloaded. Copies DataRow objects to the specified DataTable, given an input IEnumerable<T> object where the generic parameter T is DataRow.(Defined by DataTableExtensions.)

System_CAPS_pubmethodCopyToDataTable<T>(DataTable, LoadOption, FillErrorEventHandler)

Overloaded. Copies DataRow objects to the specified DataTable, given an input IEnumerable<T> object where the generic parameter T is DataRow.(Defined by DataTableExtensions.)

System_CAPS_pubmethodCount<TSource>()

Overloaded. Returns the number of elements in a sequence.(Defined by Enumerable.)

System_CAPS_pubmethodCount<TSource>(Func<TSource, Boolean>)

Overloaded. Returns a number that represents how many elements in the specified sequence satisfy a condition.(Defined by Enumerable.)

System_CAPS_pubmethodDefaultIfEmpty<TSource>()

Overloaded. Returns the elements of the specified sequence or the type parameter's default value in a singleton collection if the sequence is empty.(Defined by Enumerable.)

System_CAPS_pubmethodDefaultIfEmpty<TSource>(TSource)

Overloaded. Returns the elements of the specified sequence or the specified value in a singleton collection if the sequence is empty.(Defined by Enumerable.)

System_CAPS_pubmethodDescendantNodes<T>()

Returns a collection of the descendant nodes of every document and element in the source collection.(Defined by Extensions.)

System_CAPS_pubmethodDescendants<T>()

Overloaded. Returns a collection of elements that contains the descendant elements of every element and document in the source collection.(Defined by Extensions.)

System_CAPS_pubmethodDescendants<T>(XName)

Overloaded. Returns a filtered collection of elements that contains the descendant elements of every element and document in the source collection. Only elements that have a matching XName are included in the collection.(Defined by Extensions.)

System_CAPS_pubmethodDistinct<TSource>()

Overloaded. Returns distinct elements from a sequence by using the default equality comparer to compare values.(Defined by Enumerable.)

System_CAPS_pubmethodDistinct<TSource>(IEqualityComparer<TSource>)

Overloaded. Returns distinct elements from a sequence by using a specified IEqualityComparer<T> to compare values.(Defined by Enumerable.)

System_CAPS_pubmethodElementAt<TSource>(Int32)

Returns the element at a specified index in a sequence.(Defined by Enumerable.)

System_CAPS_pubmethodElementAtOrDefault<TSource>(Int32)

Returns the element at a specified index in a sequence or a default value if the index is out of range.(Defined by Enumerable.)

System_CAPS_pubmethodElements<T>()

Overloaded. Returns a collection of the child elements of every element and document in the source collection.(Defined by Extensions.)

System_CAPS_pubmethodElements<T>(XName)

Overloaded. Returns a filtered collection of the child elements of every element and document in the source collection. Only elements that have a matching XName are included in the collection.(Defined by Extensions.)

System_CAPS_pubmethodExcept<TSource>(IEnumerable<TSource>)

Overloaded. Produces the set difference of two sequences by using the default equality comparer to compare values.(Defined by Enumerable.)

System_CAPS_pubmethodExcept<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)

Overloaded. Produces the set difference of two sequences by using the specified IEqualityComparer<T> to compare values.(Defined by Enumerable.)

System_CAPS_pubmethodFirst<TSource>()

Overloaded. Returns the first element of a sequence.(Defined by Enumerable.)

System_CAPS_pubmethodFirst<TSource>(Func<TSource, Boolean>)

Overloaded. Returns the first element in a sequence that satisfies a specified condition.(Defined by Enumerable.)

System_CAPS_pubmethodFirstOrDefault<TSource>()

Overloaded. Returns the first element of a sequence, or a default value if the sequence contains no elements.(Defined by Enumerable.)

System_CAPS_pubmethodFirstOrDefault<TSource>(Func<TSource, Boolean>)

Overloaded. Returns the first element of the sequence that satisfies a condition or a default value if no such element is found.(Defined by Enumerable.)

System_CAPS_pubmethodGroupBy<TSource, TKey>(Func<TSource, TKey>)

Overloaded. Groups the elements of a sequence according to a specified key selector function.(Defined by Enumerable.)

System_CAPS_pubmethodGroupBy<TSource, TKey>(Func<TSource, TKey>, IEqualityComparer<TKey>)

Overloaded. Groups the elements of a sequence according to a specified key selector function and compares the keys by using a specified comparer.(Defined by Enumerable.)

System_CAPS_pubmethodGroupBy<TSource, TKey, TElement>(Func<TSource, TKey>, Func<TSource, TElement>)

Overloaded. Groups the elements of a sequence according to a specified key selector function and projects the elements for each group by using a specified function.(Defined by Enumerable.)

System_CAPS_pubmethodGroupBy<TSource, TKey, TElement>(Func<TSource, TKey>, Func<TSource, TElement>, IEqualityComparer<TKey>)

Overloaded. Groups the elements of a sequence according to a key selector function. The keys are compared by using a comparer and each group's elements are projected by using a specified function.(Defined by Enumerable.)

System_CAPS_pubmethodGroupBy<TSource, TKey, TResult>(Func<TSource, TKey>, Func<TKey, IEnumerable<TSource>, TResult>)

Overloaded. Groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key.(Defined by Enumerable.)

System_CAPS_pubmethodGroupBy<TSource, TKey, TResult>(Func<TSource, TKey>, Func<TKey, IEnumerable<TSource>, TResult>, IEqualityComparer<TKey>)

Overloaded. Groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. The keys are compared by using a specified comparer.(Defined by Enumerable.)

System_CAPS_pubmethodGroupBy<TSource, TKey, TElement, TResult>(Func<TSource, TKey>, Func<TSource, TElement>, Func<TKey, IEnumerable<TElement>, TResult>)

Overloaded. Groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. The elements of each group are projected by using a specified function.(Defined by Enumerable.)

System_CAPS_pubmethodGroupBy<TSource, TKey, TElement, TResult>(Func<TSource, TKey>, Func<TSource, TElement>, Func<TKey, IEnumerable<TElement>, TResult>, IEqualityComparer<TKey>)

Overloaded. Groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. Key values are compared by using a specified comparer, and the elements of each group are projected by using a specified function.(Defined by Enumerable.)

System_CAPS_pubmethodGroupJoin<TOuter, TInner, TKey, TResult>(IEnumerable<TInner>, Func<TOuter, TKey>, Func<TInner, TKey>, Func<TOuter, IEnumerable<TInner>, TResult>)

Overloaded. Correlates the elements of two sequences based on equality of keys and groups the results. The default equality comparer is used to compare keys.(Defined by Enumerable.)

System_CAPS_pubmethodGroupJoin<TOuter, TInner, TKey, TResult>(IEnumerable<TInner>, Func<TOuter, TKey>, Func<TInner, TKey>, Func<TOuter, IEnumerable<TInner>, TResult>, IEqualityComparer<TKey>)

Overloaded. Correlates the elements of two sequences based on key equality and groups the results. A specified IEqualityComparer<T> is used to compare keys.(Defined by Enumerable.)

System_CAPS_pubmethodInDocumentOrder<T>()

Returns a collection of nodes that contains all nodes in the source collection, sorted in document order.(Defined by Extensions.)

System_CAPS_pubmethodIntersect<TSource>(IEnumerable<TSource>)

Overloaded. Produces the set intersection of two sequences by using the default equality comparer to compare values.(Defined by Enumerable.)

System_CAPS_pubmethodIntersect<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)

Overloaded. Produces the set intersection of two sequences by using the specified IEqualityComparer<T> to compare values.(Defined by Enumerable.)

System_CAPS_pubmethodJoin<TOuter, TInner, TKey, TResult>(IEnumerable<TInner>, Func<TOuter, TKey>, Func<TInner, TKey>, Func<TOuter, TInner, TResult>)

Overloaded. Correlates the elements of two sequences based on matching keys. The default equality comparer is used to compare keys.(Defined by Enumerable.)

System_CAPS_pubmethodJoin<TOuter, TInner, TKey, TResult>(IEnumerable<TInner>, Func<TOuter, TKey>, Func<TInner, TKey>, Func<TOuter, TInner, TResult>, IEqualityComparer<TKey>)

Overloaded. Correlates the elements of two sequences based on matching keys. A specified IEqualityComparer<T> is used to compare keys.(Defined by Enumerable.)

System_CAPS_pubmethodLast<TSource>()

Overloaded. Returns the last element of a sequence.(Defined by Enumerable.)

System_CAPS_pubmethodLast<TSource>(Func<TSource, Boolean>)

Overloaded. Returns the last element of a sequence that satisfies a specified condition.(Defined by Enumerable.)

System_CAPS_pubmethodLastOrDefault<TSource>()

Overloaded. Returns the last element of a sequence, or a default value if the sequence contains no elements.(Defined by Enumerable.)

System_CAPS_pubmethodLastOrDefault<TSource>(Func<TSource, Boolean>)

Overloaded. Returns the last element of a sequence that satisfies a condition or a default value if no such element is found.(Defined by Enumerable.)

System_CAPS_pubmethodLongCount<TSource>()

Overloaded. Returns an Int64 that represents the total number of elements in a sequence.(Defined by Enumerable.)

System_CAPS_pubmethodLongCount<TSource>(Func<TSource, Boolean>)

Overloaded. Returns an Int64 that represents how many elements in a sequence satisfy a condition.(Defined by Enumerable.)

System_CAPS_pubmethodMax<TSource>()

Overloaded. Returns the maximum value in a generic sequence.(Defined by Enumerable.)

System_CAPS_pubmethodMax<TSource>(Func<TSource, Decimal>)

Overloaded. Invokes a transform function on each element of a sequence and returns the maximum Decimal value.(Defined by Enumerable.)

System_CAPS_pubmethodMax<TSource>(Func<TSource, Double>)

Overloaded. Invokes a transform function on each element of a sequence and returns the maximum Double value.(Defined by Enumerable.)

System_CAPS_pubmethodMax<TSource>(Func<TSource, Int32>)

Overloaded. Invokes a transform function on each element of a sequence and returns the maximum Int32 value.(Defined by Enumerable.)

System_CAPS_pubmethodMax<TSource>(Func<TSource, Int64>)

Overloaded. Invokes a transform function on each element of a sequence and returns the maximum Int64 value.(Defined by Enumerable.)

System_CAPS_pubmethodMax<TSource>(Func<TSource, Nullable<Decimal>>)

Overloaded. Invokes a transform function on each element of a sequence and returns the maximum nullable Decimal value.(Defined by Enumerable.)

System_CAPS_pubmethodMax<TSource>(Func<TSource, Nullable<Double>>)

Overloaded. Invokes a transform function on each element of a sequence and returns the maximum nullable Double value.(Defined by Enumerable.)

System_CAPS_pubmethodMax<TSource>(Func<TSource, Nullable<Int32>>)

Overloaded. Invokes a transform function on each element of a sequence and returns the maximum nullable Int32 value.(Defined by Enumerable.)

System_CAPS_pubmethodMax<TSource>(Func<TSource, Nullable<Int64>>)

Overloaded. Invokes a transform function on each element of a sequence and returns the maximum nullable Int64 value.(Defined by Enumerable.)

System_CAPS_pubmethodMax<TSource>(Func<TSource, Nullable<Single>>)

Overloaded. Invokes a transform function on each element of a sequence and returns the maximum nullable Single value.(Defined by Enumerable.)

System_CAPS_pubmethodMax<TSource>(Func<TSource, Single>)

Overloaded. Invokes a transform function on each element of a sequence and returns the maximum Single value.(Defined by Enumerable.)

System_CAPS_pubmethodMax<TSource, TResult>(Func<TSource, TResult>)

Overloaded. Invokes a transform function on each element of a generic sequence and returns the maximum resulting value.(Defined by Enumerable.)

System_CAPS_pubmethodMin<TSource>()

Overloaded. Returns the minimum value in a generic sequence.(Defined by Enumerable.)

System_CAPS_pubmethodMin<TSource>(Func<TSource, Decimal>)

Overloaded. Invokes a transform function on each element of a sequence and returns the minimum Decimal value.(Defined by Enumerable.)

System_CAPS_pubmethodMin<TSource>(Func<TSource, Double>)

Overloaded. Invokes a transform function on each element of a sequence and returns the minimum Double value.(Defined by Enumerable.)

System_CAPS_pubmethodMin<TSource>(Func<TSource, Int32>)

Overloaded. Invokes a transform function on each element of a sequence and returns the minimum Int32 value.(Defined by Enumerable.)

System_CAPS_pubmethodMin<TSource>(Func<TSource, Int64>)

Overloaded. Invokes a transform function on each element of a sequence and returns the minimum Int64 value.(Defined by Enumerable.)

System_CAPS_pubmethodMin<TSource>(Func<TSource, Nullable<Decimal>>)

Overloaded. Invokes a transform function on each element of a sequence and returns the minimum nullable Decimal value.(Defined by Enumerable.)

System_CAPS_pubmethodMin<TSource>(Func<TSource, Nullable<Double>>)

Overloaded. Invokes a transform function on each element of a sequence and returns the minimum nullable Double value.(Defined by Enumerable.)

System_CAPS_pubmethodMin<TSource>(Func<TSource, Nullable<Int32>>)

Overloaded. Invokes a transform function on each element of a sequence and returns the minimum nullable Int32 value.(Defined by Enumerable.)

System_CAPS_pubmethodMin<TSource>(Func<TSource, Nullable<Int64>>)

Overloaded. Invokes a transform function on each element of a sequence and returns the minimum nullable Int64 value.(Defined by Enumerable.)

System_CAPS_pubmethodMin<TSource>(Func<TSource, Nullable<Single>>)

Overloaded. Invokes a transform function on each element of a sequence and returns the minimum nullable Single value.(Defined by Enumerable.)

System_CAPS_pubmethodMin<TSource>(Func<TSource, Single>)

Overloaded. Invokes a transform function on each element of a sequence and returns the minimum Single value.(Defined by Enumerable.)

System_CAPS_pubmethodMin<TSource, TResult>(Func<TSource, TResult>)

Overloaded. Invokes a transform function on each element of a generic sequence and returns the minimum resulting value.(Defined by Enumerable.)

System_CAPS_pubmethodNodes<T>()

Returns a collection of the child nodes of every document and element in the source collection.(Defined by Extensions.)

System_CAPS_pubmethodOfType<TResult>()

Filters the elements of an IEnumerable based on a specified type.(Defined by Enumerable.)

System_CAPS_pubmethodOrderBy<TSource, TKey>(Func<TSource, TKey>)

Overloaded. Sorts the elements of a sequence in ascending order according to a key.(Defined by Enumerable.)

System_CAPS_pubmethodOrderBy<TSource, TKey>(Func<TSource, TKey>, IComparer<TKey>)

Overloaded. Sorts the elements of a sequence in ascending order by using a specified comparer.(Defined by Enumerable.)

System_CAPS_pubmethodOrderByDescending<TSource, TKey>(Func<TSource, TKey>)

Overloaded. Sorts the elements of a sequence in descending order according to a key.(Defined by Enumerable.)

System_CAPS_pubmethodOrderByDescending<TSource, TKey>(Func<TSource, TKey>, IComparer<TKey>)

Overloaded. Sorts the elements of a sequence in descending order by using a specified comparer.(Defined by Enumerable.)

System_CAPS_pubmethodRemove<T>()

Overloaded. Removes every node in the source collection from its parent node.(Defined by Extensions.)

System_CAPS_pubmethodReverse<TSource>()

Inverts the order of the elements in a sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSelect<TSource, TResult>(Func<TSource, TResult>)

Overloaded. Projects each element of a sequence into a new form.(Defined by Enumerable.)

System_CAPS_pubmethodSelect<TSource, TResult>(Func<TSource, Int32, TResult>)

Overloaded. Projects each element of a sequence into a new form by incorporating the element's index.(Defined by Enumerable.)

System_CAPS_pubmethodSelectMany<TSource, TResult>(Func<TSource, IEnumerable<TResult>>)

Overloaded. Projects each element of a sequence to an IEnumerable<T> and flattens the resulting sequences into one sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSelectMany<TSource, TResult>(Func<TSource, Int32, IEnumerable<TResult>>)

Overloaded. Projects each element of a sequence to an IEnumerable<T>, and flattens the resulting sequences into one sequence. The index of each source element is used in the projected form of that element.(Defined by Enumerable.)

System_CAPS_pubmethodSelectMany<TSource, TCollection, TResult>(Func<TSource, IEnumerable<TCollection>>, Func<TSource, TCollection, TResult>)

Overloaded. Projects each element of a sequence to an IEnumerable<T>, flattens the resulting sequences into one sequence, and invokes a result selector function on each element therein.(Defined by Enumerable.)

System_CAPS_pubmethodSelectMany<TSource, TCollection, TResult>(Func<TSource, Int32, IEnumerable<TCollection>>, Func<TSource, TCollection, TResult>)

Overloaded. Projects each element of a sequence to an IEnumerable<T>, flattens the resulting sequences into one sequence, and invokes a result selector function on each element therein. The index of each source element is used in the intermediate projected form of that element.(Defined by Enumerable.)

System_CAPS_pubmethodSequenceEqual<TSource>(IEnumerable<TSource>)

Overloaded. Determines whether two sequences are equal by comparing the elements by using the default equality comparer for their type.(Defined by Enumerable.)

System_CAPS_pubmethodSequenceEqual<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)

Overloaded. Determines whether two sequences are equal by comparing their elements by using a specified IEqualityComparer<T>.(Defined by Enumerable.)

System_CAPS_pubmethodSingle<TSource>()

Overloaded. Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSingle<TSource>(Func<TSource, Boolean>)

Overloaded. Returns the only element of a sequence that satisfies a specified condition, and throws an exception if more than one such element exists.(Defined by Enumerable.)

System_CAPS_pubmethodSingleOrDefault<TSource>()

Overloaded. Returns the only element of a sequence, or a default value if the sequence is empty; this method throws an exception if there is more than one element in the sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSingleOrDefault<TSource>(Func<TSource, Boolean>)

Overloaded. Returns the only element of a sequence that satisfies a specified condition or a default value if no such element exists; this method throws an exception if more than one element satisfies the condition.(Defined by Enumerable.)

System_CAPS_pubmethodSkip<TSource>(Int32)

Bypasses a specified number of elements in a sequence and then returns the remaining elements.(Defined by Enumerable.)

System_CAPS_pubmethodSkipWhile<TSource>(Func<TSource, Boolean>)

Overloaded. Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements.(Defined by Enumerable.)

System_CAPS_pubmethodSkipWhile<TSource>(Func<TSource, Int32, Boolean>)

Overloaded. Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements. The element's index is used in the logic of the predicate function.(Defined by Enumerable.)

System_CAPS_pubmethodSum<TSource>(Func<TSource, Decimal>)

Overloaded. Computes the sum of the sequence of Decimal values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSum<TSource>(Func<TSource, Double>)

Overloaded. Computes the sum of the sequence of Double values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSum<TSource>(Func<TSource, Int32>)

Overloaded. Computes the sum of the sequence of Int32 values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSum<TSource>(Func<TSource, Int64>)

Overloaded. Computes the sum of the sequence of Int64 values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSum<TSource>(Func<TSource, Nullable<Decimal>>)

Overloaded. Computes the sum of the sequence of nullable Decimal values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSum<TSource>(Func<TSource, Nullable<Double>>)

Overloaded. Computes the sum of the sequence of nullable Double values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSum<TSource>(Func<TSource, Nullable<Int32>>)

Overloaded. Computes the sum of the sequence of nullable Int32 values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSum<TSource>(Func<TSource, Nullable<Int64>>)

Overloaded. Computes the sum of the sequence of nullable Int64 values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSum<TSource>(Func<TSource, Nullable<Single>>)

Overloaded. Computes the sum of the sequence of nullable Single values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodSum<TSource>(Func<TSource, Single>)

Overloaded. Computes the sum of the sequence of Single values that are obtained by invoking a transform function on each element of the input sequence.(Defined by Enumerable.)

System_CAPS_pubmethodTake<TSource>(Int32)

Returns a specified number of contiguous elements from the start of a sequence.(Defined by Enumerable.)

System_CAPS_pubmethodTakeWhile<TSource>(Func<TSource, Boolean>)

Overloaded. Returns elements from a sequence as long as a specified condition is true.(Defined by Enumerable.)

System_CAPS_pubmethodTakeWhile<TSource>(Func<TSource, Int32, Boolean>)

Overloaded. Returns elements from a sequence as long as a specified condition is true. The element's index is used in the logic of the predicate function.(Defined by Enumerable.)

System_CAPS_pubmethodToArray<TSource>()

Creates an array from a IEnumerable<T>.(Defined by Enumerable.)

System_CAPS_pubmethodToDictionary<TSource, TKey>(Func<TSource, TKey>)

Overloaded. Creates a Dictionary<TKey, TValue> from an IEnumerable<T> according to a specified key selector function.(Defined by Enumerable.)

System_CAPS_pubmethodToDictionary<TSource, TKey>(Func<TSource, TKey>, IEqualityComparer<TKey>)

Overloaded. Creates a Dictionary<TKey, TValue> from an IEnumerable<T> according to a specified key selector function and key comparer.(Defined by Enumerable.)

System_CAPS_pubmethodToDictionary<TSource, TKey, TElement>(Func<TSource, TKey>, Func<TSource, TElement>)

Overloaded. Creates a Dictionary<TKey, TValue> from an IEnumerable<T> according to specified key selector and element selector functions.(Defined by Enumerable.)

System_CAPS_pubmethodToDictionary<TSource, TKey, TElement>(Func<TSource, TKey>, Func<TSource, TElement>, IEqualityComparer<TKey>)

Overloaded. Creates a Dictionary<TKey, TValue> from an IEnumerable<T> according to a specified key selector function, a comparer, and an element selector function.(Defined by Enumerable.)

System_CAPS_pubmethodToList<TSource>()

Creates a List<T> from an IEnumerable<T>.(Defined by Enumerable.)

System_CAPS_pubmethodToLookup<TSource, TKey>(Func<TSource, TKey>)

Overloaded. Creates a Lookup<TKey, TElement> from an IEnumerable<T> according to a specified key selector function.(Defined by Enumerable.)

System_CAPS_pubmethodToLookup<TSource, TKey>(Func<TSource, TKey>, IEqualityComparer<TKey>)

Overloaded. Creates a Lookup<TKey, TElement> from an IEnumerable<T> according to a specified key selector function and key comparer.(Defined by Enumerable.)

System_CAPS_pubmethodToLookup<TSource, TKey, TElement>(Func<TSource, TKey>, Func<TSource, TElement>)

Overloaded. Creates a Lookup<TKey, TElement> from an IEnumerable<T> according to specified key selector and element selector functions.(Defined by Enumerable.)

System_CAPS_pubmethodToLookup<TSource, TKey, TElement>(Func<TSource, TKey>, Func<TSource, TElement>, IEqualityComparer<TKey>)

Overloaded. Creates a Lookup<TKey, TElement> from an IEnumerable<T> according to a specified key selector function, a comparer and an element selector function.(Defined by Enumerable.)

System_CAPS_pubmethodUnion<TSource>(IEnumerable<TSource>)

Overloaded. Produces the set union of two sequences by using the default equality comparer.(Defined by Enumerable.)

System_CAPS_pubmethodUnion<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)

Overloaded. Produces the set union of two sequences by using a specified IEqualityComparer<T>.(Defined by Enumerable.)

System_CAPS_pubmethodWhere<TSource>(Func<TSource, Boolean>)

Overloaded. Filters a sequence of values based on a predicate.(Defined by Enumerable.)

System_CAPS_pubmethodWhere<TSource>(Func<TSource, Int32, Boolean>)

Overloaded. Filters a sequence of values based on a predicate. Each element's index is used in the logic of the predicate function.(Defined by Enumerable.)

System_CAPS_pubmethodZip<TFirst, TSecond, TResult>(IEnumerable<TSecond>, Func<TFirst, TSecond, TResult>)

Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results.(Defined by Enumerable.)

Remarks

System_CAPS_noteNote

To view the .NET Framework source code for this type, see the Reference Source. You can browse through the source code online, download the reference for offline viewing, and step through the sources (including patches and updates) during debugging; see instructions.

IEnumerable<T> is the base interface for collections in the System.Collections.Generic namespace such as List<T>Dictionary<TKey, TValue>, and Stack<T> and other generic collections such as ObservableCollection<T> and ConcurrentStack<T>. Collections that implement IEnumerable<T> can be enumerated by using the foreach statement. For the non-generic version of this interface, see System.Collections.IEnumerable.

For the non-generic version of this interface, see System.Collections.IEnumerable.

IEnumerable<T> contains a single method that you must implement when implementing this interface; GetEnumerator, which returns an IEnumerator<T> object. The returned IEnumerator<T> provides the ability to iterate through the collection by exposing a Current property.

Notes to Implementers:

IEnumerable<T> is included for parity with non-generic collections; implementing IEnumerable<T> allows a generic collection to be passed to a method that expects an IEnumerable object.

Examples

The following example demonstrates how to implement the IEnumerable<T> interface and how to use that implementation to create a LINQ query. When you implement IEnumerable<T>, you must also implement IEnumerator<T> or, for C# only, you can use the yield (C# Reference) keyword. Implementing IEnumerator<T> also requires IDisposable to be implemented, which you will see in this example.

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class App
{
    // Excercise the Iterator and show that it's more
    // performant.
    public static void Main()
    {
        TestStreamReaderEnumerable();
        Console.WriteLine("---");
        TestReadingFile();
    }

    public static void TestStreamReaderEnumerable()
	{
		// Check the memory before the iterator is used.
		long memoryBefore = GC.GetTotalMemory(true);
      IEnumerable<String> stringsFound;
		// Open a file with the StreamReaderEnumerable and check for a string.
      try {
         stringsFound =
               from line in new StreamReaderEnumerable(@"c:\temp\tempFile.txt")
               where line.Contains("string to search for")
               select line;
         Console.WriteLine("Found: " + stringsFound.Count());
      }
      catch (FileNotFoundException) {
         Console.WriteLine(@"This example requires a file named C:\temp\tempFile.txt.");
         return;
      }

		// Check the memory after the iterator and output it to the console.
		long memoryAfter = GC.GetTotalMemory(false);
		Console.WriteLine("Memory Used With Iterator = \t"
            + string.Format(((memoryAfter - memoryBefore) / 1000).ToString(), "n") + "kb");
	}

    public static void TestReadingFile()
	{
		long memoryBefore = GC.GetTotalMemory(true);
      StreamReader sr;
      try {
         sr = File.OpenText("c:\\temp\\tempFile.txt");
      }
      catch (FileNotFoundException) {
         Console.WriteLine(@"This example requires a file named C:\temp\tempFile.txt.");
         return;
      }

        // Add the file contents to a generic list of strings.
		List<string> fileContents = new List<string>();
		while (!sr.EndOfStream) {
			fileContents.Add(sr.ReadLine());
		}

		// Check for the string.
		var stringsFound = 
            from line in fileContents
            where line.Contains("string to search for")
            select line;

        sr.Close();
        Console.WriteLine("Found: " + stringsFound.Count());

		// Check the memory after when the iterator is not used, and output it to the console.
		long memoryAfter = GC.GetTotalMemory(false);
		Console.WriteLine("Memory Used Without Iterator = \t" + 
            string.Format(((memoryAfter - memoryBefore) / 1000).ToString(), "n") + "kb");
	}
}

// A custom class that implements IEnumerable(T). When you implement IEnumerable(T), 
// you must also implement IEnumerable and IEnumerator(T).
public class StreamReaderEnumerable : IEnumerable<string>
{
    private string _filePath;
    public StreamReaderEnumerable(string filePath)
    {
        _filePath = filePath;
    }

    // Must implement GetEnumerator, which returns a new StreamReaderEnumerator.
    public IEnumerator<string> GetEnumerator()
    {
        return new StreamReaderEnumerator(_filePath);
    }

    // Must also implement IEnumerable.GetEnumerator, but implement as a private method.
    private IEnumerator GetEnumerator1()
    {
        return this.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator1();
    }
}

// When you implement IEnumerable(T), you must also implement IEnumerator(T), 
// which will walk through the contents of the file one line at a time.
// Implementing IEnumerator(T) requires that you implement IEnumerator and IDisposable.
public class StreamReaderEnumerator : IEnumerator<string>
{
    private StreamReader _sr;
    public StreamReaderEnumerator(string filePath)
    {
        _sr = new StreamReader(filePath);
    }

    private string _current;
    // Implement the IEnumerator(T).Current publicly, but implement 
    // IEnumerator.Current, which is also required, privately.
    public string Current
    {

        get
        {
            if (_sr == null || _current == null)
            {
                throw new InvalidOperationException();
            }

            return _current;
        }
    }

    private object Current1
    {

        get { return this.Current; }
    }

    object IEnumerator.Current
    {
        get { return Current1; }
    }

    // Implement MoveNext and Reset, which are required by IEnumerator.
    public bool MoveNext()
    {
        _current = _sr.ReadLine();
        if (_current == null)
            return false;
        return true;
    }

    public void Reset()
    {
        _sr.DiscardBufferedData();
        _sr.BaseStream.Seek(0, SeekOrigin.Begin);
        _current = null;
    }

    // Implement IDisposable, which is also implemented by IEnumerator(T).
    private bool disposedValue = false;
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposedValue)
        {
            if (disposing)
            {
                // Dispose of managed resources.
            }
            _current = null;
            if (_sr != null) {
               _sr.Close();
               _sr.Dispose();
            }
        }

        this.disposedValue = true;
    }

     ~StreamReaderEnumerator()
    {
        Dispose(false);
    }
}
// This example displays output similar to the following:
//       Found: 2
//       Memory Used With Iterator =     33kb
//       ---
//       Found: 2
//       Memory Used Without Iterator =  206kb

For another C# example that demonstrates how to implement the IEnumerable<T> interface, see the Generics Sample. This sample uses the yield keyword instead of implementing IEnumerator<T>.







'프로그래밍 > C#' 카테고리의 다른 글

Using the Visual Studio Development Environment for C#  (0) 2017.02.14
Getting Started with C#  (0) 2017.02.13
C# Keywords - Types  (0) 2016.12.29
helpful classes  (0) 2016.11.24
Operators  (0) 2016.11.14
:
Posted by 지훈2