달력

5

« 2025/5 »

  • 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

ObservableCollection<T> 클래스


https://msdn.microsoft.com/ko-kr/library/ms668604(v=vs.110).aspx


Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.

네임스페이스:   System.Collections.ObjectModel
어셈블리:  System(System.dll에 있음)


[SerializableAttribute]
public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, 
	INotifyPropertyChanged

형식 매개 변수

T

The type of elements in the collection.

이름설명
System_CAPS_pubmethodObservableCollection<T>()

Initializes a new instance of the ObservableCollection<T> class.

System_CAPS_pubmethodObservableCollection<T>(IEnumerable<T>)

Initializes a new instance of the ObservableCollection<T> class that contains elements copied from the specified collection.

System_CAPS_pubmethodObservableCollection<T>(List<T>)

Initializes a new instance of the ObservableCollection<T> class that contains elements copied from the specified list.

이름설명
System_CAPS_pubpropertyCount

Gets the number of elements actually contained in the Collection<T>.(Collection<T>에서 상속됨)

System_CAPS_pubpropertyItem[Int32]

Gets or sets the element at the specified index.(Collection<T>에서 상속됨)

System_CAPS_protpropertyItems

Gets a IList<T> wrapper around the Collection<T>.(Collection<T>에서 상속됨)

이름설명
System_CAPS_pubmethodAdd(T)

Adds an object to the end of the Collection<T>.(Collection<T>에서 상속됨)

System_CAPS_protmethodBlockReentrancy()

Disallows reentrant attempts to change this collection.

System_CAPS_protmethodCheckReentrancy()

Checks for reentrant attempts to change this collection.

System_CAPS_pubmethodClear()

Removes all elements from the Collection<T>.(Collection<T>에서 상속됨)

System_CAPS_protmethodClearItems()

Removes all items from the collection.(Collection<T>.ClearItems()을(를) 재정의함)

System_CAPS_pubmethodContains(T)

Determines whether an element is in the Collection<T>.(Collection<T>에서 상속됨)

System_CAPS_pubmethodCopyTo(T[], Int32)

Copies the entire Collection<T> to a compatible one-dimensional Array, starting at the specified index of the target array.(Collection<T>에서 상속됨)

System_CAPS_pubmethodEquals(Object)

Determines whether the specified object is equal to the current object.(Object에서 상속됨)

System_CAPS_protmethodFinalize()

Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.(Object에서 상속됨)

System_CAPS_pubmethodGetEnumerator()

Returns an enumerator that iterates through the Collection<T>.(Collection<T>에서 상속됨)

System_CAPS_pubmethodGetHashCode()

Serves as the default hash function.(Object에서 상속됨)

System_CAPS_pubmethodGetType()

Gets the Type of the current instance.(Object에서 상속됨)

System_CAPS_pubmethodIndexOf(T)

Searches for the specified object and returns the zero-based index of the first occurrence within the entire Collection<T>.(Collection<T>에서 상속됨)

System_CAPS_pubmethodInsert(Int32, T)

Inserts an element into the Collection<T> at the specified index.(Collection<T>에서 상속됨)

System_CAPS_protmethodInsertItem(Int32, T)

Inserts an item into the collection at the specified index.(Collection<T>.InsertItem(Int32, T)을(를) 재정의함)

System_CAPS_protmethodMemberwiseClone()

Creates a shallow copy of the current Object.(Object에서 상속됨)

System_CAPS_pubmethodMove(Int32, Int32)

Moves the item at the specified index to a new location in the collection.

System_CAPS_protmethodMoveItem(Int32, Int32)

Moves the item at the specified index to a new location in the collection.

System_CAPS_protmethodOnCollectionChanged(NotifyCollectionChangedEventArgs)

Raises the CollectionChanged event with the provided arguments.

System_CAPS_protmethodOnPropertyChanged(PropertyChangedEventArgs)

Raises the PropertyChanged event with the provided arguments.

System_CAPS_pubmethodRemove(T)

Removes the first occurrence of a specific object from the Collection<T>.(Collection<T>에서 상속됨)

System_CAPS_pubmethodRemoveAt(Int32)

Removes the element at the specified index of the Collection<T>.(Collection<T>에서 상속됨)

System_CAPS_protmethodRemoveItem(Int32)

Removes the item at the specified index of the collection.(Collection<T>.RemoveItem(Int32)을(를) 재정의함)

System_CAPS_protmethodSetItem(Int32, T)

Replaces the element at the specified index.(Collection<T>.SetItem(Int32, T)을(를) 재정의함)

System_CAPS_pubmethodToString()

Returns a string that represents the current object.(Object에서 상속됨)

이름설명
System_CAPS_pubeventCollectionChanged

Occurs when an item is added, removed, changed, moved, or the entire list is refreshed.

System_CAPS_proteventPropertyChanged

Occurs when a property value changes.

이름설명
System_CAPS_pubinterfaceSystem_CAPS_priveventINotifyPropertyChanged.PropertyChanged

Occurs when a property value changes.

System_CAPS_pubinterfaceSystem_CAPS_privmethodICollection.CopyTo(Array, Int32)

Copies the elements of the ICollection to an Array, starting at a particular Array index.(Collection<T>에서 상속됨)

System_CAPS_pubinterfaceSystem_CAPS_privmethodIEnumerable.GetEnumerator()

Returns an enumerator that iterates through a collection.(Collection<T>에서 상속됨)

System_CAPS_pubinterfaceSystem_CAPS_privmethodIList.Add(Object)

Adds an item to the IList.(Collection<T>에서 상속됨)

System_CAPS_pubinterfaceSystem_CAPS_privmethodIList.Contains(Object)

Determines whether the IList contains a specific value.(Collection<T>에서 상속됨)

System_CAPS_pubinterfaceSystem_CAPS_privmethodIList.IndexOf(Object)

Determines the index of a specific item in the IList.(Collection<T>에서 상속됨)

System_CAPS_pubinterfaceSystem_CAPS_privmethodIList.Insert(Int32, Object)

Inserts an item into the IList at the specified index.(Collection<T>에서 상속됨)

System_CAPS_pubinterfaceSystem_CAPS_privmethodIList.Remove(Object)

Removes the first occurrence of a specific object from the IList.(Collection<T>에서 상속됨)

System_CAPS_pubinterfaceSystem_CAPS_privpropertyICollection<T>.IsReadOnly

Gets a value indicating whether the ICollection<T> is read-only.(Collection<T>에서 상속됨)

System_CAPS_pubinterfaceSystem_CAPS_privpropertyICollection.IsSynchronized

Gets a value indicating whether access to the ICollection is synchronized (thread safe).(Collection<T>에서 상속됨)

System_CAPS_pubinterfaceSystem_CAPS_privpropertyICollection.SyncRoot

Gets an object that can be used to synchronize access to the ICollection.(Collection<T>에서 상속됨)

System_CAPS_pubinterfaceSystem_CAPS_privpropertyIList.IsFixedSize

Gets a value indicating whether the IList has a fixed size.(Collection<T>에서 상속됨)

System_CAPS_pubinterfaceSystem_CAPS_privpropertyIList.IsReadOnly

Gets a value indicating whether the IList is read-only.(Collection<T>에서 상속됨)

System_CAPS_pubinterfaceSystem_CAPS_privpropertyIList.Item[Int32]

Gets or sets the element at the specified index.(Collection<T>에서 상속됨)

이름설명
System_CAPS_pubmethodAggregate<T>(Func<T, T, T>)

오버로드되었습니다. Applies an accumulator function over a sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodAggregate<T, TAccumulate>(TAccumulate, Func<TAccumulate, T, TAccumulate>)

오버로드되었습니다. Applies an accumulator function over a sequence. The specified seed value is used as the initial accumulator value.(Enumerable에서 정의됨)

System_CAPS_pubmethodAggregate<T, TAccumulate, TResult>(TAccumulate, Func<TAccumulate, T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodAll<T>(Func<T, Boolean>)

Determines whether all elements of a sequence satisfy a condition.(Enumerable에서 정의됨)

System_CAPS_pubmethodAny<T>()

오버로드되었습니다. Determines whether a sequence contains any elements.(Enumerable에서 정의됨)

System_CAPS_pubmethodAny<T>(Func<T, Boolean>)

오버로드되었습니다. Determines whether any element of a sequence satisfies a condition.(Enumerable에서 정의됨)

System_CAPS_pubmethodAsEnumerable<T>()

Returns the input typed as IEnumerable<T>.(Enumerable에서 정의됨)

System_CAPS_pubmethodAsParallel()

오버로드되었습니다. Enables parallelization of a query.(ParallelEnumerable에서 정의됨)

System_CAPS_pubmethodAsParallel<T>()

오버로드되었습니다. Enables parallelization of a query.(ParallelEnumerable에서 정의됨)

System_CAPS_pubmethodAsQueryable()

오버로드되었습니다. Converts an IEnumerable to an IQueryable.(Queryable에서 정의됨)

System_CAPS_pubmethodAsQueryable<T>()

오버로드되었습니다. Converts a generic IEnumerable<T> to a generic IQueryable<T>.(Queryable에서 정의됨)

System_CAPS_pubmethodAverage<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodAverage<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodAverage<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodAverage<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodAverage<T>(Func<T, Nullable<Decimal>>)

오버로드되었습니다. Computes the average of a sequence of nullable Decimalvalues that are obtained by invoking a transform function on each element of the input sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodAverage<T>(Func<T, Nullable<Double>>)

오버로드되었습니다. Computes the average of a sequence of nullable Doublevalues that are obtained by invoking a transform function on each element of the input sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodAverage<T>(Func<T, Nullable<Int32>>)

오버로드되었습니다. Computes the average of a sequence of nullable Int32values that are obtained by invoking a transform function on each element of the input sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodAverage<T>(Func<T, Nullable<Int64>>)

오버로드되었습니다. Computes the average of a sequence of nullable Int64values that are obtained by invoking a transform function on each element of the input sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodAverage<T>(Func<T, Nullable<Single>>)

오버로드되었습니다. Computes the average of a sequence of nullable Singlevalues that are obtained by invoking a transform function on each element of the input sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodAverage<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodCast<TResult>()

Casts the elements of an IEnumerable to the specified type.(Enumerable에서 정의됨)

System_CAPS_pubmethodConcat<T>(IEnumerable<T>)

Concatenates two sequences.(Enumerable에서 정의됨)

System_CAPS_pubmethodContains<T>(T)

오버로드되었습니다. Determines whether a sequence contains a specified element by using the default equality comparer.(Enumerable에서 정의됨)

System_CAPS_pubmethodContains<T>(T, IEqualityComparer<T>)

오버로드되었습니다. Determines whether a sequence contains a specified element by using a specified IEqualityComparer<T>.(Enumerable에서 정의됨)

System_CAPS_pubmethodCount<T>()

오버로드되었습니다. Returns the number of elements in a sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodCount<T>(Func<T, Boolean>)

오버로드되었습니다. Returns a number that represents how many elements in the specified sequence satisfy a condition.(Enumerable에서 정의됨)

System_CAPS_pubmethodDefaultIfEmpty<T>()

오버로드되었습니다. Returns the elements of the specified sequence or the type parameter's default value in a singleton collection if the sequence is empty.(Enumerable에서 정의됨)

System_CAPS_pubmethodDefaultIfEmpty<T>(T)

오버로드되었습니다. Returns the elements of the specified sequence or the specified value in a singleton collection if the sequence is empty.(Enumerable에서 정의됨)

System_CAPS_pubmethodDistinct<T>()

오버로드되었습니다. Returns distinct elements from a sequence by using the default equality comparer to compare values.(Enumerable에서 정의됨)

System_CAPS_pubmethodDistinct<T>(IEqualityComparer<T>)

오버로드되었습니다. Returns distinct elements from a sequence by using a specified IEqualityComparer<T> to compare values.(Enumerable에서 정의됨)

System_CAPS_pubmethodElementAt<T>(Int32)

Returns the element at a specified index in a sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodElementAtOrDefault<T>(Int32)

Returns the element at a specified index in a sequence or a default value if the index is out of range.(Enumerable에서 정의됨)

System_CAPS_pubmethodExcept<T>(IEnumerable<T>)

오버로드되었습니다. Produces the set difference of two sequences by using the default equality comparer to compare values.(Enumerable에서 정의됨)

System_CAPS_pubmethodExcept<T>(IEnumerable<T>, IEqualityComparer<T>)

오버로드되었습니다. Produces the set difference of two sequences by using the specified IEqualityComparer<T> to compare values.(Enumerable에서 정의됨)

System_CAPS_pubmethodFirst<T>()

오버로드되었습니다. Returns the first element of a sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodFirst<T>(Func<T, Boolean>)

오버로드되었습니다. Returns the first element in a sequence that satisfies a specified condition.(Enumerable에서 정의됨)

System_CAPS_pubmethodFirstOrDefault<T>()

오버로드되었습니다. Returns the first element of a sequence, or a default value if the sequence contains no elements.(Enumerable에서 정의됨)

System_CAPS_pubmethodFirstOrDefault<T>(Func<T, Boolean>)

오버로드되었습니다. Returns the first element of the sequence that satisfies a condition or a default value if no such element is found.(Enumerable에서 정의됨)

System_CAPS_pubmethodGroupBy<T, TKey>(Func<T, TKey>)

오버로드되었습니다. Groups the elements of a sequence according to a specified key selector function.(Enumerable에서 정의됨)

System_CAPS_pubmethodGroupBy<T, TKey>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodGroupBy<T, TKey, TElement>(Func<T, TKey>, Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodGroupBy<T, TKey, TElement>(Func<T, TKey>, Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodGroupBy<T, TKey, TResult>(Func<T, TKey>, Func<TKey, IEnumerable<T>, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodGroupBy<T, TKey, TResult>(Func<T, TKey>, Func<TKey, IEnumerable<T>, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodGroupBy<T, TKey, TElement, TResult>(Func<T, TKey>, Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodGroupBy<T, TKey, TElement, TResult>(Func<T, TKey>, Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodGroupJoin<T, TInner, TKey, TResult>(IEnumerable<TInner>, Func<T, TKey>, Func<TInner, TKey>, Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodGroupJoin<T, TInner, TKey, TResult>(IEnumerable<TInner>, Func<T, TKey>, Func<TInner, TKey>, Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodIntersect<T>(IEnumerable<T>)

오버로드되었습니다. Produces the set intersection of two sequences by using the default equality comparer to compare values.(Enumerable에서 정의됨)

System_CAPS_pubmethodIntersect<T>(IEnumerable<T>, IEqualityComparer<T>)

오버로드되었습니다. Produces the set intersection of two sequences by using the specified IEqualityComparer<T> to compare values.(Enumerable에서 정의됨)

System_CAPS_pubmethodJoin<T, TInner, TKey, TResult>(IEnumerable<TInner>, Func<T, TKey>, Func<TInner, TKey>, Func<T, TInner, TResult>)

오버로드되었습니다. Correlates the elements of two sequences based on matching keys. The default equality comparer is used to compare keys.(Enumerable에서 정의됨)

System_CAPS_pubmethodJoin<T, TInner, TKey, TResult>(IEnumerable<TInner>, Func<T, TKey>, Func<TInner, TKey>, Func<T, TInner, TResult>, IEqualityComparer<TKey>)

오버로드되었습니다. Correlates the elements of two sequences based on matching keys. A specified IEqualityComparer<T> is used to compare keys.(Enumerable에서 정의됨)

System_CAPS_pubmethodLast<T>()

오버로드되었습니다. Returns the last element of a sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodLast<T>(Func<T, Boolean>)

오버로드되었습니다. Returns the last element of a sequence that satisfies a specified condition.(Enumerable에서 정의됨)

System_CAPS_pubmethodLastOrDefault<T>()

오버로드되었습니다. Returns the last element of a sequence, or a default value if the sequence contains no elements.(Enumerable에서 정의됨)

System_CAPS_pubmethodLastOrDefault<T>(Func<T, Boolean>)

오버로드되었습니다. Returns the last element of a sequence that satisfies a condition or a default value if no such element is found.(Enumerable에서 정의됨)

System_CAPS_pubmethodLongCount<T>()

오버로드되었습니다. Returns an Int64 that represents the total number of elements in a sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodLongCount<T>(Func<T, Boolean>)

오버로드되었습니다. Returns an Int64 that represents how many elements in a sequence satisfy a condition.(Enumerable에서 정의됨)

System_CAPS_pubmethodMax<T>()

오버로드되었습니다. Returns the maximum value in a generic sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodMax<T>(Func<T, Decimal>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the maximum Decimal value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMax<T>(Func<T, Double>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the maximum Double value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMax<T>(Func<T, Int32>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the maximum Int32 value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMax<T>(Func<T, Int64>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the maximum Int64 value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMax<T>(Func<T, Nullable<Decimal>>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the maximum nullable Decimal value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMax<T>(Func<T, Nullable<Double>>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the maximum nullable Double value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMax<T>(Func<T, Nullable<Int32>>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the maximum nullable Int32 value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMax<T>(Func<T, Nullable<Int64>>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the maximum nullable Int64 value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMax<T>(Func<T, Nullable<Single>>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the maximum nullable Single value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMax<T>(Func<T, Single>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the maximum Single value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMax<T, TResult>(Func<T, TResult>)

오버로드되었습니다. Invokes a transform function on each element of a generic sequence and returns the maximum resulting value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMin<T>()

오버로드되었습니다. Returns the minimum value in a generic sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodMin<T>(Func<T, Decimal>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the minimum Decimal value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMin<T>(Func<T, Double>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the minimum Double value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMin<T>(Func<T, Int32>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the minimum Int32 value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMin<T>(Func<T, Int64>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the minimum Int64 value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMin<T>(Func<T, Nullable<Decimal>>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the minimum nullable Decimal value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMin<T>(Func<T, Nullable<Double>>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the minimum nullable Double value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMin<T>(Func<T, Nullable<Int32>>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the minimum nullable Int32 value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMin<T>(Func<T, Nullable<Int64>>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the minimum nullable Int64 value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMin<T>(Func<T, Nullable<Single>>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the minimum nullable Single value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMin<T>(Func<T, Single>)

오버로드되었습니다. Invokes a transform function on each element of a sequence and returns the minimum Single value.(Enumerable에서 정의됨)

System_CAPS_pubmethodMin<T, TResult>(Func<T, TResult>)

오버로드되었습니다. Invokes a transform function on each element of a generic sequence and returns the minimum resulting value.(Enumerable에서 정의됨)

System_CAPS_pubmethodOfType<TResult>()

Filters the elements of an IEnumerable based on a specified type.(Enumerable에서 정의됨)

System_CAPS_pubmethodOrderBy<T, TKey>(Func<T, TKey>)

오버로드되었습니다. Sorts the elements of a sequence in ascending order according to a key.(Enumerable에서 정의됨)

System_CAPS_pubmethodOrderBy<T, TKey>(Func<T, TKey>, IComparer<TKey>)

오버로드되었습니다. Sorts the elements of a sequence in ascending order by using a specified comparer.(Enumerable에서 정의됨)

System_CAPS_pubmethodOrderByDescending<T, TKey>(Func<T, TKey>)

오버로드되었습니다. Sorts the elements of a sequence in descending order according to a key.(Enumerable에서 정의됨)

System_CAPS_pubmethodOrderByDescending<T, TKey>(Func<T, TKey>, IComparer<TKey>)

오버로드되었습니다. Sorts the elements of a sequence in descending order by using a specified comparer.(Enumerable에서 정의됨)

System_CAPS_pubmethodReverse<T>()

Inverts the order of the elements in a sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodSelect<T, TResult>(Func<T, TResult>)

오버로드되었습니다. Projects each element of a sequence into a new form.(Enumerable에서 정의됨)

System_CAPS_pubmethodSelect<T, TResult>(Func<T, Int32, TResult>)

오버로드되었습니다. Projects each element of a sequence into a new form by incorporating the element's index.(Enumerable에서 정의됨)

System_CAPS_pubmethodSelectMany<T, TResult>(Func<T, IEnumerable<TResult>>)

오버로드되었습니다. Projects each element of a sequence to an IEnumerable<T> and flattens the resulting sequences into one sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodSelectMany<T, TResult>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodSelectMany<T, TCollection, TResult>(Func<T, IEnumerable<TCollection>>, Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodSelectMany<T, TCollection, TResult>(Func<T, Int32, IEnumerable<TCollection>>, Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodSequenceEqual<T>(IEnumerable<T>)

오버로드되었습니다. Determines whether two sequences are equal by comparing the elements by using the default equality comparer for their type.(Enumerable에서 정의됨)

System_CAPS_pubmethodSequenceEqual<T>(IEnumerable<T>, IEqualityComparer<T>)

오버로드되었습니다. Determines whether two sequences are equal by comparing their elements by using a specified IEqualityComparer<T>.(Enumerable에서 정의됨)

System_CAPS_pubmethodSingle<T>()

오버로드되었습니다. Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodSingle<T>(Func<T, Boolean>)

오버로드되었습니다. Returns the only element of a sequence that satisfies a specified condition, and throws an exception if more than one such element exists.(Enumerable에서 정의됨)

System_CAPS_pubmethodSingleOrDefault<T>()

오버로드되었습니다. 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodSingleOrDefault<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodSkip<T>(Int32)

Bypasses a specified number of elements in a sequence and then returns the remaining elements.(Enumerable에서 정의됨)

System_CAPS_pubmethodSkipWhile<T>(Func<T, Boolean>)

오버로드되었습니다. Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements.(Enumerable에서 정의됨)

System_CAPS_pubmethodSkipWhile<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodSum<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodSum<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodSum<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodSum<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodSum<T>(Func<T, Nullable<Decimal>>)

오버로드되었습니다. Computes the sum of the sequence of nullable Decimalvalues that are obtained by invoking a transform function on each element of the input sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodSum<T>(Func<T, Nullable<Double>>)

오버로드되었습니다. Computes the sum of the sequence of nullable Doublevalues that are obtained by invoking a transform function on each element of the input sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodSum<T>(Func<T, Nullable<Int32>>)

오버로드되었습니다. Computes the sum of the sequence of nullable Int32values that are obtained by invoking a transform function on each element of the input sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodSum<T>(Func<T, Nullable<Int64>>)

오버로드되었습니다. Computes the sum of the sequence of nullable Int64values that are obtained by invoking a transform function on each element of the input sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodSum<T>(Func<T, Nullable<Single>>)

오버로드되었습니다. Computes the sum of the sequence of nullable Singlevalues that are obtained by invoking a transform function on each element of the input sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodSum<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodTake<T>(Int32)

Returns a specified number of contiguous elements from the start of a sequence.(Enumerable에서 정의됨)

System_CAPS_pubmethodTakeWhile<T>(Func<T, Boolean>)

오버로드되었습니다. Returns elements from a sequence as long as a specified condition is true.(Enumerable에서 정의됨)

System_CAPS_pubmethodTakeWhile<T>(Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodToArray<T>()

Creates an array from a IEnumerable<T>.(Enumerable에서 정의됨)

System_CAPS_pubmethodToDictionary<T, TKey>(Func<T, TKey>)

오버로드되었습니다. Creates a Dictionary<TKey, TValue> from an IEnumerable<T> according to a specified key selector function.(Enumerable에서 정의됨)

System_CAPS_pubmethodToDictionary<T, TKey>(Func<T, TKey>, IEqualityComparer<TKey>)

오버로드되었습니다. Creates a Dictionary<TKey, TValue> from an IEnumerable<T> according to a specified key selector function and key comparer.(Enumerable에서 정의됨)

System_CAPS_pubmethodToDictionary<T, TKey, TElement>(Func<T, TKey>, Func<T, TElement>)

오버로드되었습니다. Creates a Dictionary<TKey, TValue> from an IEnumerable<T> according to specified key selector and element selector functions.(Enumerable에서 정의됨)

System_CAPS_pubmethodToDictionary<T, TKey, TElement>(Func<T, TKey>, Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodToList<T>()

Creates a List<T> from an IEnumerable<T>.(Enumerable에서 정의됨)

System_CAPS_pubmethodToLookup<T, TKey>(Func<T, TKey>)

오버로드되었습니다. Creates a Lookup<TKey, TElement> from an IEnumerable<T> according to a specified key selector function.(Enumerable에서 정의됨)

System_CAPS_pubmethodToLookup<T, TKey>(Func<T, TKey>, IEqualityComparer<TKey>)

오버로드되었습니다. Creates a Lookup<TKey, TElement> from an IEnumerable<T> according to a specified key selector function and key comparer.(Enumerable에서 정의됨)

System_CAPS_pubmethodToLookup<T, TKey, TElement>(Func<T, TKey>, Func<T, TElement>)

오버로드되었습니다. Creates a Lookup<TKey, TElement> from an IEnumerable<T> according to specified key selector and element selector functions.(Enumerable에서 정의됨)

System_CAPS_pubmethodToLookup<T, TKey, TElement>(Func<T, TKey>, Func<T, 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.(Enumerable에서 정의됨)

System_CAPS_pubmethodUnion<T>(IEnumerable<T>)

오버로드되었습니다. Produces the set union of two sequences by using the default equality comparer.(Enumerable에서 정의됨)

System_CAPS_pubmethodUnion<T>(IEnumerable<T>, IEqualityComparer<T>)

오버로드되었습니다. Produces the set union of two sequences by using a specified IEqualityComparer<T>.(Enumerable에서 정의됨)

System_CAPS_pubmethodWhere<T>(Func<T, Boolean>)

오버로드되었습니다. Filters a sequence of values based on a predicate.(Enumerable에서 정의됨)

System_CAPS_pubmethodWhere<T>(Func<T, Int32, Boolean>)

오버로드되었습니다. Filters a sequence of values based on a predicate. Each element's index is used in the logic of the predicate function.(Enumerable에서 정의됨)

System_CAPS_pubmethodZip<T, TSecond, TResult>(IEnumerable<TSecond>, Func<T, TSecond, TResult>)

Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results.(Enumerable에서 정의됨)

In many cases the data that you work with is a collection of objects. For example, a common scenario in data binding is to use an ItemsControl such as a ListBoxListView, or TreeView to display a collection of records.

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 the CollectionChanged event, 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 implements the INotifyCollectionChanged interface.

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. Implementing IList provides the best performance with the data binding engine.

System_CAPS_note참고

To fully support transferring data values from binding source objects to binding targets, each object in your collection that supports bindable properties must implement an appropriate property changed notification mechanism such as the INotifyPropertyChangedinterface.

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

ObservableCollection<T> can be used as a XAML object element in Windows Presentation Foundation (WPF), in versions 3.0 and 3.5.However, the usage has substantial limitations.

  • ObservableCollection<T> must be the root element, because the that must be used to specify the constrained type of the generic ObservableCollection<T> is only supported on the object element for the root element.

  • You must declare an (which entails that the build action for this XAML file must be Page or some other build action that compiles the XAML).

  • ObservableCollection<T> is in a namespace and assembly that are not initially mapped to the default XML namespace. You must map a prefix for the namespace and assembly, and then use that prefix on the object element tag for ObservableCollection<T>.

A more straightforward way to use ObservableCollection<T> capabilities from XAML in an application is to declare your own non-generic custom collection class that derives from ObservableCollection<T>, and constrains it to a specific type. Then map the assembly that contains this class, and reference it as an object element in your XAML.



INotifyPropertyChanged Interface


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


Notifies clients that a property value has changed.

Namespace:   System.ComponentModel
Assembly:  System (in System.dll)

Syntax

public interface INotifyPropertyChanged

Events

NameDescription
System_CAPS_pubeventPropertyChanged

Occurs when a property value changes.

Remarks

The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed.

For example, consider a Person object with a property called FirstName. To provide generic property-change notification, the Person type implements the INotifyPropertyChanged interface and raises a PropertyChanged event when FirstName is changed.

For change notification to occur in a binding between a bound client and a data source, your bound type should either:

  • Implement the INotifyPropertyChanged interface (preferred).

  • Provide a change event for each property of the bound type.

Do not do both.

Examples

The following code example demonstrates the how to implement the INotifyPropertyChanged interface. When you run this example, you will notice the bound DataGridView control reflects the change in the data source without requiring the binding to be reset.

If you use the CallerMemberName attribute, calls to the NotifyPropertyChanged method don't have to specify the property name as a string argument. For more information, see Caller Information (C# and Visual Basic).

Replace the code in your Form1 with the following code and then change the namespace to the name of your project. As an alternative, you can name your project with the namespace name below when you create it.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Windows.Forms;

// Either change the following namespace to the name of your project, 
// or name your project with the following name when you create it.
namespace TestNotifyPropertyChangedCS
{
    // This form demonstrates using a BindingSource to bind
    // a list to a DataGridView control. The list does not
    // raise change notifications. However the DemoCustomer type 
    // in the list does.
    public partial class Form1 : Form
    {
        // This button causes the value of a list element to be changed.
        private Button changeItemBtn = new Button();

        // This DataGridView control displays the contents of the list.
        private DataGridView customersDataGridView = new DataGridView();

        // This BindingSource binds the list to the DataGridView control.
        private BindingSource customersBindingSource = new BindingSource();

        public Form1()
        {
            InitializeComponent();

            // Set up the "Change Item" button.
            this.changeItemBtn.Text = "Change Item";
            this.changeItemBtn.Dock = DockStyle.Bottom;
            this.changeItemBtn.Click +=
                new EventHandler(changeItemBtn_Click);
            this.Controls.Add(this.changeItemBtn);

            // Set up the DataGridView.
            customersDataGridView.Dock = DockStyle.Top;
            this.Controls.Add(customersDataGridView);

            this.Size = new Size(400, 200);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // Create and populate the list of DemoCustomer objects
            // which will supply data to the DataGridView.
            BindingList<DemoCustomer> customerList = new BindingList<DemoCustomer>();
            customerList.Add(DemoCustomer.CreateNewCustomer());
            customerList.Add(DemoCustomer.CreateNewCustomer());
            customerList.Add(DemoCustomer.CreateNewCustomer());

            // Bind the list to the BindingSource.
            this.customersBindingSource.DataSource = customerList;

            // Attach the BindingSource to the DataGridView.
            this.customersDataGridView.DataSource =
                this.customersBindingSource;

        }

        // Change the value of the CompanyName property for the first 
        // item in the list when the "Change Item" button is clicked.
        void changeItemBtn_Click(object sender, EventArgs e)
        {
            // Get a reference to the list from the BindingSource.
            BindingList<DemoCustomer> customerList =
                this.customersBindingSource.DataSource as BindingList<DemoCustomer>;

            // Change the value of the CompanyName property for the 
            // first item in the list.
            customerList[0].CustomerName = "Tailspin Toys";
            customerList[0].PhoneNumber = "(708)555-0150";
        }

    }

    // This is a simple customer class that 
    // implements the IPropertyChange interface.
    public class DemoCustomer : INotifyPropertyChanged
    {
        // These fields hold the values for the public properties.
        private Guid idValue = Guid.NewGuid();
        private string customerNameValue = String.Empty;
        private string phoneNumberValue = String.Empty;

        public event PropertyChangedEventHandler PropertyChanged;

        // This method is called by the Set accessor of each property.
        // The CallerMemberName attribute that is applied to the optional propertyName
        // parameter causes the property name of the caller to be substituted as an argument.
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        // The constructor is private to enforce the factory pattern.
        private DemoCustomer()
        {
            customerNameValue = "Customer";
            phoneNumberValue = "(312)555-0100";
        }

        // This is the public factory method.
        public static DemoCustomer CreateNewCustomer()
        {
            return new DemoCustomer();
        }

        // This property represents an ID, suitable
        // for use as a primary key in a database.
        public Guid ID
        {
            get
            {
                return this.idValue;
            }
        }

        public string CustomerName
        {
            get
            {
                return this.customerNameValue;
            }

            set
            {
                if (value != this.customerNameValue)
                {
                    this.customerNameValue = value;
                    NotifyPropertyChanged();
                }
            }
        }

        public string PhoneNumber
        {
            get
            {
                return this.phoneNumberValue;
            }

            set
            {
                if (value != this.phoneNumberValue)
                {
                    this.phoneNumberValue = value;
                    NotifyPropertyChanged();
                }
            }
        }
    }
}




Caller Information


https://msdn.microsoft.com/ko-kr/library/hh534540(v=vs.110).aspx


By using Caller Info attributes, you can obtain information about the caller to a method. You can obtain file path of the source code, the line number in the source code, and the member name of the caller. This information is helpful for tracing, debugging, and creating diagnostic tools.

To obtain this information, you use attributes that are applied to optional parameters, each of which has a default value. The following table lists the Caller Info attributes that are defined in the System.Runtime.CompilerServices namespace:

Attribute

Description

Type

CallerFilePathAttribute

Full path of the source file that contains the caller. This is the file path at compile time.

String

CallerLineNumberAttribute

Line number in the source file at which the method is called.

Integer

CallerMemberNameAttribute

Method or property name of the caller. See Member Names later in this topic.

String

The following example shows how to use Caller Info attributes. On each call to the TraceMessage method, the caller information is substituted as arguments to the optional parameters.

// using System.Runtime.CompilerServices
// using System.Diagnostics;

public void DoProcessing()
{
    TraceMessage("Something happened.");
}

public void TraceMessage(string message,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string sourceFilePath = "",
        [CallerLineNumber] int sourceLineNumber = 0)
{
    Trace.WriteLine("message: " + message);
    Trace.WriteLine("member name: " + memberName);
    Trace.WriteLine("source file path: " + sourceFilePath);
    Trace.WriteLine("source line number: " + sourceLineNumber);
}

// Sample Output:
//  message: Something happened.
//  member name: DoProcessing
//  source file path: c:\Users\username\Documents\Visual Studio 2012\Projects\CallerInfoCS\CallerInfoCS\Form1.cs
//  source line number: 31


You must specify an explicit default value for each optional parameter. You can't apply Caller Info attributes to parameters that aren't specified as optional.

The Caller Info attributes don't make a parameter optional. Instead, they affect the default value that's passed in when the argument is omitted.

Caller Info values are emitted as literals into the Intermediate Language (IL) at compile time. Unlike the results of the StackTrace property for exceptions, the results aren't affected by obfuscation.

Hh534540.collapse_all(ko-kr,VS.110).gifMember Names

You can use the CallerMemberName attribute to avoid specifying the member name as a String argument to the called method. By using this technique, you avoid the problem that Rename Refactoring doesn't change the String values. This benefit is especially useful for the following tasks:

  • Using tracing and diagnostic routines.

  • Implementing the INotifyPropertyChanged interface when binding data. This interface allows the property of an object to notify a bound control that the property has changed, so that the control can display the updated information. Without the CallerMemberName attribute, you must specify the property name as a literal.

The following chart shows the member names that are returned when you use the CallerMemberName attribute.

Calls occurs within

Member name result

Method, property, or event

The name of the method, property, or event from which the call originated.

Constructor

The string ".ctor"

Static constructor

The string ".cctor"

Destructor

The string "Finalize"

User-defined operators or conversions

The generated name for the member, for example, "op_Addition".

Attribute constructor

The name of the member to which the attribute is applied. If the attribute is any element within a member (such as a parameter, a return value, or a generic type parameter), this result is the name of the member that's associated with that element.

No containing member (for example, assembly-level or attributes that are applied to types)

The default value of the optional parameter.







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

WPF 고급 - 끌어서 놓기 (Drag and Drop)  (0) 2016.10.21
WPF 고급 - 입력 (Input)  (0) 2016.10.15
WPF 고급 - 아키텍처, XAML  (0) 2016.09.23
WPF - Application Development  (1) 2016.09.08
Data Binding (WPF)  (0) 2016.09.04
:
Posted by 지훈2
2016. 10. 12. 15:54

DateTime, TimeSpan 프로그래밍/C#2016. 10. 12. 15:54

DateTime Structure

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


Represents an instant in time, typically expressed as a date and time of day.

To browse the .NET Framework source code for this type, see the Reference Source.

Namespace:   System
Assembly:  mscorlib (in mscorlib.dll)

Syntax

[SerializableAttribute]
public struct DateTime : IComparable, IFormattable, IConvertible, 
	ISerializable, IComparable<DateTime>, IEquatable<DateTime>

Constructors

NameDescription
System_CAPS_pubmethodDateTime(Int32, Int32, Int32)

Initializes a new instance of the DateTime structure to the specified year, month, and day.

System_CAPS_pubmethodDateTime(Int32, Int32, Int32, Calendar)

Initializes a new instance of the DateTime structure to the specified year, month, and day for the specified calendar.

System_CAPS_pubmethodDateTime(Int32, Int32, Int32, Int32, Int32, Int32)

Initializes a new instance of the DateTime structure to the specified year, month, day, hour, minute, and second.

System_CAPS_pubmethodDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Calendar)

Initializes a new instance of the DateTime structure to the specified year, month, day, hour, minute, and second for the specified calendar.

System_CAPS_pubmethodDateTime(Int32, Int32, Int32, Int32, Int32, Int32, DateTimeKind)

Initializes a new instance of the DateTime structure to the specified year, month, day, hour, minute, second, and Coordinated Universal Time (UTC) or local time.

System_CAPS_pubmethodDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32)

Initializes a new instance of the DateTime structure to the specified year, month, day, hour, minute, second, and millisecond.

System_CAPS_pubmethodDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Calendar)

Initializes a new instance of the DateTime structure to the specified year, month, day, hour, minute, second, and millisecond for the specified calendar.

System_CAPS_pubmethodDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Calendar, DateTimeKind)

Initializes a new instance of the DateTime structure to the specified year, month, day, hour, minute, second, millisecond, and Coordinated Universal Time (UTC) or local time for the specified calendar.

System_CAPS_pubmethodDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, DateTimeKind)

Initializes a new instance of the DateTime structure to the specified year, month, day, hour, minute, second, millisecond, and Coordinated Universal Time (UTC) or local time.

System_CAPS_pubmethodDateTime(Int64)

Initializes a new instance of the DateTime structure to a specified number of ticks.

System_CAPS_pubmethodDateTime(Int64, DateTimeKind)

Initializes a new instance of the DateTime structure to a specified number of ticks and to Coordinated Universal Time (UTC) or local time.

Properties

NameDescription
System_CAPS_pubpropertyDate

Gets the date component of this instance.

System_CAPS_pubpropertyDay

Gets the day of the month represented by this instance.

System_CAPS_pubpropertyDayOfWeek

Gets the day of the week represented by this instance.

System_CAPS_pubpropertyDayOfYear

Gets the day of the year represented by this instance.

System_CAPS_pubpropertyHour

Gets the hour component of the date represented by this instance.

System_CAPS_pubpropertyKind

Gets a value that indicates whether the time represented by this instance is based on local time, Coordinated Universal Time (UTC), or neither.

System_CAPS_pubpropertyMillisecond

Gets the milliseconds component of the date represented by this instance.

System_CAPS_pubpropertyMinute

Gets the minute component of the date represented by this instance.

System_CAPS_pubpropertyMonth

Gets the month component of the date represented by this instance.

System_CAPS_pubpropertySystem_CAPS_staticNow

Gets a DateTime object that is set to the current date and time on this computer, expressed as the local time.

System_CAPS_pubpropertySecond

Gets the seconds component of the date represented by this instance.

System_CAPS_pubpropertyTicks

Gets the number of ticks that represent the date and time of this instance.

System_CAPS_pubpropertyTimeOfDay

Gets the time of day for this instance.

System_CAPS_pubpropertySystem_CAPS_staticToday

Gets the current date.

System_CAPS_pubpropertySystem_CAPS_staticUtcNow

Gets a DateTime object that is set to the current date and time on this computer, expressed as the Coordinated Universal Time (UTC).

System_CAPS_pubpropertyYear

Gets the year component of the date represented by this instance.

Methods

NameDescription
System_CAPS_pubmethodAdd(TimeSpan)

Returns a new DateTime that adds the value of the specified TimeSpan to the value of this instance.

System_CAPS_pubmethodAddDays(Double)

Returns a new DateTime that adds the specified number of days to the value of this instance.

System_CAPS_pubmethodAddHours(Double)

Returns a new DateTime that adds the specified number of hours to the value of this instance.

System_CAPS_pubmethodAddMilliseconds(Double)

Returns a new DateTime that adds the specified number of milliseconds to the value of this instance.

System_CAPS_pubmethodAddMinutes(Double)

Returns a new DateTime that adds the specified number of minutes to the value of this instance.

System_CAPS_pubmethodAddMonths(Int32)

Returns a new DateTime that adds the specified number of months to the value of this instance.

System_CAPS_pubmethodAddSeconds(Double)

Returns a new DateTime that adds the specified number of seconds to the value of this instance.

System_CAPS_pubmethodAddTicks(Int64)

Returns a new DateTime that adds the specified number of ticks to the value of this instance.

System_CAPS_pubmethodAddYears(Int32)

Returns a new DateTime that adds the specified number of years to the value of this instance.

System_CAPS_pubmethodSystem_CAPS_staticCompare(DateTime, DateTime)

Compares two instances of DateTime and returns an integer that indicates whether the first instance is earlier than, the same as, or later than the second instance.

System_CAPS_pubmethodCompareTo(DateTime)

Compares the value of this instance to a specified DateTime value and returns an integer that indicates whether this instance is earlier than, the same as, or later than the specified DateTime value.

System_CAPS_pubmethodCompareTo(Object)

Compares the value of this instance to a specified object that contains a specified DateTime value, and returns an integer that indicates whether this instance is earlier than, the same as, or later than the specified DateTime value.

System_CAPS_pubmethodSystem_CAPS_staticDaysInMonth(Int32, Int32)

Returns the number of days in the specified month and year.

System_CAPS_pubmethodEquals(DateTime)

Returns a value indicating whether the value of this instance is equal to the value of the specifiedDateTime instance.

System_CAPS_pubmethodSystem_CAPS_staticEquals(DateTime, DateTime)

Returns a value indicating whether two DateTime instances have the same date and time value.

System_CAPS_pubmethodEquals(Object)

Returns a value indicating whether this instance is equal to a specified object.(OverridesValueType.Equals(Object).)

System_CAPS_pubmethodSystem_CAPS_staticFromBinary(Int64)

Deserializes a 64-bit binary value and recreates an original serialized DateTime object.

System_CAPS_pubmethodSystem_CAPS_staticFromFileTime(Int64)

Converts the specified Windows file time to an equivalent local time.

System_CAPS_pubmethodSystem_CAPS_staticFromFileTimeUtc(Int64)

Converts the specified Windows file time to an equivalent UTC time.

System_CAPS_pubmethodSystem_CAPS_staticFromOADate(Double)

Returns a DateTime equivalent to the specified OLE Automation Date.

System_CAPS_pubmethodGetDateTimeFormats()

Converts the value of this instance to all the string representations supported by the standard date and time format specifiers.

System_CAPS_pubmethodGetDateTimeFormats(Char)

Converts the value of this instance to all the string representations supported by the specified standard date and time format specifier.

System_CAPS_pubmethodGetDateTimeFormats(Char, IFormatProvider)

Converts the value of this instance to all the string representations supported by the specified standard date and time format specifier and culture-specific formatting information.

System_CAPS_pubmethodGetDateTimeFormats(IFormatProvider)

Converts the value of this instance to all the string representations supported by the standard date and time format specifiers and the specified culture-specific formatting information.

System_CAPS_pubmethodGetHashCode()

Returns the hash code for this instance.(Overrides ValueType.GetHashCode().)

System_CAPS_pubmethodGetType()

Gets the Type of the current instance.(Inherited from Object.)

System_CAPS_pubmethodGetTypeCode()

Returns the TypeCode for value type DateTime.

System_CAPS_pubmethodIsDaylightSavingTime()

Indicates whether this instance of DateTime is within the daylight saving time range for the current time zone.

System_CAPS_pubmethodSystem_CAPS_staticIsLeapYear(Int32)

Returns an indication whether the specified year is a leap year.

System_CAPS_pubmethodSystem_CAPS_staticParse(String)

Converts the string representation of a date and time to its DateTime equivalent.

System_CAPS_pubmethodSystem_CAPS_staticParse(String, IFormatProvider)

Converts the string representation of a date and time to its DateTime equivalent by using culture-specific format information.

System_CAPS_pubmethodSystem_CAPS_staticParse(String, IFormatProvider, DateTimeStyles)

Converts the string representation of a date and time to its DateTime equivalent by using culture-specific format information and formatting style.

System_CAPS_pubmethodSystem_CAPS_staticParseExact(String, String, IFormatProvider)

Converts the specified string representation of a date and time to its DateTime equivalent using the specified format and culture-specific format information. The format of the string representation must match the specified format exactly.

System_CAPS_pubmethodSystem_CAPS_staticParseExact(String, String, IFormatProvider, DateTimeStyles)

Converts the specified string representation of a date and time to its DateTime equivalent using the specified format, culture-specific format information, and style. The format of the string representation must match the specified format exactly or an exception is thrown.

System_CAPS_pubmethodSystem_CAPS_staticParseExact(String, String[], IFormatProvider, DateTimeStyles)

Converts the specified string representation of a date and time to its DateTime equivalent using the specified array of formats, culture-specific format information, and style. The format of the string representation must match at least one of the specified formats exactly or an exception is thrown.

System_CAPS_pubmethodSystem_CAPS_staticSpecifyKind(DateTime, DateTimeKind)

Creates a new DateTime object that has the same number of ticks as the specified DateTime, but is designated as either local time, Coordinated Universal Time (UTC), or neither, as indicated by the specified DateTimeKind value.

System_CAPS_pubmethodSubtract(DateTime)

Subtracts the specified date and time from this instance.

System_CAPS_pubmethodSubtract(TimeSpan)

Subtracts the specified duration from this instance.

System_CAPS_pubmethodToBinary()

Serializes the current DateTime object to a 64-bit binary value that subsequently can be used to recreate the DateTime object.

System_CAPS_pubmethodToFileTime()

Converts the value of the current DateTime object to a Windows file time.

System_CAPS_pubmethodToFileTimeUtc()

Converts the value of the current DateTime object to a Windows file time.

System_CAPS_pubmethodToLocalTime()

Converts the value of the current DateTime object to local time.

System_CAPS_pubmethodToLongDateString()

Converts the value of the current DateTime object to its equivalent long date string representation.

System_CAPS_pubmethodToLongTimeString()

Converts the value of the current DateTime object to its equivalent long time string representation.

System_CAPS_pubmethodToOADate()

Converts the value of this instance to the equivalent OLE Automation date.

System_CAPS_pubmethodToShortDateString()

Converts the value of the current DateTime object to its equivalent short date string representation.

System_CAPS_pubmethodToShortTimeString()

Converts the value of the current DateTime object to its equivalent short time string representation.

System_CAPS_pubmethodToString()

Converts the value of the current DateTime object to its equivalent string representation using the formatting conventions of the current culture.(Overrides ValueType.ToString().)

System_CAPS_pubmethodToString(IFormatProvider)

Converts the value of the current DateTime object to its equivalent string representation using the specified culture-specific format information.

System_CAPS_pubmethodToString(String)

Converts the value of the current DateTime object to its equivalent string representation using the specified format and the formatting conventions of the current culture.

System_CAPS_pubmethodToString(String, IFormatProvider)

Converts the value of the current DateTime object to its equivalent string representation using the specified format and culture-specific format information.

System_CAPS_pubmethodToUniversalTime()

Converts the value of the current DateTime object to Coordinated Universal Time (UTC).

System_CAPS_pubmethodSystem_CAPS_staticTryParse(String, DateTime)

Converts the specified string representation of a date and time to its DateTime equivalent and returns a value that indicates whether the conversion succeeded.

System_CAPS_pubmethodSystem_CAPS_staticTryParse(String, IFormatProvider, DateTimeStyles, DateTime)

Converts the specified string representation of a date and time to its DateTime equivalent using the specified culture-specific format information and formatting style, and returns a value that indicates whether the conversion succeeded.

System_CAPS_pubmethodSystem_CAPS_staticTryParseExact(String, String, IFormatProvider, DateTimeStyles, DateTime)

Converts the specified string representation of a date and time to its DateTime equivalent using the specified format, culture-specific format information, and style. The format of the string representation must match the specified format exactly. The method returns a value that indicates whether the conversion succeeded.

System_CAPS_pubmethodSystem_CAPS_staticTryParseExact(String, String[], IFormatProvider, DateTimeStyles, DateTime)

Converts the specified string representation of a date and time to its DateTime equivalent using the specified array of formats, culture-specific format information, and style. The format of the string representation must match at least one of the specified formats exactly. The method returns a value that indicates whether the conversion succeeded.

Fields

NameDescription
System_CAPS_pubfieldSystem_CAPS_staticMaxValue

Represents the largest possible value of DateTime. This field is read-only.

System_CAPS_pubfieldSystem_CAPS_staticMinValue

Represents the smallest possible value of DateTime. This field is read-only.

Operators

NameDescription
System_CAPS_puboperatorSystem_CAPS_staticAddition(DateTime, TimeSpan)

Adds a specified time interval to a specified date and time, yielding a new date and time.

System_CAPS_puboperatorSystem_CAPS_staticEquality(DateTime, DateTime)

Determines whether two specified instances of DateTime are equal.

System_CAPS_puboperatorSystem_CAPS_staticGreaterThan(DateTime, DateTime)

Determines whether one specified DateTime is later than another specified DateTime.

System_CAPS_puboperatorSystem_CAPS_staticGreaterThanOrEqual(DateTime, DateTime)

Determines whether one specified DateTime represents a date and time that is the same as or later than another specified DateTime.

System_CAPS_puboperatorSystem_CAPS_staticInequality(DateTime, DateTime)

Determines whether two specified instances of DateTime are not equal.

System_CAPS_puboperatorSystem_CAPS_staticLessThan(DateTime, DateTime)

Determines whether one specified DateTime is earlier than another specified DateTime.

System_CAPS_puboperatorSystem_CAPS_staticLessThanOrEqual(DateTime, DateTime)

Determines whether one specified DateTime represents a date and time that is the same as or earlier than another specified DateTime.

System_CAPS_puboperatorSystem_CAPS_staticSubtraction(DateTime, DateTime)

Subtracts a specified date and time from another specified date and time and returns a time interval.

System_CAPS_puboperatorSystem_CAPS_staticSubtraction(DateTime, TimeSpan)

Subtracts a specified time interval from a specified date and time and returns a new date and time.

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. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToByte(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToChar(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToDateTime(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. Returns the current DateTime object.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToDecimal(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToDouble(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToInt16(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToInt32(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToInt64(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToSByte(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToSingle(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

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 DateTime object to an object of a specified 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. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToUInt32(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToUInt64(IFormatProvider)

This API supports the product infrastructure and is not intended to be used directly from your code. This conversion is not supported. Attempting to use this method throws anInvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodISerializable.GetObjectData(SerializationInfo, StreamingContext)

Populates a SerializationInfo object with the data needed to serialize the current DateTimeobject.

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.

The DateTime value type represents dates and times with values ranging from 00:00:00 (midnight), January 1, 0001 Anno Domini (Common Era) through 11:59:59 P.M., December 31, 9999 A.D. (C.E.) in the Gregorian calendar.

Time values are measured in 100-nanosecond units called ticks, and a particular date is the number of ticks since 12:00 midnight, January 1, 0001 A.D. (C.E.) in the GregorianCalendar calendar (excluding ticks that would be added by leap seconds). For example, a ticks value of 31241376000000000L represents the date, Friday, January 01, 0100 12:00:00 midnight. A DateTime value is always expressed in the context of an explicit or default calendar.

System_CAPS_noteNote

If you are working with a ticks value that you want to convert to some other time interval, such as minutes or seconds, you should use theTimeSpan.TicksPerDayTimeSpan.TicksPerHourTimeSpan.TicksPerMinuteTimeSpan.TicksPerSecond, or TimeSpan.TicksPerMillisecond constant to perform the conversion. For example, to add the number of seconds represented by a specified number of ticks to the Second component of aDateTime value, you can use the expression dateValue.Second + nTicks/Timespan.TicksPerSecond.

In this section:

Instantiating a DateTime object
DateTime values and their string representations
Converting strings to DateTime values
Version considerations
DateTime values
DateTime operations
DateTime resolution
DateTime vs. TimeSpan
DateTime values and calendars
Persisting DateTime values
COM interop considerations

Instantiating a DateTime object

You can create a new DateTime value in any of the following ways:

  • By calling any of the overloads of the DateTime constructor that allow you to specify specific elements of the date and time value (such as the year, month, and day, or the number of ticks). The following statement illustrates a call to one of the DateTime constructors to create a date with a specific year, month, day, hour, minute, and second.

    DateTime date1 = new DateTime(2008, 5, 1, 8, 30, 52);
    
  • By using any compiler-specific syntax for declaring date and time values. For example, the following Visual Basic statement initializes a newDateTime value.

    Dim date1 As Date = #5/1/2008 8:30:52AM#
    
  • By assigning the DateTime object a date and time value returned by a property or method. The following example assigns the current date and time, the current Coordinated Universal Time (UTC) date and time, and the current date to three new DateTime variables.

    DateTime date1 = DateTime.Now;
    DateTime date2 = DateTime.UtcNow;
    DateTime date3 = DateTime.Today;
    
  • By parsing the string representation of a date and time value. The ParseParseExactTryParse, and TryParseExact methods all convert a string to its equivalent date and time value. The following example uses the Parse method to parse a string and convert it to a DateTime value.

    string dateString = "5/1/2008 8:30:52 AM";
    DateTime date1 = DateTime.Parse(dateString, 
                              System.Globalization.CultureInfo.InvariantCulture); 
    

    Note that the TryParse and TryParseExact methods indicate whether a particular string contains a valid representation of a DateTime value in addition to performing the conversion.

  • By calling the DateTime structure's implicit default constructor. (For details on the implicit default constructor of a value type, see Value Types (C# Reference).) An approximate equivalent, for compilers that support it, is declaring a DateTime value without explicitly assigning a date and time to it. The following example illustrates a call to the DateTime implicit default constructor in C# and Visual Basic, as well as aDateTime variable declaration with no assignment in Visual Basic.

    DateTime dat1 = new DateTime();
    // The following method call displays 1/1/0001 12:00:00 AM.
    Console.WriteLine(dat1.ToString(System.Globalization.CultureInfo.InvariantCulture));
    // The following method call displays True.
    Console.WriteLine(dat1.Equals(DateTime.MinValue));
    

DateTime values and their string representations

Internally, all DateTime values are represented as the number of ticks (the number of 100-nanosecond intervals) that have elapsed since 12:00:00 midnight, January 1, 0001. The actual DateTime value is independent of the way in which that value appears when displayed in a user interface element or when written to a file. The appearance of a DateTime value is the result of a formatting operation. Formatting is the process of converting a value to its string representation.

Because the appearance of date and time values is dependent on such factors as culture, international standards, application requirements, and personal preference, the DateTime structure offers a great deal of flexibility in formatting date and time values through the overloads of itsToString method. The default DateTime.ToString() method returns the string representation of a date and time value using the current culture's short date and long time pattern. The following example uses the default DateTime.ToString() method to display the date and time using the short date and long time pattern for the en-US culture, the current culture on the computer on which the example was run.

DateTime date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString());
// For en-US culture, displays 3/1/2008 7:00:00 AM

The DateTime.ToString(IFormatProvider) method returns the string representation of a date and time value using the short date and long time pattern of a specific culture. The following example uses the DateTime.ToString(IFormatProvider) method to display the date and time using the short date and long time pattern for the fr-FR culture.

DateTime date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString(System.Globalization.CultureInfo.CreateSpecificCulture("fr-FR")));
// Displays 01/03/2008 07:00:00

The DateTime.ToString(String) method returns the string representation of the date and time in a format defined by a standard or custom format specifier and using the formatting conventions of the current culture. The following example uses the DateTime.ToString(String) method to display the full date and time pattern for the en-US culture, the current culture on the computer on which the example was run.

DateTime date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString("F"));
// Displays Saturday, March 01, 2008 7:00:00 AM

The DateTime.ToString(String, IFormatProvider) method returns the string representation of the date and time in a format defined by a specific format specifier and using the formatting conventions of a specific culture. The following example uses the DateTime.ToString(String, IFormatProvider) method to display the full date and time pattern for the fr-FR culture.

DateTime date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString("F", new System.Globalization.CultureInfo("fr-FR")));
// Displays samedi 1 mars 2008 07:00:00

For more information about formatting DateTime values, see Standard Date and Time Format Strings and Custom Date and Time Format Strings.

Converting strings to DateTime values

Parsing involves converting the string representation of a date and time to a DateTime value. Typically, date and time strings have two different usages in applications:

  • They represent a date and time that can take a variety of forms and that reflect the conventions of either the current culture or a specific culture. For example, an application may allow a user whose current culture is en-US to input a date value as "12/15/2013" or "December 15, 2013", and allow a user whose current culture is en-GB to input a date value as "15/12/2013" or "15 December 2013".

  • They represent a date and time in a predefined format. For example, an application may serialize a date as "20130103" independently of the culture on which the app is running, or it may require that a date be input in the current culture's short date format.

You can use the Parse or TryParse method to convert a string that might reflect one of the common date and time formats used by a culture to aDateTime value. The following example shows how you can use TryParse to convert date strings in a number of different culture-specific formats to a DateTime value. It changes the current culture to English (Great Britain) and calls the GetDateTimeFormats() method to generate an array of date and time strings. It then passes each element in the array to the TryParse method. The output from the example shows that the parsing method was able to successfully convert each of the culture-specific date and time strings.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");

      DateTime date1 = new DateTime(2013, 6, 1, 12, 32, 30);
      List<string> badFormats = new List<String>();

      Console.WriteLine("{0,-37} {1,-19}\n", "Date String", "Date");
      foreach (var dateString in date1.GetDateTimeFormats()) {
         DateTime parsedDate;
         if (DateTime.TryParse(dateString, out parsedDate))
            Console.WriteLine("{0,-37} {1,-19}", dateString, DateTime.Parse(dateString));
         else
            badFormats.Add(dateString);
      } 

      // Display strings that could not be parsed.
      if (badFormats.Count > 0) {
         Console.WriteLine("\nStrings that could not be parsed: ");
         foreach (var badFormat in badFormats)
            Console.WriteLine("   {0}", badFormat);         
      }
   }
}
// The example displays the following output:
//       Date String                           Date               
//       
//       01/06/2013                            01/06/2013 00:00:00
//       01/06/13                              01/06/2013 00:00:00
//       1/6/13                                01/06/2013 00:00:00
//       1.6.13                                01/06/2013 00:00:00
//       2013-06-01                            01/06/2013 00:00:00
//       01 June 2013                          01/06/2013 00:00:00
//       1 June 2013                           01/06/2013 00:00:00
//       01 June 2013 12:32                    01/06/2013 12:32:00
//       01 June 2013 12:32                    01/06/2013 12:32:00
//       01 June 2013 12:32 PM                 01/06/2013 12:32:00
//       01 June 2013 12:32 PM                 01/06/2013 12:32:00
//       1 June 2013 12:32                     01/06/2013 12:32:00
//       1 June 2013 12:32                     01/06/2013 12:32:00
//       1 June 2013 12:32 PM                  01/06/2013 12:32:00
//       1 June 2013 12:32 PM                  01/06/2013 12:32:00
//       01 June 2013 12:32:30                 01/06/2013 12:32:30
//       01 June 2013 12:32:30                 01/06/2013 12:32:30
//       01 June 2013 12:32:30 PM              01/06/2013 12:32:30
//       01 June 2013 12:32:30 PM              01/06/2013 12:32:30
//       1 June 2013 12:32:30                  01/06/2013 12:32:30
//       1 June 2013 12:32:30                  01/06/2013 12:32:30
//       1 June 2013 12:32:30 PM               01/06/2013 12:32:30
//       1 June 2013 12:32:30 PM               01/06/2013 12:32:30
//       01/06/2013 12:32                      01/06/2013 12:32:00
//       01/06/2013 12:32                      01/06/2013 12:32:00
//       01/06/2013 12:32 PM                   01/06/2013 12:32:00
//       01/06/2013 12:32 PM                   01/06/2013 12:32:00
//       01/06/13 12:32                        01/06/2013 12:32:00
//       01/06/13 12:32                        01/06/2013 12:32:00
//       01/06/13 12:32 PM                     01/06/2013 12:32:00
//       01/06/13 12:32 PM                     01/06/2013 12:32:00
//       1/6/13 12:32                          01/06/2013 12:32:00
//       1/6/13 12:32                          01/06/2013 12:32:00
//       1/6/13 12:32 PM                       01/06/2013 12:32:00
//       1/6/13 12:32 PM                       01/06/2013 12:32:00
//       1.6.13 12:32                          01/06/2013 12:32:00
//       1.6.13 12:32                          01/06/2013 12:32:00
//       1.6.13 12:32 PM                       01/06/2013 12:32:00
//       1.6.13 12:32 PM                       01/06/2013 12:32:00
//       2013-06-01 12:32                      01/06/2013 12:32:00
//       2013-06-01 12:32                      01/06/2013 12:32:00
//       2013-06-01 12:32 PM                   01/06/2013 12:32:00
//       2013-06-01 12:32 PM                   01/06/2013 12:32:00
//       01/06/2013 12:32:30                   01/06/2013 12:32:30
//       01/06/2013 12:32:30                   01/06/2013 12:32:30
//       01/06/2013 12:32:30 PM                01/06/2013 12:32:30
//       01/06/2013 12:32:30 PM                01/06/2013 12:32:30
//       01/06/13 12:32:30                     01/06/2013 12:32:30
//       01/06/13 12:32:30                     01/06/2013 12:32:30
//       01/06/13 12:32:30 PM                  01/06/2013 12:32:30
//       01/06/13 12:32:30 PM                  01/06/2013 12:32:30
//       1/6/13 12:32:30                       01/06/2013 12:32:30
//       1/6/13 12:32:30                       01/06/2013 12:32:30
//       1/6/13 12:32:30 PM                    01/06/2013 12:32:30
//       1/6/13 12:32:30 PM                    01/06/2013 12:32:30
//       1.6.13 12:32:30                       01/06/2013 12:32:30
//       1.6.13 12:32:30                       01/06/2013 12:32:30
//       1.6.13 12:32:30 PM                    01/06/2013 12:32:30
//       1.6.13 12:32:30 PM                    01/06/2013 12:32:30
//       2013-06-01 12:32:30                   01/06/2013 12:32:30
//       2013-06-01 12:32:30                   01/06/2013 12:32:30
//       2013-06-01 12:32:30 PM                01/06/2013 12:32:30
//       2013-06-01 12:32:30 PM                01/06/2013 12:32:30
//       01 June                               01/06/2013 00:00:00
//       01 June                               01/06/2013 00:00:00
//       2013-06-01T12:32:30.0000000           01/06/2013 12:32:30
//       2013-06-01T12:32:30.0000000           01/06/2013 12:32:30
//       Sat, 01 Jun 2013 12:32:30 GMT         01/06/2013 05:32:30
//       Sat, 01 Jun 2013 12:32:30 GMT         01/06/2013 05:32:30
//       2013-06-01T12:32:30                   01/06/2013 12:32:30
//       12:32                                 22/04/2013 12:32:00
//       12:32                                 22/04/2013 12:32:00
//       12:32 PM                              22/04/2013 12:32:00
//       12:32 PM                              22/04/2013 12:32:00
//       12:32:30                              22/04/2013 12:32:30
//       12:32:30                              22/04/2013 12:32:30
//       12:32:30 PM                           22/04/2013 12:32:30
//       12:32:30 PM                           22/04/2013 12:32:30
//       2013-06-01 12:32:30Z                  01/06/2013 05:32:30
//       01 June 2013 19:32:30                 01/06/2013 19:32:30
//       01 June 2013 19:32:30                 01/06/2013 19:32:30
//       01 June 2013 07:32:30 PM              01/06/2013 19:32:30
//       01 June 2013 7:32:30 PM               01/06/2013 19:32:30
//       1 June 2013 19:32:30                  01/06/2013 19:32:30
//       1 June 2013 19:32:30                  01/06/2013 19:32:30
//       1 June 2013 07:32:30 PM               01/06/2013 19:32:30
//       1 June 2013 7:32:30 PM                01/06/2013 19:32:30
//       June 2013                             01/06/2013 00:00:00
//       June 2013                             01/06/2013 00:00:00

You can use the TryParse and TryParseExact methods to convert a date and time string that must match a particular format or formats to aDateTime value. You specify the required format or formats as a parameter to the parsing methodby using one or more or date and time format strings. The following example uses the TryParseExact(String, String[], IFormatProvider, DateTimeStyles, DateTime) method to convert strings that must be either in a "yyyyMMdd" format or a "HHmmss" format to DateTime values.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      string[] formats = { "yyyyMMdd", "HHmmss" };
      string[] dateStrings = { "20130816", "20131608", "  20130816   ", 
                               "115216", "521116", "  115216  " };
      DateTime parsedDate;

      foreach (var dateString in dateStrings) {
         if (DateTime.TryParseExact(dateString, formats, null, 
                                    DateTimeStyles.AllowWhiteSpaces |
                                    DateTimeStyles.AdjustToUniversal,
                                    out parsedDate))
            Console.WriteLine("{0} --> {1:g}", dateString, parsedDate);
         else
            Console.WriteLine("Cannot convert {0}", dateString);
      }
   }
}
// The example displays the following output:
//       20130816 --> 8/16/2013 12:00 AM
//       Cannot convert 20131608
//         20130816    --> 8/16/2013 12:00 AM
//       115216 --> 4/22/2013 11:52 AM
//       Cannot convert 521116
//         115216   --> 4/22/2013 11:52 AM

The Parse and ParseExact methods throw an exception if the string to be converted to a DateTime value cannot be parsed. The TryParse andTryParseExact methods return a Boolean value that indicates whether the conversion succeeded or failed. Because the parsing operation for date and time strings, particularly if strings are input by users, tends to have a high failure rate, and because exception handling is expensive, you should use the TryParse or TryParseExact methods in scenarios where performance is important or conversions are subject to a high rate of failure.

For more information about parsing date and time values, see Parsing Date and Time Strings in the .NET Framework.

Version considerations

Prior to the .NET Framework version 2.0, the DateTime structure contains a 64-bit field composed of an unused 2-bit field concatenated with a private Ticks field, which is a 62-bit unsigned field that contains the number of ticks that represent the date and time. The value of the Ticks field can be obtained with the Ticks property.

Starting with the .NET Framework 2.0, the DateTime structure contains a 64-bit field composed of a private Kind field concatenated with the Ticks field. The Kind field is a 2-bit field that indicates whether the DateTime structure represents a local time, a Coordinated Universal Time (UTC), or the time in an unspecified time zone. The Kind field is used when performing time conversions between time zones, but not for time comparisons or arithmetic. The value of the Kind field can be obtained with the Kind property.

System_CAPS_noteNote

An alternative to the DateTime structure for working with date and time values in particular time zones is the DateTimeOffset structure. TheDateTimeOffset structure stores date and time information in a private DateTime field and the number of minutes by which that date and time differs from UTC in a private Int16 field. This makes it possible for a DateTimeOffset value to reflect the time in a particular time zone, whereas aDateTime value can unambiguously reflect only UTC and the local time zone's time. For a discussion about when to use the DateTime structure or the DateTimeOffset structure when working with date and time values, see Choosing Between DateTime, DateTimeOffset, TimeSpan, and TimeZoneInfo.

DateTime values

Descriptions of time values in the DateTime type are often expressed using the Coordinated Universal Time (UTC) standard, which is the internationally recognized name for Greenwich Mean Time (GMT). Coordinated Universal Time is the time as measured at zero degrees longitude, the UTC origin point. Daylight saving time is not applicable to UTC.

Local time is relative to a particular time zone. A time zone is associated with a time zone offset, which is the displacement of the time zone measured in hours from the UTC origin point. In addition, local time is optionally affected by daylight saving time, which adds or subtracts an hour from the length of a day. Consequently, local time is calculated by adding the time zone offset to UTC and adjusting for daylight saving time if necessary. The time zone offset at the UTC origin point is zero.

UTC time is suitable for calculations, comparisons, and storing dates and time in files. Local time is appropriate for display in user interfaces of desktop applications. Time zone-aware applications (such as many Web applications) also need to work with a number of other time zones.

If the Kind property of a DateTime object is DateTimeKind.Unspecified, it is unspecified whether the time represented is local time, UTC time, or a time in some other time zone.

DateTime operations

A calculation using a DateTime structure, such as Add or Subtract, does not modify the value of the structure. Instead, the calculation returns a new DateTime structure whose value is the result of the calculation.

Conversion operations between time zones (such as between UTC and local time, or between one time zone and another) take daylight saving time into account, but arithmetic and comparison operations do not.

The DateTime structure itself offers limited support for converting from one time zone to another. You can use the ToLocalTime method to convert UTC to local time, or you can use the ToUniversalTime method to convert from local time to UTC. However, a full set of time zone conversion methods is available in the TimeZoneInfo class. Using these methods, you can convert the time in any one of the world's time zones to the time in any other time zone.

Calculations and comparisons of DateTime objects are meaningful only if the objects represent times in the same time zone. You can use aTimeZoneInfo object to represent a DateTime value's time zone, although the two are loosely coupled. (That is, a DateTime object does not have a property that returns an object that represents that date and time value's time zone other than the Kind property.) For this reason, in a time zone-aware application, you must rely on some external mechanism to determine the time zone in which a DateTime object was created. For example, you could use a structure that wraps both the DateTime value and the TimeZoneInfo object that represents the DateTime value's time zone. For details on using UTC in calculations and comparisons with DateTime values, see Performing Arithmetic Operations with Dates and Times.

Each DateTime member implicitly uses the Gregorian calendar to perform its operation, with the exception of constructors that specify a calendar, and methods with a parameter derived from IFormatProvider, such as System.Globalization.DateTimeFormatInfo, that implicitly specifies a calendar.

Operations by members of the DateTime type take into account details such as leap years and the number of days in a month.

Two other common operations with DateTime values involve converting a date and time value to or from its string representation. The process of converting a DateTime value to its string representation is a formatting operation; for more information about formatting, see DateTime values and their string representations. The process of converting the string representation of a date and time to a DateTime value is a parsing operation; for more information about parsing, see Converting strings to DateTime values.

DateTime resolution

System_CAPS_noteNote

As an alternative to performing date and time arithmetic on DateTime values to measure elapsed time, you can use the Stopwatch class.

The Ticks property expresses date and time values in units of one ten-millionth of a second, and the Millisecond property returns the thousandths of a second in a date and time value. However, if you are using repeated calls to the DateTime.Now property to measure elapsed time, and you are concerned with small time intervals less than 100 milliseconds, you should note that values returned by the DateTime.Now property are dependent on the system clock, which on Windows 7 and Windows 8 systems has a resolution of approximately 15 milliseconds.

The following example illustrates the dependence of current date and time values on the resolution of the system clock. In the example, an outer loop repeats 20 times, and an inner loop serves to delay the outer loop. If the value of the outer loop counter is 10, a call to the Thread.Sleepmethod introduces a five millisecond delay. As the output from the example shows, the number of milliseconds in returned by theDateTime.Now.Milliseconds property changed only after the call to Thread.Sleep.

using System;
using System.Threading;

public class Example
{
   public static void Main()
   {
      String output = "";
      for (int ctr = 0; ctr <= 20; ctr++) {
         output += String.Format("{0}\n", DateTime.Now.Millisecond);
         // Introduce a delay loop.
         for (int delay = 0; delay <= 1000; delay++)
         {}

         if (ctr == 10) {
            output += "Thread.Sleep called...\n";
            Thread.Sleep(5);
         }
      }
      Console.WriteLine(output);
   }
}
// The example displays the following output:
//       111
//       111
//       111
//       111
//       111
//       111
//       111
//       111
//       111
//       111
//       111
//       Thread.Sleep called...
//       143
//       143
//       143
//       143
//       143
//       143
//       143
//       143
//       143
//       143

DateTime vs. TimeSpan

The DateTime and TimeSpan value types differ in that a DateTime represents an instant in time whereas a TimeSpan represents a time interval. This means, for example, that you can subtract one instance of DateTime from another to obtain a TimeSpan object that represents the time interval between them. Or you could add a positive TimeSpan to the current DateTime to obtain a DateTime value that represents a future date.

You can add or subtract a time interval from a DateTime object. Time intervals can be negative or positive, can be expressed in units such as ticks or seconds, or can be expressed as a TimeSpan object.

DateTime values and calendars

The .NET Framework Class Library includes a number of calendar classes, all of which are derived from the Calendar class. They are:

Each culture uses a default calendar defined by its read-only CultureInfo.Calendar property and supports one or more calendars defined by its read-only CultureInfo.OptionalCalendars property. The calendar currently used by a specific CultureInfo object is defined by itsDateTimeFormatInfo.Calendar property; it must be one of the calendars found in the CultureInfo.OptionalCalendars array.

A culture's current calendar is used in all formatting operations for that culture. For example, the default calendar of the Persian (Iran) culture is the Umm al-Qura calendar, which is represented by the UmAlQuraCalendar class. When a CultureInfo object that represents the Persian (Iran) culture is used in a date and time formatting operation, the Umm al-Qura calendar is used by default, and the Gregorian calendar is used only if the culture's DateTimeFormatInfo.Calendar property is changed, as the following example shows.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      var faIR = new CultureInfo("fa-IR");
      var value = new DateTime(2016, 5, 28);

      Console.WriteLine(value.ToString(faIR));

      faIR.DateTimeFormat.Calendar = new GregorianCalendar();
      Console.WriteLine(value.ToString(faIR));
   }
}
// The example displays the following output:
// 08/03/1395 12:00:00 ?.?
// 28/05/2016 12:00:00 ?.?

A culture's current calendar is also used in all parsing operations for that culture, as the following example shows.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      var faIR = new CultureInfo("fa-IR");
      var value = DateTime.Parse("08/03/1395", faIR);
      Console.WriteLine(value.ToString(faIR));

      faIR.DateTimeFormat.Calendar = new GregorianCalendar();
      Console.WriteLine(value.ToString(faIR));
   }
}
// The example displays the following output:
//       08/03/1395 12:00:00 ?.?
//       28/05/2016 12:00:00 ?.?

You can also instantiate a DateTime value by using the date and time elements (such as the number of the year, month, and day) of a specific calendar by calling a DateTime constructor that includes a calendar parameter and passing it a Calendar object that represents that calendar. The following example does this by using the date and time elements from the UmAlQuraCalendar calendar.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      var faIR = new CultureInfo("fa-IR");
      var dat = new DateTime(1395, 8, 18, faIR.DateTimeFormat.Calendar);
      Console.WriteLine("Umm-al-Qura date: {0}", dat.ToString("d", faIR));
      Console.WriteLine("Gregorian date:   {0:d}", dat);
   }
}
// The example displays the following output:
//       Umm-al-Qura date: 18/08/1395
//       Gregorian date:   11/8/2016

DateTime constructors that do not include a calendar parameter assume that the date and time elements are expressed as units in the Gregorian calendar.

All other DateTime properties and methods use the Gregorian calendar. For example, the DateTime.Year property returns the year in the Gregorian calendar, and the DateTime.IsLeapYear(Int32) method assumes that the year parameter is a year in the Gregorian calendar. Each DateTime member that uses the Gregorian calendar has a corresponding member of the Calendar class that uses a specific calendar. For example, theCalendar.GetYear method returns the year in a specific calendar, and the Calendar.IsLeapYear method interprets the year parameter as a year number in a specific calendar. The following example use both the DateTime and the corresponding members of the UmAlQuraCalendar class.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      var faIR = new CultureInfo("fa-IR");
      var cal = faIR.DateTimeFormat.Calendar;
      var dat = new DateTime(1395, 8, 18, cal);
      Console.WriteLine("Using the Umm-al-Qura calendar:");
      Console.WriteLine("Date: {0}", dat.ToString("d", faIR));
      Console.WriteLine("Year: {0}", cal.GetYear(dat));
      Console.WriteLine("Leap year: {0}\n", 
                        cal.IsLeapYear(cal.GetYear(dat)));

      Console.WriteLine("Using the Gregorian calendar:");
      Console.WriteLine("Date: {0:d}", dat);
      Console.WriteLine("Year: {0}", dat.Year);
      Console.WriteLine("Leap year: {0}", DateTime.IsLeapYear(dat.Year));
   }
}
// The example displays the following output:
//       Using the Umm-al-Qura calendar:
//       Date: 18/08/1395
//       Year: 1395
//       Leap year: True
//       
//       Using the Gregorian calendar:
//       Date: 11/8/2016
//       Year: 2016
//       Leap year: True

Although the DateTime structure includes DayOfWeek property that returns the day of the week in the Gregorian calendar, it does not include a member that allows you to retrieve the week number of the year. To retrieve the week of the year, call the individual calendar'sCalendar.GetWeekOfYear method. The following example provides an illustration.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      var faIR = new CultureInfo("fa-IR");
      var umAlQura = faIR.DateTimeFormat.Calendar;
      var dat = new DateTime(1395, 8, 18, umAlQura);
      Console.WriteLine("Using the Umm-al-Qura calendar:");
      Console.WriteLine("Date: {0}", dat.ToString("d", faIR));
      Console.WriteLine("Day of Week: {0}", umAlQura.GetDayOfWeek(dat));
      Console.WriteLine("Week of year: {0}\n", 
                        umAlQura.GetWeekOfYear(dat, CalendarWeekRule.FirstDay, 
                                               DayOfWeek.Sunday));

      var greg = new GregorianCalendar(); 
      Console.WriteLine("Using the Gregorian calendar:");
      Console.WriteLine("Date: {0:d}", dat);
      Console.WriteLine("Day of Week: {0}", dat.DayOfWeek);
      Console.WriteLine("Week of year: {0}", 
                         greg.GetWeekOfYear(dat, CalendarWeekRule.FirstDay, 
                                            DayOfWeek.Sunday));
   }
}
// The example displays the following output:
//       Using the Umm-al-Qura calendar:
//       Date: 18/08/1395
//       Day of Week: Tuesday
//       Week of year: 34
//       
//       Using the Gregorian calendar:
//       Date: 11/8/2016
//       Day of Week: Tuesday
//       Week of year: 46

For more information on dates and calendars, see Working with Calendars.

Persisting DateTime values

You can persist DateTime values in four ways:

Regardless of which technique you choose, you must ensure that the routine that restores the DateTime values doesn't lose data or throw an exception. DateTime values should round-trip. That is, the original value and the restored value should be the same. And if the original DateTimevalue represents a single instant of time, it should identify the same moment of time when it's restored.

Persisting values as strings

To successfully restore DateTime values that are persisted as strings, follow these rules:

  • Make the same assumptions about culture-specific formatting when you restore the string as when you persisted it. To ensure that a string can be restored on a system whose current culture is different from the culture of the system it was saved on, call theToStringoverload to save the string by using the conventions of the invariant culture, and call the Parse(String, IFormatProvider, DateTimeStyles) or TryParse(String, IFormatProvider, DateTimeStyles, DateTime) overload to restore the string by using the conventions of the invariant culture. Never use the ToString()Parse(String), or TryParse(String, DateTime) overloads, which use the conventions of the current thread culture.

  • If the data represents a single moment of time, ensure that it represents the same moment in time when it's restored, even if it's restored on a system that uses a different time zone. To do this, you convert the DateTime value to Coordinated Universal Time (UTC) before saving it. You can also serialize the value along with time zone information; for more information about this approach, see Serializing DateTime and time zone data.

The most common error made when persisting DateTime values as strings is to rely on the formatting conventions of the default or current culture. Problems arise if the current culture is different when saving and restoring the strings. The following example illustrates these problems. It saves five dates using the formatting conventions of the current culture, which in this case is English (United States). It restores the dates using the formatting conventions of the current culture, which in this case is English (Great Britain). Because the formatting conventions of the two cultures are different, two of the dates can't be restored, and the remaining three dates are interpreted incorrectly. Also, if the original date and time values represent single moments in time, the restored times are incorrect because time zone information is lost.

using System;
using System.Globalization;
using System.IO;
using System.Threading;

public class Example
{
   private const string filename = @".\BadDates.txt";

   public static void Main()
   {
      if (! File.Exists(filename))
         SaveDates();
      else
         RestoreDates();
   }

   private static void SaveDates()
   {
      DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0), 
                           new DateTime(2014, 7, 10, 23, 49, 0),  
                           new DateTime(2015, 1, 10, 1, 16, 0), 
                           new DateTime(2014, 12, 20, 21, 45, 0), 
                           new DateTime(2014, 6, 2, 15, 14, 0) }; 
      string output = null;

      Console.WriteLine("Current Time Zone: {0}",
                        TimeZoneInfo.Local.DisplayName);
      Console.WriteLine("The dates on an {0} system:", 
                        Thread.CurrentThread.CurrentCulture.Name);
      for (int ctr = 0; ctr < dates.Length; ctr++) { 
         Console.WriteLine(dates[ctr].ToString("f"));
         output += dates[ctr].ToString() + (ctr != dates.Length - 1 ? "|" : "");
      }
      StreamWriter sw = new StreamWriter(filename);
      sw.Write(output);
      sw.Close();
      Console.WriteLine("Saved dates...");
   }

   private static void RestoreDates()
   {
      TimeZoneInfo.ClearCachedData();
      Console.WriteLine("Current Time Zone: {0}",
                        TimeZoneInfo.Local.DisplayName);
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
      StreamReader sr = new StreamReader(filename);
      string[] inputValues = sr.ReadToEnd().Split( new char[] { '|' } , 
                                                  StringSplitOptions.RemoveEmptyEntries);
      sr.Close();
      Console.WriteLine("The dates on an {0} system:", 
                        Thread.CurrentThread.CurrentCulture.Name);
      foreach (var inputValue in inputValues) {
         DateTime dateValue;
         if (DateTime.TryParse(inputValue, out dateValue)) {
            Console.WriteLine("'{0}' --> {1:f}", inputValue, dateValue);
         }
         else {
            Console.WriteLine("Cannot parse '{0}'", inputValue);   
         }
      }
      Console.WriteLine("Restored dates...");   
   }
}
// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       Cannot parse //6/14/2014 6:32:00 AM//
//       //7/10/2014 11:49:00 PM// --> 07 October 2014 23:49
//       //1/10/2015 1:16:00 AM// --> 01 October 2015 01:16
//       Cannot parse //12/20/2014 9:45:00 PM//
//       //6/2/2014 3:14:00 PM// --> 06 February 2014 15:14
//       Restored dates...

To round-trip DateTime values successfully, follow these steps:

  1. If the values represent single moments of time, convert them from the local time to UTC by calling the ToUniversalTime method.

  2. Convert the dates to their string representations by calling the ToString(String, IFormatProvider) or String.Format(IFormatProvider, String, Object[]) overload. Use the formatting conventions of the invariant culture by specifying CultureInfo.InvariantCulture as theprovider argument. Specify that the value should round-trip by using the "O" or "R" .

  3. When you call the Parse(String, IFormatProvider, DateTimeStyles) or TryParse(String, IFormatProvider, DateTimeStyles, DateTime)method.

To restore the persisted DateTime values without data loss, do the following:

  1. Parse the data by calling the ParseExact or TryParseExact overload. Specify CultureInfo.InvariantCulture as the provider argument, and use the same standard format string you used for the format argument during conversion. Include the DateTimeStyles.RoundtripKind value in the styles argument.

  2. If the DateTime values represent single moments in time, call the ToLocalTime method to convert the parsed date from UTC to local time.

The following example uses the invariant culture and the "O" standard format string to ensure that DateTime values that are saved and restored represent the same moment in time regardless of the system, culture, or time zone of the source and target systems.

using System;
using System.Globalization;
using System.IO;
using System.Threading;

public class Example
{
   private const string filename = @".\Dates.txt";

   public static void Main()
   {
      if (! File.Exists(filename))
         SaveDates();
      else
         RestoreDates();
   }

   private static void SaveDates()
   {
      DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0), 
                           new DateTime(2014, 7, 10, 23, 49, 0),  
                           new DateTime(2015, 1, 10, 1, 16, 0), 
                           new DateTime(2014, 12, 20, 21, 45, 0), 
                           new DateTime(2014, 6, 2, 15, 14, 0) }; 
      string output = null;

      Console.WriteLine("Current Time Zone: {0}",
                        TimeZoneInfo.Local.DisplayName);
      Console.WriteLine("The dates on an {0} system:", 
                        Thread.CurrentThread.CurrentCulture.Name);
      for (int ctr = 0; ctr < dates.Length; ctr++) { 
         Console.WriteLine(dates[ctr].ToString("f"));
         output += dates[ctr].ToUniversalTime().ToString("O", CultureInfo.InvariantCulture) 
                   + (ctr != dates.Length - 1 ? "|" : "");
      }
      StreamWriter sw = new StreamWriter(filename);
      sw.Write(output);
      sw.Close();
      Console.WriteLine("Saved dates...");
   }

   private static void RestoreDates()
   {
      TimeZoneInfo.ClearCachedData();
      Console.WriteLine("Current Time Zone: {0}",
                        TimeZoneInfo.Local.DisplayName);
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
      StreamReader sr = new StreamReader(filename);
      string[] inputValues = sr.ReadToEnd().Split( new char[] { '|' } , 
                                                  StringSplitOptions.RemoveEmptyEntries);
      sr.Close();
      Console.WriteLine("The dates on an {0} system:", 
                        Thread.CurrentThread.CurrentCulture.Name);
      foreach (var inputValue in inputValues) {
         DateTime dateValue;
         if (DateTime.TryParseExact(inputValue, "O", CultureInfo.InvariantCulture, 
                               DateTimeStyles.RoundtripKind, out dateValue)) {
            Console.WriteLine("'{0}' --> {1:f}", 
                              inputValue, dateValue.ToLocalTime());
         }
         else {
            Console.WriteLine("Cannot parse '{0}'", inputValue);   
         }
      }
      Console.WriteLine("Restored dates...");   
   }
}
// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       '2014-06-14T13:32:00.0000000Z' --> 14 June 2014 14:32
//       '2014-07-11T06:49:00.0000000Z' --> 11 July 2014 07:49
//       '2015-01-10T09:16:00.0000000Z' --> 10 January 2015 09:16
//       '2014-12-21T05:45:00.0000000Z' --> 21 December 2014 05:45
//       '2014-06-02T22:14:00.0000000Z' --> 02 June 2014 23:14
//       Restored dates...

Persisting values as integers

Instead of persisting a DateTime value as a string, you can persist it as an Int64 value that represents a number of ticks. In this case, you don't have to consider the culture of the systems the DateTime values are persisted and restored on.

To persist a DateTime value as an integer:

  • If the DateTime values represent single moments in time, convert them to UTC by calling the ToUniversalTime method.

  • Retrieve the number of ticks represented by the DateTime value from its Ticks property.

To restore a DateTime value that has been persisted as an integer:

  1. Instantiate a new DateTime object by passing the Int64 value to the DateTime(Int64) constructor.

  2. If the DateTime value represents a single moment in time, convert it from UTC to the local time by calling the ToLocalTime method.

The following example persists an array of DateTime values as integers on a system in the U.S. Pacific Time zone. It restores it on a system in the UTC zone. The file that contains the integers includes an Int32 value that indicates the total number of Int64 values that immediately follow it.

using System;
using System.Globalization;
using System.IO;
using System.Threading;

class Example
{
   private const string filename = @".\IntDates.bin";

   public static void Main()
   {
      if (! File.Exists(filename))
         SaveDates();
      else
         RestoreDates();
   }

   private static void SaveDates()
   {
      DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0), 
                           new DateTime(2014, 7, 10, 23, 49, 0),  
                           new DateTime(2015, 1, 10, 1, 16, 0), 
                           new DateTime(2014, 12, 20, 21, 45, 0), 
                           new DateTime(2014, 6, 2, 15, 14, 0) }; 

      Console.WriteLine("Current Time Zone: {0}",
                        TimeZoneInfo.Local.DisplayName);
      Console.WriteLine("The dates on an {0} system:", 
                        Thread.CurrentThread.CurrentCulture.Name);
      long[] ticks = new long[dates.Length];
      for (int ctr = 0; ctr < dates.Length; ctr++) { 
         Console.WriteLine(dates[ctr].ToString("f"));
         ticks[ctr] = dates[ctr].ToUniversalTime().Ticks; 
      }
      FileStream fs = new FileStream(filename, FileMode.Create);
      BinaryWriter bw = new BinaryWriter(fs);
      bw.Write(ticks.Length);
      foreach (var tick in ticks)
         bw.Write(tick);

      bw.Close();
      Console.WriteLine("Saved dates...");
   }

   private static void RestoreDates()
   {
      TimeZoneInfo.ClearCachedData();
      Console.WriteLine("Current Time Zone: {0}",
                        TimeZoneInfo.Local.DisplayName);
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
      FileStream fs = new FileStream(filename, FileMode.Open);
      BinaryReader br = new BinaryReader(fs);
      int items;
      DateTime[] dates;

      try { 
         items = br.ReadInt32();
         dates = new DateTime[items];

         for (int ctr = 0; ctr < items; ctr++) {
            long ticks = br.ReadInt64();
            dates[ctr] = new DateTime(ticks).ToLocalTime();
         }
      }   
      catch (EndOfStreamException) {
         Console.WriteLine("File corruption detected. Unable to restore data...");
         return;
      }   
      catch (IOException) {
         Console.WriteLine("Unspecified I/O error. Unable to restore data...");
         return;
      }
      // Thrown during array initialization.
      catch (OutOfMemoryException) {
         Console.WriteLine("File corruption detected. Unable to restore data...");
         return;
      }
      finally {      
         br.Close();
      }   

      Console.WriteLine("The dates on an {0} system:", 
                        Thread.CurrentThread.CurrentCulture.Name);
      foreach (var value in dates)
         Console.WriteLine(value.ToString("f"));

      Console.WriteLine("Restored dates...");   
   }
}
// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       14 June 2014 14:32
//       11 July 2014 07:49
//       10 January 2015 09:16
//       21 December 2014 05:45
//       02 June 2014 23:14
//       Restored dates...

Serializing DateTime values

Instead of saving DateTime values as strings or integers, which you then have to convert back to DateTime values, you can persist DateTimevalues through serialization to a stream or file, and then restore them through deserialization. In this case, DateTimedata is serialized in some specified object format, and the objects are restored when they are deserialized. A formatter or serializer, such as XmlSerializer orBinaryFormatter, handles the process of serialization and deserialization. For more information about serialization and the types of serialization supported by the .NET Framework, see Serialization in the .NET Framework.

The following example uses the XmlSerializer class to serialize and deserialize DateTime values that represent all leap year days in the twenty-first century. The output represents the result if the example is run on a system whose current culture is English (Great Britain). Because we've deserialized the DateTime object itself, the code doesn't have to handle cultural differences in date and time formats.

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Xml.Serialization;

class Example
{
   private const string filename = @".\LeapYears.xml";

   public static void Main()
   {
      // Serialize the data.
      List<DateTime> leapYears = new List<DateTime>();
      for (int year = 2000; year <= 2100; year += 4) {
         if (DateTime.IsLeapYear(year)) 
            leapYears.Add(new DateTime(year, 2, 29));
      }
      DateTime[] dateArray = leapYears.ToArray();

      XmlSerializer serializer = new XmlSerializer(dateArray.GetType());
      TextWriter sw = new StreamWriter(filename);

      try {
         serializer.Serialize(sw, dateArray);
      }
      catch (InvalidOperationException e) {
         Console.WriteLine(e.InnerException.Message);         
      }
      finally {
         if (sw != null) sw.Close();
      }   

      // Deserialize the data.
      DateTime[] deserializedDates;
      using (FileStream fs = new FileStream(filename, FileMode.Open)) {
         deserializedDates = (DateTime[]) serializer.Deserialize(fs);
      } 

      // Display the dates.
      Console.WriteLine("Leap year days from 2000-2100 on an {0} system:",
                        Thread.CurrentThread.CurrentCulture.Name);
      int nItems = 0;
      foreach (var dat in deserializedDates) {
         Console.Write("   {0:d}     ", dat);
         nItems++;
         if (nItems % 5 == 0) 
               Console.WriteLine(); 
      }
   }
}
// The example displays the following output:
//    Leap year days from 2000-2100 on an en-GB system:
//       29/02/2000       29/02/2004       29/02/2008       29/02/2012       29/02/2016
//       29/02/2020       29/02/2024       29/02/2028       29/02/2032       29/02/2036
//       29/02/2040       29/02/2044       29/02/2048       29/02/2052       29/02/2056
//       29/02/2060       29/02/2064       29/02/2068       29/02/2072       29/02/2076
//       29/02/2080       29/02/2084       29/02/2088       29/02/2092       29/02/2096

The previous example doesn't include time information. However, if a DateTime value represents a moment in time and is expressed as a local time, you should convert it from local time to UTC before serializing it by calling the ToUniversalTime method. After you deserialize it, you should convert it from UTC to local time by calling the ToLocalTime method. The following example uses the BinaryFormatter class to serializeDateTime data on a system in the U.S. Pacific Standard Time zone and to deserialize it on a system in the UTC zone.

using System;
using System.IO;
using System.Globalization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;

class Example
{
   private const string filename = @".\Dates.bin";

   public static void Main()
   {
      if (! File.Exists(filename))
         SaveDates();
      else
         RestoreDates();
   }

   private static void SaveDates()
   {
      DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0), 
                           new DateTime(2014, 7, 10, 23, 49, 0),  
                           new DateTime(2015, 1, 10, 1, 16, 0), 
                           new DateTime(2014, 12, 20, 21, 45, 0), 
                           new DateTime(2014, 6, 2, 15, 14, 0) }; 
      FileStream fs = new FileStream(filename, FileMode.Create);
      BinaryFormatter bin = new BinaryFormatter();

      Console.WriteLine("Current Time Zone: {0}",
                        TimeZoneInfo.Local.DisplayName);
      Console.WriteLine("The dates on an {0} system:", 
                        Thread.CurrentThread.CurrentCulture.Name);
      for (int ctr = 0; ctr < dates.Length; ctr++) { 
         Console.WriteLine(dates[ctr].ToString("f"));
         dates[ctr] = dates[ctr].ToUniversalTime();
      }
      bin.Serialize(fs, dates);
      fs.Close();
      Console.WriteLine("Saved dates...");
   }

   private static void RestoreDates()
   {
      TimeZoneInfo.ClearCachedData();
      Console.WriteLine("Current Time Zone: {0}",
                        TimeZoneInfo.Local.DisplayName);
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");

      FileStream fs = new FileStream(filename, FileMode.Open);
      BinaryFormatter bin = new BinaryFormatter();
      DateTime[] dates = (DateTime[]) bin.Deserialize(fs);
      fs.Close();

      Console.WriteLine("The dates on an {0} system:", 
                        Thread.CurrentThread.CurrentCulture.Name);
      foreach (var value in dates)
         Console.WriteLine(value.ToLocalTime().ToString("f"));

      Console.WriteLine("Restored dates...");   
   }
}
// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       14 June 2014 14:32
//       11 July 2014 07:49
//       10 January 2015 09:16
//       21 December 2014 05:45
//       02 June 2014 23:14
//       Restored dates...

Serializing DateTime and time zone data

The previous examples have all assumed that DateTime values are expressed as local times, and converted the values between UTC and local time so they reflect the same moment in time on the source and target systems. DateTime values may also reflect moments in time in a time zone other than local and UTC. In this case, because the DateTime structure is not time zone-aware, you have to serialize both theDateTimevalue and the TimeZoneInfo object that represents its time zone. To do this, create a type whose fields include both the DateTimevalue and its time zone. The following example defines a DateWithTimeZone structure that illustrates how this might be done.

using System;

namespace DateTimeExtensions
{
   [Serializable] public struct DateWithTimeZone
   {
      private TimeZoneInfo tz;
      private DateTime dt;

      public DateWithTimeZone(DateTime dateValue, TimeZoneInfo timeZone)
      {
         dt = dateValue;
         if (timeZone == null)
            tz = TimeZoneInfo.Local;
         else
            tz = timeZone;
      }   

      public TimeZoneInfo TimeZone 
      { get { return (tz); }
        set { tz = value; } }

      public DateTime DateTime 
      { get { return (dt); }
        set { dt = value; } }
   }
}
System_CAPS_importantImportant

The DateWithTimeZone structure is used in the next two examples, which serialize and deserialize an array of DateWithTimeZone objects. To run the examples, first create a class library that contains the DateWithTimeZone structure, and then add a reference to it when you compile each example.

By using the DateWithTimeZone structure , you can then persist date and time along with time zone information. The following example uses the BinaryFormatter class to serialize an array of DateWithTimeZoneobjects.

using System;
using DateTimeExtensions;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public class Example
{
   public static void Main()
   {
      DateWithTimeZone[] dates= { new DateWithTimeZone(new DateTime(2014, 8, 9, 19, 30, 0),  
                                      TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")),
                                  new DateWithTimeZone(new DateTime(2014, 8, 15, 19, 0, 0), 
                                      TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time")),  
                                  new DateWithTimeZone(new DateTime(2014, 8, 22, 19, 30, 0),  
                                      TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")),  
                                  new DateWithTimeZone(new DateTime(2014, 8, 28, 19, 0, 0), 
                                      TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")) };
      FileStream fs = new FileStream(@".\Schedule.bin", FileMode.Create);
      BinaryFormatter formatter = new BinaryFormatter();
      try {
         formatter.Serialize(fs, dates);
         // Display dates.
         foreach (var date in dates) {
            TimeZoneInfo tz = date.TimeZone;
            Console.WriteLine("{0} {1}", date.DateTime, 
                              tz.IsDaylightSavingTime(date.DateTime) ? 
                              tz.DaylightName : tz.StandardName);      
         }
      }
      catch (SerializationException e) {
         Console.WriteLine("Serialization failed. Reason: {0}", e.Message);
      }   
      finally {
         if (fs != null) fs.Close();
      }
   }
}
// The example displays the following output:
//       8/9/2014 7:30:00 PM Eastern Daylight Time
//       8/15/2014 7:00:00 PM Pacific Daylight Time
//       8/22/2014 7:30:00 PM Eastern Daylight Time
//       8/28/2014 7:00:00 PM Eastern Daylight Time

The following example then calls the BinaryFormatter.Deserialize method to deserialize it.

using System;
using DateTimeExtensions;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public class Example
{
   private const string filename = @".\Schedule.bin";

   public static void Main()
   {
      FileStream fs;
      if (File.Exists(filename))
         fs = new FileStream(filename, FileMode.Open);
      else {
         Console.WriteLine("Unable to find file to deserialize.");
         return;
      }

      BinaryFormatter formatter = new BinaryFormatter();
      DateWithTimeZone[] dates;
      try {
         dates = (DateWithTimeZone[]) formatter.Deserialize(fs);
         // Display dates.
         foreach (var date in dates) {
            TimeZoneInfo tz = date.TimeZone;
            Console.WriteLine("{0} {1}", date.DateTime, 
                              tz.IsDaylightSavingTime(date.DateTime) ? 
                              tz.DaylightName : tz.StandardName);      
         }
      }
      catch (SerializationException e) {
         Console.WriteLine("Deserialization failed. Reason: {0}", e.Message);
      }   
      finally {
         if (fs != null) fs.Close();
      }
   }
}
// The example displays the following output:
//       8/9/2014 7:30:00 PM Eastern Daylight Time
//       8/15/2014 7:00:00 PM Pacific Daylight Time
//       8/22/2014 7:30:00 PM Eastern Daylight Time
//       8/28/2014 7:00:00 PM Eastern Daylight Time

COM interop considerations

DateTime value that is transferred to a COM application, then is transferred back to a managed application, is said to round-trip. However, aDateTime value that specifies only a time does not round-trip as you might expect.

If you round-trip only a time, such as 3 P.M., the final date and time is December 30, 1899 C.E. at 3:00 P.M., instead of January, 1, 0001 C.E. at 3:00 P.M. This happens because the .NET Framework and COM assume a default date when only a time is specified. However, the COM system assumes a base date of December 30, 1899 C.E. while the .NET Framework assumes a base date of January, 1, 0001 C.E.

When only a time is passed from the .NET Framework to COM, special processing is performed that converts the time to the format used by COM. When only a time is passed from COM to the .NET Framework, no special processing is performed because that would corrupt legitimate dates and times on or before December 30, 1899. This also means if a date starts its round-trip from COM, the .NET Framework and COM preserve the date.

The behavior of the .NET Framework and COM means that if your application round-trips a DateTime that only specifies a time, your application must remember to modify or ignore the erroneous date from the final DateTime object.

Examples

The following example demonstrates how to compare roughly equivalent DateTime values, accepting a small margin of difference when declaring them equal.

using System;

class DateTimeTester 
{
   static bool RoughlyEquals(DateTime time, DateTime timeWithWindow, int windowInSeconds, int frequencyInSeconds)
   {
      long delta = (long)((TimeSpan)(timeWithWindow - time)).TotalSeconds 
                                                     % frequencyInSeconds;

      delta = delta > windowInSeconds ? frequencyInSeconds - delta : delta;

      return Math.Abs(delta) < windowInSeconds;
	}

	public static void Main() 
	{
      int window = 10;
      int freq = 60 * 60 * 2; // 2 hours;

      DateTime d1 = DateTime.Now;

      DateTime d2 = d1.AddSeconds(2 * window);
      DateTime d3 = d1.AddSeconds(-2 * window);
      DateTime d4 = d1.AddSeconds(window / 2);
      DateTime d5 = d1.AddSeconds(-window / 2);

      DateTime d6 = (d1.AddHours(2)).AddSeconds(2 * window);
      DateTime d7 = (d1.AddHours(2)).AddSeconds(-2 * window);
      DateTime d8 = (d1.AddHours(2)).AddSeconds(window / 2);
      DateTime d9 = (d1.AddHours(2)).AddSeconds(-window / 2);

      Console.WriteLine("d1 ({0}) ~= d1 ({1}): {2}",
                        d1, d1, RoughlyEquals(d1, d1, window, freq));
      Console.WriteLine("d1 ({0}) ~= d2 ({1}): {2}", 
                        d1, d2, RoughlyEquals(d1, d2, window, freq));
      Console.WriteLine("d1 ({0}) ~= d3 ({1}): {2}", 
                        d1, d3, RoughlyEquals(d1, d3, window, freq));
      Console.WriteLine("d1 ({0}) ~= d4 ({1}): {2}", 
                        d1, d4, RoughlyEquals(d1, d4, window, freq));
      Console.WriteLine("d1 ({0}) ~= d5 ({1}): {2}", 
                        d1, d5, RoughlyEquals(d1, d5, window, freq));

      Console.WriteLine("d1 ({0}) ~= d6 ({1}): {2}", 
                        d1, d6, RoughlyEquals(d1, d6, window, freq));
      Console.WriteLine("d1 ({0}) ~= d7 ({1}): {2}", 
                        d1, d7, RoughlyEquals(d1, d7, window, freq));
      Console.WriteLine("d1 ({0}) ~= d8 ({1}): {2}", 
                        d1, d8, RoughlyEquals(d1, d8, window, freq));
      Console.WriteLine("d1 ({0}) ~= d9 ({1}): {2}", 
                        d1, d9, RoughlyEquals(d1, d9, window, freq));
	}
}
// The example displays output similar to the following:
//    d1 (1/28/2010 9:01:26 PM) ~= d1 (1/28/2010 9:01:26 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d2 (1/28/2010 9:01:46 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d3 (1/28/2010 9:01:06 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d4 (1/28/2010 9:01:31 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d5 (1/28/2010 9:01:21 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d6 (1/28/2010 11:01:46 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d7 (1/28/2010 11:01:06 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d8 (1/28/2010 11:01:31 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d9 (1/28/2010 11:01:21 PM): True

Version Information

Universal Windows Platform
Available since 8
.NET Framework
Available since 1.1
Portable Class Library
Supported in: portable .NET platforms
Silverlight
Available since 2.0
Windows Phone Silverlight
Available since 7.0
Windows Phone
Available since 8.1

Thread Safety

All members of this type are thread safe. Members that appear to modify instance state actually return a new instance initialized with the new value. As with any other type, reading and writing to a shared variable that contains an instance of this type must be protected by a lock to guarantee thread safety.

System_CAPS_cautionCaution

Assigning an instance of this type is not thread safe on all hardware platforms because the binary representation of that instance might be too large to assign in a single atomic operation.




TimeSpan Structure

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


Represents a time interval.

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 struct TimeSpan : IComparable, IComparable<TimeSpan>, 
	IEquatable<TimeSpan>, IFormattable

Constructors

NameDescription
System_CAPS_pubmethodTimeSpan(Int32, Int32, Int32)

Initializes a new instance of the TimeSpan structure to a specified number of hours, minutes, and seconds.

System_CAPS_pubmethodTimeSpan(Int32, Int32, Int32, Int32)

Initializes a new instance of the TimeSpan structure to a specified number of days, hours, minutes, and seconds.

System_CAPS_pubmethodTimeSpan(Int32, Int32, Int32, Int32, Int32)

Initializes a new instance of the TimeSpan structure to a specified number of days, hours, minutes, seconds, and milliseconds.

System_CAPS_pubmethodTimeSpan(Int64)

Initializes a new instance of the TimeSpan structure to the specified number of ticks.

Properties

NameDescription
System_CAPS_pubpropertyDays

Gets the days component of the time interval represented by the current TimeSpan structure.

System_CAPS_pubpropertyHours

Gets the hours component of the time interval represented by the current TimeSpan structure.

System_CAPS_pubpropertyMilliseconds

Gets the milliseconds component of the time interval represented by the current TimeSpan structure.

System_CAPS_pubpropertyMinutes

Gets the minutes component of the time interval represented by the current TimeSpan structure.

System_CAPS_pubpropertySeconds

Gets the seconds component of the time interval represented by the current TimeSpan structure.

System_CAPS_pubpropertyTicks

Gets the number of ticks that represent the value of the current TimeSpan structure.

System_CAPS_pubpropertyTotalDays

Gets the value of the current TimeSpan structure expressed in whole and fractional days.

System_CAPS_pubpropertyTotalHours

Gets the value of the current TimeSpan structure expressed in whole and fractional hours.

System_CAPS_pubpropertyTotalMilliseconds

Gets the value of the current TimeSpan structure expressed in whole and fractional milliseconds.

System_CAPS_pubpropertyTotalMinutes

Gets the value of the current TimeSpan structure expressed in whole and fractional minutes.

System_CAPS_pubpropertyTotalSeconds

Gets the value of the current TimeSpan structure expressed in whole and fractional seconds.

Methods

NameDescription
System_CAPS_pubmethodAdd(TimeSpan)

Returns a new TimeSpan object whose value is the sum of the specified TimeSpan object and this instance.

System_CAPS_pubmethodSystem_CAPS_staticCompare(TimeSpan, TimeSpan)

Compares two TimeSpan values and returns an integer that indicates whether the first value is shorter than, equal to, or longer than the second value.

System_CAPS_pubmethodCompareTo(Object)

Compares this instance to a specified object and returns an integer that indicates whether this instance is shorter than, equal to, or longer than the specified object.

System_CAPS_pubmethodCompareTo(TimeSpan)

Compares this instance to a specified TimeSpan object and returns an integer that indicates whether this instance is shorter than, equal to, or longer than the TimeSpan object.

System_CAPS_pubmethodDuration()

Returns a new TimeSpan object whose value is the absolute value of the current TimeSpan object.

System_CAPS_pubmethodEquals(Object)

Returns a value indicating whether this instance is equal to a specified object.(OverridesValueType.Equals(Object).)

System_CAPS_pubmethodEquals(TimeSpan)

Returns a value indicating whether this instance is equal to a specified TimeSpan object.

System_CAPS_pubmethodSystem_CAPS_staticEquals(TimeSpan, TimeSpan)

Returns a value that indicates whether two specified instances of TimeSpan are equal.

System_CAPS_pubmethodSystem_CAPS_staticFromDays(Double)

Returns a TimeSpan that represents a specified number of days, where the specification is accurate to the nearest millisecond.

System_CAPS_pubmethodSystem_CAPS_staticFromHours(Double)

Returns a TimeSpan that represents a specified number of hours, where the specification is accurate to the nearest millisecond.

System_CAPS_pubmethodSystem_CAPS_staticFromMilliseconds(Double)

Returns a TimeSpan that represents a specified number of milliseconds.

System_CAPS_pubmethodSystem_CAPS_staticFromMinutes(Double)

Returns a TimeSpan that represents a specified number of minutes, where the specification is accurate to the nearest millisecond.

System_CAPS_pubmethodSystem_CAPS_staticFromSeconds(Double)

Returns a TimeSpan that represents a specified number of seconds, where the specification is accurate to the nearest millisecond.

System_CAPS_pubmethodSystem_CAPS_staticFromTicks(Int64)

Returns a TimeSpan that represents a specified time, where the specification is in units of ticks.

System_CAPS_pubmethodGetHashCode()

Returns a hash code for this instance.(Overrides ValueType.GetHashCode().)

System_CAPS_pubmethodGetType()

Gets the Type of the current instance.(Inherited from Object.)

System_CAPS_pubmethodNegate()

Returns a new TimeSpan object whose value is the negated value of this instance.

System_CAPS_pubmethodSystem_CAPS_staticParse(String)

Converts the string representation of a time interval to its TimeSpan equivalent.

System_CAPS_pubmethodSystem_CAPS_staticParse(String, IFormatProvider)

Converts the string representation of a time interval to its TimeSpan equivalent by using the specified culture-specific format information.

System_CAPS_pubmethodSystem_CAPS_staticParseExact(String, String, IFormatProvider)

Converts the string representation of a time interval to its TimeSpan equivalent by using the specified format and culture-specific format information. The format of the string representation must match the specified format exactly.

System_CAPS_pubmethodSystem_CAPS_staticParseExact(String, String, IFormatProvider, TimeSpanStyles)

Converts the string representation of a time interval to its TimeSpan equivalent by using the specified format, culture-specific format information, and styles. The format of the string representation must match the specified format exactly.

System_CAPS_pubmethodSystem_CAPS_staticParseExact(String, String[], IFormatProvider)

Converts the string representation of a time interval to its TimeSpan equivalent by using the specified array of format strings and culture-specific format information. The format of the string representation must match one of the specified formats exactly.

System_CAPS_pubmethodSystem_CAPS_staticParseExact(String, String[], IFormatProvider, TimeSpanStyles)

Converts the string representation of a time interval to its TimeSpan equivalent by using the specified formats, culture-specific format information, and styles. The format of the string representation must match one of the specified formats exactly.

System_CAPS_pubmethodSubtract(TimeSpan)

Returns a new TimeSpan object whose value is the difference between the specified TimeSpan object and this instance.

System_CAPS_pubmethodToString()

Converts the value of the current TimeSpan object to its equivalent string representation.(OverridesValueType.ToString().)

System_CAPS_pubmethodToString(String)

Converts the value of the current TimeSpan object to its equivalent string representation by using the specified format.

System_CAPS_pubmethodToString(String, IFormatProvider)

Converts the value of the current TimeSpan object to its equivalent string representation by using the specified format and culture-specific formatting information.

System_CAPS_pubmethodSystem_CAPS_staticTryParse(String, IFormatProvider, TimeSpan)

Converts the string representation of a time interval to its TimeSpan equivalent by using the specified culture-specific formatting information, and returns a value that indicates whether the conversion succeeded.

System_CAPS_pubmethodSystem_CAPS_staticTryParse(String, TimeSpan)

Converts the string representation of a time interval to its TimeSpan equivalent and returns a value that indicates whether the conversion succeeded.

System_CAPS_pubmethodSystem_CAPS_staticTryParseExact(String, String, IFormatProvider, TimeSpan)

Converts the string representation of a time interval to its TimeSpan equivalent by using the specified format and culture-specific format information, and returns a value that indicates whether the conversion succeeded. The format of the string representation must match the specified format exactly.

System_CAPS_pubmethodSystem_CAPS_staticTryParseExact(String, String, IFormatProvider, TimeSpanStyles, TimeSpan)

Converts the string representation of a time interval to its TimeSpan equivalent by using the specified format, culture-specific format information, and styles, and returns a value that indicates whether the conversion succeeded. The format of the string representation must match the specified format exactly.

System_CAPS_pubmethodSystem_CAPS_staticTryParseExact(String, String[], IFormatProvider, TimeSpan)

Converts the specified string representation of a time interval to its TimeSpan equivalent by using the specified formats and culture-specific format information, and returns a value that indicates whether the conversion succeeded. The format of the string representation must match one of the specified formats exactly.

System_CAPS_pubmethodSystem_CAPS_staticTryParseExact(String, String[], IFormatProvider, TimeSpanStyles, TimeSpan)

Converts the specified string representation of a time interval to its TimeSpan equivalent by using the specified formats, culture-specific format information, and styles, and returns a value that indicates whether the conversion succeeded. The format of the string representation must match one of the specified formats exactly.

Fields

NameDescription
System_CAPS_pubfieldSystem_CAPS_staticMaxValue

Represents the maximum TimeSpan value. This field is read-only.

System_CAPS_pubfieldSystem_CAPS_staticMinValue

Represents the minimum TimeSpan value. This field is read-only.

System_CAPS_pubfieldSystem_CAPS_staticTicksPerDay

Represents the number of ticks in 1 day. This field is constant.

System_CAPS_pubfieldSystem_CAPS_staticTicksPerHour

Represents the number of ticks in 1 hour. This field is constant.

System_CAPS_pubfieldSystem_CAPS_staticTicksPerMillisecond

Represents the number of ticks in 1 millisecond. This field is constant.

System_CAPS_pubfieldSystem_CAPS_staticTicksPerMinute

Represents the number of ticks in 1 minute. This field is constant.

System_CAPS_pubfieldSystem_CAPS_staticTicksPerSecond

Represents the number of ticks in 1 second.

System_CAPS_pubfieldSystem_CAPS_staticZero

Represents the zero TimeSpan value. This field is read-only.

Operators

NameDescription
System_CAPS_puboperatorSystem_CAPS_staticAddition(TimeSpan, TimeSpan)

Adds two specified TimeSpan instances.

System_CAPS_puboperatorSystem_CAPS_staticEquality(TimeSpan, TimeSpan)

Indicates whether two TimeSpan instances are equal.

System_CAPS_puboperatorSystem_CAPS_staticGreaterThan(TimeSpan, TimeSpan)

Indicates whether a specified TimeSpan is greater than another specified TimeSpan.

System_CAPS_puboperatorSystem_CAPS_staticGreaterThanOrEqual(TimeSpan, TimeSpan)

Indicates whether a specified TimeSpan is greater than or equal to another specifiedTimeSpan.

System_CAPS_puboperatorSystem_CAPS_staticInequality(TimeSpan, TimeSpan)

Indicates whether two TimeSpan instances are not equal.

System_CAPS_puboperatorSystem_CAPS_staticLessThan(TimeSpan, TimeSpan)

Indicates whether a specified TimeSpan is less than another specified TimeSpan.

System_CAPS_puboperatorSystem_CAPS_staticLessThanOrEqual(TimeSpan, TimeSpan)

Indicates whether a specified TimeSpan is less than or equal to another specifiedTimeSpan.

System_CAPS_puboperatorSystem_CAPS_staticSubtraction(TimeSpan, TimeSpan)

Subtracts a specified TimeSpan from another specified TimeSpan.

System_CAPS_puboperatorSystem_CAPS_staticUnaryNegation(TimeSpan)

Returns a TimeSpan whose value is the negated value of the specified instance.

System_CAPS_puboperatorSystem_CAPS_staticUnaryPlus(TimeSpan)

Returns the specified instance of TimeSpan.

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.

TimeSpan object represents a time interval (duration of time or elapsed time) that is measured as a positive or negative number of days, hours, minutes, seconds, and fractions of a second. The TimeSpan structure can also be used to represent the time of day, but only if the time is unrelated to a particular date. Otherwise, the DateTime or DateTimeOffset structure should be used instead. (For more information about using the TimeSpanstructure to reflect the time of day, see Choosing Between DateTime, DateTimeOffset, TimeSpan, and TimeZoneInfo.)

System_CAPS_noteNote

TimeSpan value represents a time interval and can be expressed as a particular number of days, hours, minutes, seconds, and milliseconds. Because it represents a general interval without reference to a particular start or end point, it cannot be expressed in terms of years and months, both of which have a variable number of days. It differs from a DateTime value, which represents a date and time without reference to a particular time zone, or a DateTimeOffset value, which represents a specific moment of time.

The largest unit of time that the TimeSpan structure uses to measure duration is a day. Time intervals are measured in days for consistency, because the number of days in larger units of time, such as months and years, varies.

The value of a TimeSpan object is the number of ticks that equal the represented time interval. A tick is equal to 100 nanoseconds, or one ten-millionth of a second. The value of a TimeSpan object can range from TimeSpan.MinValue to TimeSpan.MaxValue.

Instantiating a TimeSpan Value

You can instantiate a TimeSpan value in a number of ways:

  • By calling its implicit default constructor. This creates an object whose value is TimeSpan.Zero, as the following example shows.

    TimeSpan interval = new TimeSpan();
    Console.WriteLine(interval.Equals(TimeSpan.Zero));    // Displays "True".
    
  • By calling one of its explicit constructors. The following example initializes a TimeSpan value to a specified number of hours, minutes, and seconds.

    TimeSpan interval = new TimeSpan(2, 14, 18);
    Console.WriteLine(interval.ToString());              // Displays "02:14:18".
    
  • By calling a method or performing an operation that returns a TimeSpan value. For example, you can instantiate a TimeSpan value that represents the interval between two date and time values, as the following example shows.

    DateTime departure = new DateTime(2010, 6, 12, 18, 32, 0);
    DateTime arrival = new DateTime(2010, 6, 13, 22, 47, 0);
    TimeSpan travelTime = arrival - departure;  
    Console.WriteLine("{0} - {1} = {2}", arrival, departure, travelTime);      
    // The example displays the following output:
    //       6/13/2010 10:47:00 PM - 6/12/2010 6:32:00 PM = 1.04:15:00
    

    You can also initialize a TimeSpan object to a zero time value in this way, as the following example shows.

    using System;
    
    public class Example
    {
       static Random rnd = new Random();
    
       public static void Main()
       {
          TimeSpan timeSpent = TimeSpan.Zero;
    
          timeSpent += GetTimeBeforeLunch();
          timeSpent += GetTimeAfterLunch();
    
          Console.WriteLine("Total time: {0}", timeSpent);
       }
    
       private static TimeSpan GetTimeBeforeLunch()
       {
          return new TimeSpan(rnd.Next(3, 6), 0, 0);
       }
    
       private static TimeSpan GetTimeAfterLunch()
       {
          return new TimeSpan(rnd.Next(3, 6), 0, 0);
       }
    }
    // The example displays output like the following:
    //        Total time: 08:00:00
    

    TimeSpan values are returned by arithmetic operators and methods of the DateTimeDateTimeOffset, and TimeSpan structures.

  • By parsing the string representation of a TimeSpan value. You can use the Parse and TryParse methods to convert strings that contain time intervals to TimeSpan values. The following example uses the Parse method to convert an array of strings to TimeSpan values.

    string[] values = { "12", "31.", "5.8:32:16", "12:12:15.95", ".12"};
    foreach (string value in values)
    {
       try {
          TimeSpan ts = TimeSpan.Parse(value);
          Console.WriteLine("'{0}' --> {1}", value, ts);
       }
       catch (FormatException) {
          Console.WriteLine("Unable to parse '{0}'", value);
       }
       catch (OverflowException) {
          Console.WriteLine("'{0}' is outside the range of a TimeSpan.", value);
       }   
    }
    // The example displays the following output:
    //       '12' --> 12.00:00:00
    //       Unable to parse '31.'
    //       '5.8:32:16' --> 5.08:32:16
    //       '12:12:15.95' --> 12:12:15.9500000
    //       Unable to parse '.12'  
    

    In addition, you can define the precise format of the input string to be parsed and converted to a TimeSpan value by calling the ParseExactor TryParseExact method.

Performing Operations on TimeSpan Values

You can add and subtract time durations either by using the Addition and Subtraction operators, or by calling the Add and Subtract methods. You can also compare two time durations by calling the CompareCompareTo, and Equals methods. The TimeSpan structure also includes the Durationand Negate methods, which convert time intervals to positive and negative values,

The range of TimeSpan values is MinValue to MaxValue.

Formatting a TimeSpan Value

TimeSpan value can be represented as [-]d.hh:mm:ss.ff, where the optional minus sign indicates a negative time interval, the d component is days, hh is hours as measured on a 24-hour clock, mm is minutes, ss is seconds, and ff is fractions of a second. That is, a time interval consists of a positive or negative number of days without a time of day, or a number of days with a time of day, or only a time of day.

Beginning with the .NET Framework 4, the TimeSpan structure supports culture-sensitive formatting through the overloads of its ToString method, which converts a TimeSpan value to its string representation. The default TimeSpan.ToString() method returns a time interval by using an invariant format that is identical to its return value in previous versions of the .NET Framework. The TimeSpan.ToString(String) overload lets you specify a format string that defines the string representation of the time interval. The TimeSpan.ToString(String, IFormatProvider) overload lets you specify a format string and the culture whose formatting conventions are used to create the string representation of the time interval. TimeSpan supports both standard and custom format strings. (For more information, see Standard TimeSpan Format Strings and Custom TimeSpan Format Strings.) However, only standard format strings are culture-sensitive.

Restoring Legacy TimeSpan Formatting

In some cases, code that successfully formats TimeSpan values in .NET Framework 3.5 and earlier versions fails in .NET Framework 4. This is most common in code that calls a <TimeSpan_LegacyFormatMode> element method to format a TimeSpan value with a format string. The following example successfully formats a TimeSpan value in .NET Framework 3.5 and earlier versions, but throws an exception in .NET Framework 4 and later versions. Note that it attempts to format a TimeSpan value by using an unsupported format specifier, which is ignored in .NET Framework 3.5 and earlier versions.

TimeSpan interval = new TimeSpan(12, 30, 45);
string output;
try {
   output = String.Format("{0:r}", interval);
}
catch (FormatException) {
   output = "Invalid Format";
}
Console.WriteLine(output);
// Output from .NET Framework 3.5 and earlier versions:
//       12:30:45
// Output from .NET Framework 4:
//       Invalid Format

If you cannot modify the code, you can restore the legacy formatting of TimeSpan values in one of the following ways:

  • By creating a configuration file that contains the <TimeSpan_LegacyFormatMode> element. Setting this element's enabled attribute totrue restores legacy TimeSpan formatting on a per-application basis.

  • By setting the "NetFx40_TimeSpanLegacyFormatMode" compatibility switch when you create an application domain. This enables legacyTimeSpan formatting on a per-application-domain basis. The following example creates an application domain that uses legacy TimeSpanformatting.

    using System;
    
    public class Example
    {
       public static void Main()
       {
          AppDomainSetup appSetup = new AppDomainSetup();
          appSetup.SetCompatibilitySwitches( new string[] { "NetFx40_TimeSpanLegacyFormatMode" } );
          AppDomain legacyDomain = AppDomain.CreateDomain("legacyDomain", 
                                                          null, appSetup);
          legacyDomain.ExecuteAssembly("ShowTimeSpan.exe");
       }
    }
    

    When the following code executes in the new application domain, it reverts to legacy TimeSpan formatting behavior.

    using System;
    
    public class Example
    {
       public static void Main()
       {
          TimeSpan interval = DateTime.Now - DateTime.Now.Date;
          string msg = String.Format("Elapsed Time Today: {0:d} hours.",
                                     interval);
          Console.WriteLine(msg);
       }
    }
    // The example displays the following output:
    //       Elapsed Time Today: 01:40:52.2524662 hours.
    

Examples

The following example instantiates a TimeSpan object that represents the difference between two dates. It then displays the TimeSpan object's properties.

// Define two dates.
DateTime date1 = new DateTime(2010, 1, 1, 8, 0, 15);
DateTime date2 = new DateTime(2010, 8, 18, 13, 30, 30);
// Calculate the interval between the two dates.
TimeSpan interval = date2 - date1;
Console.WriteLine("{0} - {1} = {2}", date2, date1, interval.ToString());
// Display individual properties of the resulting TimeSpan object.
Console.WriteLine("   {0,-35} {1,20}", "Value of Days Component:", interval.Days);
Console.WriteLine("   {0,-35} {1,20}", "Total Number of Days:", interval.TotalDays);
Console.WriteLine("   {0,-35} {1,20}", "Value of Hours Component:", interval.Hours);
Console.WriteLine("   {0,-35} {1,20}", "Total Number of Hours:", interval.TotalHours);
Console.WriteLine("   {0,-35} {1,20}", "Value of Minutes Component:", interval.Minutes);
Console.WriteLine("   {0,-35} {1,20}", "Total Number of Minutes:", interval.TotalMinutes);
Console.WriteLine("   {0,-35} {1,20:N0}", "Value of Seconds Component:", interval.Seconds);
Console.WriteLine("   {0,-35} {1,20:N0}", "Total Number of Seconds:", interval.TotalSeconds);
Console.WriteLine("   {0,-35} {1,20:N0}", "Value of Milliseconds Component:", interval.Milliseconds);
Console.WriteLine("   {0,-35} {1,20:N0}", "Total Number of Milliseconds:", interval.TotalMilliseconds);
Console.WriteLine("   {0,-35} {1,20:N0}", "Ticks:", interval.Ticks);
// the example displays the following output:
//       8/18/2010 1:30:30 PM - 1/1/2010 8:00:15 AM = 229.05:30:15
//          Value of Days Component:                             229
//          Total Number of Days:                   229.229340277778
//          Value of Hours Component:                              5
//          Total Number of Hours:                  5501.50416666667
//          Value of Minutes Component:                           30
//          Total Number of Minutes:                       330090.25
//          Value of Seconds Component:                           15
//          Total Number of Seconds:                      19,805,415
//          Value of Milliseconds Component:                       0
//          Total Number of Milliseconds:             19,805,415,000
//          Ticks:                               198,054,150,000,000

Version Information

Universal Windows Platform
Available since 8
.NET Framework
Available since 1.1
Portable Class Library
Supported in: portable .NET platforms
Silverlight
Available since 2.0
Windows Phone Silverlight
Available since 7.0
Windows Phone
Available since 8.1

Thread Safety

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.




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

IEnumerable Interface  (0) 2016.11.14
Predicate<T> Delegate  (0) 2016.10.18
C# 코딩 규칙  (0) 2016.08.28
예외 및 예외 처리  (0) 2016.08.26
파일 시스템 및 레지스트리  (0) 2016.08.25
:
Posted by 지훈2
2016. 9. 23. 04:40

WPF 고급 - 아키텍처, XAML 프로그래밍/WPF2016. 9. 23. 04:40

고급

https://msdn.microsoft.com/ko-kr/library/ms746927(v=vs.110).aspx





WPF 아키텍처


This topic provides a guided tour of the Windows Presentation Foundation (WPF) class hierarchy. It covers most of the major subsystems of WPF, and describes how they interact. It also details some of the choices made by the architects of WPF.

The primary WPF programming model is exposed through managed code. Early in the design phase of WPF there were a number of debates about where the line should be drawn between the managed components of the system and the unmanaged ones. The CLR provides a number of features that make development more productive and robust (including memory management, error handling, common type system, etc.) but they come at a cost.

The major components of WPF are illustrated in the figure below. The red sections of the diagram (PresentationFramework, PresentationCore, and milcore) are the major code portions of WPF. Of these, only one is an unmanaged component – milcore. Milcore is written in unmanaged code in order to enable tight integration with DirectX. All display in WPF is done through the DirectX engine, allowing for efficient hardware and software rendering. WPF also required fine control over memory and execution. The composition engine in milcore is extremely performance sensitive, and required giving up many advantages of the CLR to gain performance.

.NET Framework 내 WPF의 위치

Communication between the managed and unmanaged portions of WPF is discussed later in this topic. The remainder of the managed programming model is described below.

Most objects in WPF derive from DispatcherObject, which provides the basic constructs for dealing with concurrency and threading. WPF is based on a messaging system implemented by the dispatcher. This works much like the familiar Win32 message pump; in fact, the WPF dispatcher uses User32 messages for performing cross thread calls.

There are really two core concepts to understand when discussing concurrency in WPF – the dispatcher and thread affinity.

During the design phase of WPF, the goal was to move to a single thread of execution, but a non-thread "affinitized" model. Thread affinity happens when a component uses the identity of the executing thread to store some type of state. The most common form of this is to use the thread local store (TLS) to store state. Thread affinity requires that each logical thread of execution be owned by only one physical thread in the operating system, which can become memory intensive. In the end, WPF’s threading model was kept in sync with the existing User32 threading model of single threaded execution with thread affinity. The primary reason for this was interoperability – systems like OLE 2.0, the clipboard, and Internet Explorer all require single thread affinity (STA) execution.

Given that you have objects with STA threading, you need a way to communicate between threads, and validate that you are on the correct thread. Herein lies the role of the dispatcher. The dispatcher is a basic message dispatching system, with multiple prioritized queues. Examples of messages include raw input notifications (mouse moved), framework functions (layout), or user commands (execute this method). By deriving from DispatcherObject, you create a CLR object that has STA behavior, and will be given a pointer to a dispatcher at creation time.

One of the primary architectural philosophies used in building WPF was a preference for properties over methods or events. Properties are declarative and allow you to more easily specify intent instead of action. This also supported a model driven, or data driven, system for displaying user interface content. This philosophy had the intended effect of creating more properties that you could bind to, in order to better control the behavior of an application.

In order to have more of the system driven by properties, a richer property system than what the CLR provides was needed. A simple example of this richness is change notifications. In order to enable two way binding, you need both sides of the bind to support change notification. In order to have behavior tied to property values, you need to be notified when the property value changes. The Microsoft .NET Framework has an interface, INotifyPropertyChange, which allows an object to publish change notifications, however it is optional.

WPF provides a richer property system, derived from the DependencyObject type. The property system is truly a "dependency" property system in that it tracks dependencies between property expressions and automatically revalidates property values when dependencies change. For example, if you have a property that inherits (like FontSize), the system is automatically updated if the property changes on a parent of an element that inherits the value.

The foundation of the WPF property system is the concept of a property expression. In this first release of WPF, the property expression system is closed, and the expressions are all provided as part of the framework. Expressions are why the property system doesn’t have data binding, styling, or inheritance hard coded, but rather provided by later layers within the framework.

The property system also provides for sparse storage of property values. Because objects can have dozens (if not hundreds) of properties, and most of the values are in their default state (inherited, set by styles, etc.), not every instance of an object needs to have the full weight of every property defined on it.

The final new feature of the property system is the notion of attached properties. WPF elements are built on the principle of composition and component reuse. It is often the case that some containing element (like a Grid layout element) needs additional data on child elements to control its behavior (like the Row/Column information). Instead of associating all of these properties with every element, any object is allowed to provide property definitions for any other object. This is similar to the "expando" features of JavaScript.

With a system defined, the next step is getting pixels drawn to the screen. The Visual class provides for building a tree of visual objects, each optionally containing drawing instructions and metadata about how to render those instructions (clipping, transformation, etc.). Visual is designed to be extremely lightweight and flexible, so most of the features have no public API exposure and rely heavily on protected callback functions.

Visual is really the entry point to the WPF composition system. Visual is the point of connection between these two subsystems, the managed API and the unmanaged milcore.

WPF displays data by traversing the unmanaged data structures managed by the milcore. These structures, called composition nodes, represent a hierarchical display tree with rendering instructions at each node. This tree, illustrated on the right hand side of the figure below, is only accessible through a messaging protocol.

When programming WPF, you create Visual elements, and derived types, which internally communicate to the composition tree through this messaging protocol. Each Visual in WPF may create one, none, or several composition nodes.

Windows Presentation Foundation 시각적 트리

There is a very important architectural detail to notice here – the entire tree of visuals and drawing instructions is cached. In graphics terms, WPF uses a retained rendering system. This enables the system to repaint at high refresh rates without the composition system blocking on callbacks to user code. This helps prevent the appearance of an unresponsive application.

Another important detail that isn’t really noticeable in the diagram is how the system actually performs composition.

In User32 and GDI, the system works on an immediate mode clipping system. When a component needs to be rendered, the system establishes a clipping bounds outside of which the component isn’t allowed to touch the pixels, and then the component is asked to paint pixels in that box. This system works very well in memory constrained systems because when something changes you only have to touch the affected component – no two components ever contribute to the color of a single pixel.

WPF uses a "painter's algorithm" painting model. This means that instead of clipping each component, each component is asked to render from the back to the front of the display. This allows each component to paint over the previous component's display. The advantage of this model is that you can have complex, partially transparent shapes. With today’s modern graphics hardware, this model is relatively fast (which wasn’t the case when User32/ GDI were created).

As mentioned previously, a core philosophy of WPF is to move to a more declarative, "property centric" model of programming. In the visual system, this shows up in a couple of interesting places.

First, if you think about the retained mode graphic system, this is really moving away from an imperative DrawLine/DrawLine type model, to a data oriented model – new Line()/new Line(). This move to data driven rendering allows complex operations on the drawing instructions to be expressed using properties. The types deriving from Drawing are effectively the object model for rendering.

Second, if you evaluate the animation system, you'll see that it is almost completely declarative. Instead of requiring a developer to compute the next location, or next color, you can express animations as a set of properties on an animation object. These animations can then express the intent of the developer or designer (move this button from here to there in 5 seconds), and the system can determine the most efficient way to accomplish that.

UIElement defines core subsystems including Layout, Input, and Events.

Layout is a core concept in WPF. In many systems there is either a fixed set of layout models (HTML supports three models for layout; flow, absolute, and tables) or no model for layout (User32 really only supports absolute positioning). WPF started with the assumption that developers and designers wanted a flexible, extensible layout model, which could be driven by property values rather than imperative logic. At the UIElement level, the basic contract for layout is introduced – a two phase model with Measure and Arrange passes.

Measure allows a component to determine how much size it would like to take. This is a separate phase from Arrange because there are many situations where a parent element will ask a child to measure several times to determine its optimal position and size. The fact that parent elements ask child elements to measure demonstrates another key philosophy of WPF – size to content. All controls in WPF support the ability to size to the natural size of their content. This makes localization much easier, and allows for dynamic layout of elements as things resize. TheArrange phase allows a parent to position and determine the final size of each child.

A lot of time is often spent talking about the output side of WPF – Visual and related objects. However there is a tremendous amount of innovation on the input side as well. Probably the most fundamental change in the input model for WPF is the consistent model by which input events are routed through the system.

Input originates as a signal on a kernel mode device driver and gets routed to the correct process and thread through an intricate process involving the Windows kernel and User32. Once the User32 message corresponding to the input is routed to WPF, it is converted into a WPF raw input message and sent to the dispatcher. WPF allows for raw input events to be converted to multiple actual events, enabling features like "MouseEnter" to be implemented at a low level of the system with guaranteed delivery.

Each input event is converted to at least two events – a "preview" event and the actual event. All events in WPF have a notion of routing through the element tree. Events are said to "bubble" if they traverse from a target up the tree to the root, and are said to "tunnel" if that start at the root and traverse down to a target. Input preview events tunnel, enabling any element in the tree an opportunity to filter or take action on the event. The regular (non-preview) events then bubble from the target up to the root.

This split between the tunnel and bubble phase makes implementation of features like keyboard accelerators work in a consistent fashion in a composite world. In User32 you would implement keyboard accelerators by having a single global table containing all the accelerators you wanted to support (Ctrl+N mapping to "New"). In the dispatcher for your application you would call TranslateAccelerator which would sniff the input messages in User32 and determine if any matched a registered accelerator. In WPF this wouldn’t work because the system is fully "composable" – any element can handle and use any keyboard accelerator. Having this two phase model for input allows components to implement their own "TranslateAccelerator".

To take this one step further, UIElement also introduces the notion of CommandBindings. The WPF command system allows developers to define functionality in terms of a command end point – something that implements ICommand. Command bindings enable an element to define a mapping between an input gesture (Ctrl+N) and a command (New). Both the input gestures and command definitions are extensible, and can be wired together at usage time. This makes it trivial, for example, to allow an end user to customize the key bindings that they want to use within an application.

To this point in the topic, "core" features of WPF – features implemented in the PresentationCore assembly, have been the focus. When building WPF, a clean separation between foundational pieces (like the contract for layout with Measure and Arrange) and framework pieces (like the implementation of a specific layout like Grid) was the desired outcome. The goal was to provide an extensibility point low in the stack that would allow external developers to create their own frameworks if needed.

FrameworkElement can be looked at in two different ways. It introduces a set of policies and customizations on the subsystems introduced in lower layers of WPF. It also introduces a set of new subsystems.

The primary policy introduced by FrameworkElement is around application layout. FrameworkElement builds on the basic layout contract introduced by UIElement and adds the notion of a layout "slot" that makes it easier for layout authors to have a consistent set of property driven layout semantics. Properties like HorizontalAlignmentVerticalAlignmentMinWidth, and Margin (to name a few) give all components derived from FrameworkElement consistent behavior inside of layout containers.

FrameworkElement also provides easier API exposure to many features found in the core layers of WPF. For example, FrameworkElementprovides direct access to animation through the BeginStoryboard method. Storyboard provides a way to script multiple animations against a set of properties.

The two most critical things that FrameworkElement introduces are data binding and styles.

The data binding subsystem in WPF should be relatively familiar to anyone that has used Windows Forms or ASP.NET for creating an application user interface (UI). In each of these systems, there is a simple way to express that you want one or more properties from a given element to be bound to a piece of data. WPF has full support for property binding, transformation, and list binding.

One of the most interesting features of data binding in WPF is the introduction of data templates. Data templates allow you to declaratively specify how a piece of data should be visualized. Instead of creating a custom user interface that can be bound to data, you can instead turn the problem around and let the data determine the display that will be created.

Styling is really a lightweight form of data binding. Using styling you can bind a set of properties from a shared definition to one or more instances of an element. Styles get applied to an element either by explicit reference (by setting the Style property) or implicitly by associating a style with the CLR type of the element.

Control’s most significant feature is templating. If you think about WPF’s composition system as a retained mode rendering system, templating allows a control to describe its rendering in a parameterized, declarative manner. ControlTemplate is really nothing more than a script to create a set of child elements, with bindings to properties offered by the control.

Control provides a set of stock properties, ForegroundBackgroundPadding, to name a few, which template authors can then use to customize the display of a control. The implementation of a control provides a data model and interaction model. The interaction model defines a set of commands (like Close for a window) and bindings to input gestures (like clicking the red X in the upper corner of the window).The data model provides a set of properties to either customize the interaction model or customize the display (determined by the template).

This split between the data model (properties), interaction model (commands and events), and display model (templates) enables complete customization of a control’s look and behavior.

A common aspect of the data model of controls is the content model. If you look at a control like Button, you will see that it has a property named "Content" of type Object. In Windows Forms and ASP.NET, this property would typically be a string – however that limits the type of content you can put in a button. Content for a button can either be a simple string, a complex data object, or an entire element tree. In the case of a data object, the data template is used to construct a display.

WPF is designed to allow you to create dynamic, data driven presentation systems. Every part of the system is designed to create objects through property sets that drive behavior. Data binding is a fundamental part of the system, and is integrated at every layer.

Traditional applications create a display and then bind to some data. In WPF, everything about the control, every aspect of the display, is generated by some type of data binding. The text found inside a button is displayed by creating a composed control inside of the button and binding its display to the button’s content property.

When you begin developing WPF based applications, it should feel very familiar. You can set properties, use objects, and data bind in much the same way that you can using Windows Forms or ASP.NET. With a deeper investigation into the architecture of WPF, you'll find that the possibility exists for creating much richer applications that fundamentally treat data as the core driver of the application.




XAML Overview (WPF)


This topic describes the features of the XAML language and demonstrates how you can use XAML to write Windows Presentation Foundation (WPF) applications. This topic specifically describes XAML as implemented by WPF. XAML itself is a larger language concept than WPF.

What is XAML?

XAML is a declarative markup language. As applied to the .NET Framework programming model, XAML simplifies creating a UI for a .NET Framework application. You can create visible UI elements in the declarative XAML markup, and then separate the UI definition from the run-time logic by using code-behind files, joined to the markup through partial class definitions. XAML directly represents the instantiation of objects in a specific set of backing types defined in assemblies. This is unlike most other markup languages, which are typically an interpreted language without such a direct tie to a backing type system. XAML enables a workflow where separate parties can work on the UI and the logic of an application, using potentially different tools.

When represented as text, XAML files are XML files that generally have the .xaml extension. The files can be encoded by any XML encoding, but encoding as UTF-8 is typical.

The following example shows how you might create a button as part of a UI. This example is just intended to give you a flavor of how XAML represents common UI programming metaphors (it is not a complete sample).

  <StackPanel>
  <Button Content="Click Me"/>
</StackPanel>

XAML Syntax in Brief

The following sections explain the basic forms of XAML syntax, and give a short markup example. These sections are not intended to provide complete information about each syntax form, such as how these are represented in the backing type system. For more information about the specifics of XAML syntax for each of the syntax forms introduced in this topic, see XAML Syntax In Detail.

Much of the material in the next few sections will be elementary to you, if you have previous familiarity with the XML language. This is a consequence of one of the basic design principles of XAML. XAML The XAML language defines concepts of its own, but these concepts work within the XML language and markup form.

XAML Object Elements

An object element typically declares an instance of a type. That type is defined in the assemblies that provide the backing types for a technology that uses XAML as a language.

Object element syntax always starts with an opening angle bracket (<). This is followed by the name of the type where you want to create an instance. (The name can possibly include a prefix, a concept that will be explained later.) After this, you can optionally declare attributes on the object element. To complete the object element tag, end with a closing angle bracket (>). You can instead use a self-closing form that does not have any content, by completing the tag with a forward slash and closing angle bracket in succession (/>). For example, look at the previously shown markup snippet again:

  

This specifies two object elements: <StackPanel> (with content, and a closing tag later), and <Button .../> (the self-closing form, with several attributes). The object elements StackPanel and Button each map to the name of a class that is defined by WPF and is part of the WPF assemblies. When you specify an object element tag, you create an instruction for XAML processing to create a new instance. Each instance is created by calling the default constructor of the underlying type when parsing and loading the XAML.

Attribute Syntax (Properties)

Properties of an object can often be expressed as attributes of the object element. An attribute syntax names the property that is being set in attribute syntax, followed by the assignment operator (=). The value of an attribute is always specified as a string that is contained within quotation marks.

Attribute syntax is the most streamlined property setting syntax and is the most intuitive syntax to use for developers who have used markup languages in the past. For example, the following markup creates a button that has red text and a blue background in addition to display text specified as Content.

<Button Background="Blue" Foreground="Red" Content="This is a button"/>

Property Element Syntax

For some properties of an object element, attribute syntax is not possible, because the object or information necessary to provide the property value cannot be adequately expressed within the quotation mark and string restrictions of attribute syntax. For these cases, a different syntax known as property element syntax can be used.

The syntax for the property element start tag is <typeName.propertyName>. Generally, the content of that tag is an object element of the type that the property takes as its value . After specifying content, you must close the property element with an end tag. The syntax for the end tag is</typeName.propertyName>.

If an attribute syntax is possible, using the attribute syntax is typically more convenient and enables a more compact markup, but that is often just a matter of style, not a technical limitation. The following example shows the same properties being set as in the previous attribute syntax example, but this time by using property element syntax for all properties of the Button.

<Button> <Button.Background> <SolidColorBrush Color="Blue"/> </Button.Background> <Button.Foreground> <SolidColorBrush Color="Red"/> </Button.Foreground> <Button.Content> This is a button </Button.Content> </Button>

Collection Syntax

The XAML language includes some optimizations that produce more human-readable markup. One such optimization is that if a particular property takes a collection type, then items that you declare in markup as child elements within that property's value become part of the collection. In this case a collection of child object elements is the value being set to the collection property.

The following example shows collection syntax for setting values of the GradientStops property:

<LinearGradientBrush>
  <LinearGradientBrush.GradientStops>
    <!-- no explicit new GradientStopCollection, parser knows how to find or create -->
    <GradientStop Offset="0.0" Color="Red" />
    <GradientStop Offset="1.0" Color="Blue" />
  </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

XAML Content Properties

XAML specifies a language feature whereby a class can designate exactly one of its properties to be the XAML content property. Child elements of that object element are used to set the value of that content property. In other words, for the content property uniquely, you can omit a property element when setting that property in XAML markup and produce a more visible parent/child metaphor in the markup.

For example, Border specifies a content property of Child. The following two Border elements are treated identically. The first one takes advantage of the content property syntax and omits the Border.Child property element. The second one shows Border.Child explicitly.

<Border>
  <TextBox Width="300"/>
</Border>
<!--explicit equivalent-->
<Border>
  <Border.Child>
    <TextBox Width="300"/>
  </Border.Child>
</Border>

As a rule of the XAML language, the value of a XAML content property must be given either entirely before or entirely after any other property elements on that object element. For instance, the following markup does not compile:

<Button>I am a 
  <Button.Background>Blue</Button.Background>
  blue button</Button>

For more information about this restriction on XAML content properties, see the "XAML Content Properties" section of XAML Syntax In Detail.

Text Content

A small number of XAML elements can directly process text as their content. To enable this, one of the following cases must be true:

  • The class must declare a content property, and that content property must be of a type assignable to a string (the type could be Object). For instance, any ContentControl uses Content as its content property and it is type Object, and this supports the following usage on a practical ContentControl such as a Button<Button>Hello</Button>.

  • The type must declare a type converter, in which case the text content is used as initialization text for that type converter. For example,<Brush>Blue</Brush>. This case is less common in practice.

  • The type must be a known XAML language primitive.

Content Properties and Collection Syntax Combined

Consider this example:

<StackPanel>
  <Button>First Button</Button>
  <Button>Second Button</Button>
</StackPanel>

Here, each Button is a child element of StackPanel. This is a streamlined and intuitive markup that omits two tags for two different reasons.

  • Omitted StackPanel.Children property element: StackPanel derives from PanelPanel defines Panel.Children as its XAML content property.

  • Omitted UIElementCollection object element: The Panel.Children property takes the type UIElementCollection, which implements IList. The collection's element tag can be omitted, based on the XAML rules for processing collections such as IList. (In this case,UIElementCollection actually cannot be instantiated because it does not expose a default constructor, and that is why theUIElementCollection object element is shown commented out).

<StackPanel>
  <StackPanel.Children>
    <!--<UIElementCollection>-->
    <Button>First Button</Button>
    <Button>Second Button</Button>
    <!--</UIElementCollection>-->
  </StackPanel.Children>
</StackPanel>

Attribute Syntax (Events)

Attribute syntax can also be used for members that are events rather than properties. In this case, the attribute's name is the name of the event. In the WPF implementation of events for XAML, the attribute's value is the name of a handler that implements that event's delegate. For example, the following markup assigns a handler for the Click event to a Button created in markup:

  <Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="MyNamespace.MyPageCode">
  <Button Click="ClickHandler" >Click Me!</Button>
</Page>


namespace MyNamespace
{
  public partial class MyPageCode
  {
    void ClickHandler(object sender, RoutedEventArgs e)
    {
      Button b = e.Source as Button;
      b.Background = Brushes.Red;
    }
  }
}

There is more to events and XAML in WPF than just this example of the attribute syntax. For example, you might wonder what the ClickHandlerreferenced here represents and how it is defined. This will be explained in the upcoming Events and XAML Code-Behind section of this topic.

Case and Whitespace in XAML

XAML is generally speaking case sensitive. For purposes of resolving backing types, WPF XAML is case sensitive by the same rules that the CLR is case sensitive. Object elements, property elements, and attribute names must all be specified by using the sensitive casing when compared by name to the underlying type in the assembly, or to a member of a type. XAML language keywords and primitives are also case sensitive. Values are not always case sensitive. Case sensitivity for values will depend on the type converter behavior associated with the property that takes the value, or the property value type. For example, properties that take the Boolean type can take either true or True as equivalent values, but only because the native WPF XAML parser type conversion for string to Boolean already permits these as equivalents.

WPF XAML processors and serializers will ignore or drop all nonsignificant whitespace, and will normalize any significant whitespace. This is consistent with the default whitespace behavior recommendations of the XAML specification. This behavior is generally only of consequence when you specify strings within XAML content properties. In simplest terms, XAML converts space, linefeed and tab characters into spaces, and then preserves one space if found at either end of a contiguous string. The full explanation of XAML whitespace handling is not covered in this topic. For details, see Whitespace Processing in XAML.

Markup Extensions

Markup extensions are a XAML language concept. When used to provide the value of an attribute syntax, curly braces ({ and }) indicate a markup extension usage. This usage directs the XAML processing to escape from the general treatment of attribute values as either a literal string or a string-convertible value.

The most common markup extensions used in WPF application programming are Binding, used for data binding expressions, and the resource references StaticResource and DynamicResource. By using markup extensions, you can use attribute syntax to provide values for properties even if that property does not support an attribute syntax in general. Markup extensions often use intermediate expression types to enable features such as deferring values or referencing other objects that are only present at run time.

For example, the following markup sets the value of the Style property using attribute syntax. The Style property takes an instance of the Style class, which by default could not be instantiated by an attribute syntax string. But in this case, the attribute references a particular markup extension,StaticResource. When that markup extension is processed, it returns a reference to a style that was previously instantiated as a keyed resource in a resource dictionary.

  <Page.Resources>
  <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
  <Style TargetType="Border" x:Key="PageBackground">
    <Setter Property="Background" Value="Blue"/>
  </Style>

  ...

</Page.Resources>
<StackPanel>
  <Border Style="{StaticResource PageBackground}">

  ...

  </Border>
</StackPanel>

For a reference listing of all markup extensions for XAML implemented specifically in WPF, see WPF XAML Extensions. For a reference listing of the markup extensions that are defined by System.Xaml and are more widely available for .NET Framework XAML implementations, see XAML Namespace (x:) Language Features. For more information about markup extension concepts, see Markup Extensions and WPF XAML.

Type Converters

In the XAML Syntax in Brief section, it was stated that the attribute value must be able to be set by a string. The basic, native handling of how strings are converted into other object types or primitive values is based on the String type itself, in addition to native processing for certain types such asDateTime or Uri. But many WPF types or members of those types extend the basic string attribute processing behavior, in such a way that instances of more complex object types can be specified as strings and attributes.

The Thickness structure is an example of a type that has a type conversion enabled for XAML usages. Thickness indicates measurements within a nested rectangle and is used as the value for properties such as Margin. By placing a type converter on Thickness, all properties that use a Thicknessare easier to specify in XAML because they can be specified as attributes. The following example uses a type conversion and attribute syntax to provide a value for a Margin:

<Button Margin="10,20,10,30" Content="Click me"/>

The previous attribute syntax example is equivalent to the following more verbose syntax example, where the Margin is instead set through property element syntax containing a Thickness object element. The four key properties of Thickness are set as attributes on the new instance:

<Button Content="Click me">
  <Button.Margin>
    <Thickness Left="10" Top="20" Right="10" Bottom="30"/>
  </Button.Margin>
</Button>  
System_CAPS_noteNote

There are also a limited number of objects where the type conversion is the only public way to set a property to that type without involving a subclass, because the type itself does not have a default constructor. An example is Cursor.

For more information on how type conversion and its use for attribute syntax is supported, see TypeConverters and XAML.

XAML Root Elements and XAML Namespaces

A XAML file must have only one root element, in order to be both a well-formed XML file and a valid XAML file. For typical WPF scenarios, you use a root element that has a prominent meaning in the WPF application model (for example, Window or Page for a page, ResourceDictionary for an external dictionary, or Application for the application definition). The following example shows the root element of a typical XAML file for a WPF page, with the root element of Page.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

	...

</Page>

The root element also contains the attributes xmlns and xmlns:x. These attributes indicate to a XAML processor which XAML namespaces contain the type definitions for backing types that the markup will reference as elements. The xmlns attribute specifically indicates the default XAML namespace. Within the default XAML namespace, object elements in the markup can be specified without a prefix. For most WPF application scenarios, and for almost all of the examples given in the WPF sections of the SDK, the default XAML namespace is mapped to the WPF namespace http://schemas.microsoft.com/winfx/2006/xaml/presentation. The xmlns:x attribute indicates an additional XAML namespace, which maps the XAML language namespace http://schemas.microsoft.com/winfx/2006/xaml.

This usage of xmlns to define a scope for usage and mapping of a namescope is consistent with the XML 1.0 specification. XAML namescopes are different from XML namescopes only in that a XAML namescope also implies something about how the namescope's elements are backed by types when it comes to type resolution and parsing the XAML.

Note that the xmlns attributes are only strictly necessary on the root element of each XAML file. xmlns definitions will apply to all descendant elements of the root element (this behavior is again consistent with the XML 1.0 specification for xmlns.) xmlns attributes are also permitted on other elements underneath the root, and would apply to any descendant elements of the defining element. However, frequent definition or redefinition of XAML namespaces can result in a XAML markup style that is difficult to read.

The WPF implementation of its XAML processor includes an infrastructure that has awareness of the WPF core assemblies. The WPF core assemblies are known to contain the types that support the WPF mappings to the default XAML namespace. This is enabled through configuration that is part of your project build file and the WPF build and project systems. Therefore, declaring the default XAML namespace as the default xmlns is all that is necessary in order to reference XAML elements that come from WPF assemblies.

The x: Prefix

In the previous root element example, the prefix x: was used to map the XAML namespace http://schemas.microsoft.com/winfx/2006/xaml, which is the dedicated XAML namespace that supports XAML language constructs. This x: prefix is used for mapping this XAML namespace in the templates for projects, in examples, and in documentation throughout this SDK. The XAML namespace for the XAML language contain several programming constructs that you will use very frequently in your XAML. The following is a listing of the most common x: prefix programming constructs you will use:

  • x:Key: Sets a unique key for each resource in a ResourceDictionary (or similar dictionary concepts in other frameworks). x:Key will probably account for 90% of the x: usages you will see in a typical WPF application's markup.

  • x:Class: Specifies the CLR namespace and class name for the class that provides code-behind for a XAML page. You must have such a class to support code-behind per the WPF programming model, and therefore you almost always see x: mapped, even if there are no resources.

  • x:Name: Specifies a run-time object name for the instance that exists in run-time code after an object element is processed. In general, you will frequently use a WPF-defined equivalent property for x:Name. Such properties map specifically to a CLR backing property and are thus more convenient for application programming, where you frequently use run time code to find the named elements from initialized XAML. The most common such property is FrameworkElement.Name. You might still use x:Name when the equivalent WPF framework-level Nameproperty is not supported in a particular type. This occurs in certain animation scenarios.

  • x:Static: Enables a reference that returns a static value that is not otherwise a XAML-compatible property.

  • x:Type: Constructs a Type reference based on a type name. This is used to specify attributes that take Type, such as Style.TargetType, although frequently the property has native string-to-Type conversion in such a way that the x:Type markup extension usage is optional.

There are additional programming constructs in the x: prefix/XAML namespace, which are not as common. For details, see XAML Namespace (x:) Language Features.

Custom Prefixes and Custom Types in XAML

For your own custom assemblies, or for assemblies outside the WPF core of PresentationCore, PresentationFramework and WindowsBase, you can specify the assembly as part of a custom xmlns mapping. You can then reference types from that assembly in your XAML, so long as that type is correctly implemented to support the XAML usages you are attempting.

The following is a very basic example of how custom prefixes work in XAML markup. The prefix custom is defined in the root element tag, and mapped to a specific assembly that is packaged and available with the application. This assembly contains a type NumericUpDown, which is implemented to support general XAML usage as well as using a class inheritance that permits its insertion at this particular point in a WPF XAML content model. An instance of this NumericUpDown control is declared as an object element, using the prefix so that a XAML parser knows which XAML namespace contains the type, and therefore where the backing assembly is that contains the type definition.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:custom="clr-namespace:NumericUpDownCustomControl;assembly=CustomLibrary"
    >
  <StackPanel Name="LayoutRoot">
    <custom:NumericUpDown Name="numericCtrl1" Width="100" Height="60"/>
...
  </StackPanel>
</Page>

For more information about custom types in XAML, see XAML and Custom Classes for WPF.

For more information about how XML namespaces and the namespaces of the backing code in assemblies are related, see XAML Namespaces and Namespace Mapping for WPF XAML.

Events and XAML Code-Behind

Most WPF applications consist of both XAML markup and code-behind. Within a project, the XAML is written as a .xaml file, and a CLR language such as Microsoft Visual Basic or C# is used to write a code-behind file. When a XAML file is markup compiled as part of the WPF programming and application models, the location of the XAML code-behind file for a XAML file is identified by specifying a namespace and class as the x:Class attribute of the root element of the XAML.

In the examples so far, you have seen several buttons, but none of these buttons had any logical behavior associated with them yet. The primary application-level mechanism for adding a behavior for an object element is to use an existing event of the element class, and to write a specific handler for that event that is invoked when that event is raised at run time. The event name and the name of the handler to use are specified in the markup, whereas the code that implements your handler is defined in the code-behind.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="MyNamespace.MyPageCode"> <Button Click="ClickHandler" >Click Me!</Button> </Page>

namespace MyNamespace
{
  public partial class MyPageCode
  {
    void ClickHandler(object sender, RoutedEventArgs e)
    {
      Button b = e.Source as Button;
      b.Background = Brushes.Red;
    }
  }

}

Notice that the code-behind file uses the CLR namespace ExampleNamespace and declares ExamplePage as a partial class within that namespace. This parallels the x:Class attribute value of ExampleNamespace.ExamplePage that was provided in the markup root. The WPF markup compiler will create a partial class for any compiled XAML file, by deriving a class from the root element type. When you provide code-behind that also defines the same partial class, the resulting code is combined within the same namespace and class of the compiled application.

For more information about requirements for code-behind programming in WPF, see the "Code-behind, Event Handler, and Partial Class Requirements" section of Code-Behind and XAML in WPF.

If you do not want to create a separate code-behind file, you can also inline your code in a XAML file. However, inline code is a less versatile technique that has substantial limitations. For details, see Code-Behind and XAML in WPF.

Routed Events

A particular event feature that is fundamental to WPF is a routed event. Routed events enable an element to handle an event that was raised by a different element, as long as the elements are connected through a tree relationship. When specifying event handling with a XAML attribute, the routed event can be listened for and handled on any element, including elements that do not list that particular event in the class members table. This is accomplished by qualifying the event name attribute with the owning class name. For instance, the parent StackPanel in the ongoingStackPanel / Button example could register a handler for the child element button's Click event by specifying the attribute Button.Click on the StackPanel object element, with your handler name as the attribute value. For more information about how routed events work, see Routed Events Overview.

XAML Named Elements

By default, the object instance that is created in an object graph by processing a XAML object element does not possess a unique identifier or object reference. In contrast, if you call a constructor in code, you almost always use the constructor result to set a variable to the constructed instance, so that you can reference the instance later in your code. In order to provide standardized access to objects that were created through a markup definition, XAML defines the x:Name attribute. You can set the value of the x:Name attribute on any object element. In your code-behind, the identifier you choose is equivalent to an instance variable that refers to the constructed instance. In all respects, named elements function as if they were object instances (the name references that instance), and your code-behind can reference the named elements to handle run-time interactions within the application. This connection between instances and variables is accomplished by the WPF XAML markup compiler, and more specifically involve features and patterns such as InitializeComponent that will not be discussed in detail in this topic.

WPF framework-level XAML elements inherit a Name property, which is equivalent to the XAML defined x:Name attribute. Certain other classes also provide property-level equivalents for x:Name, which is also generally defined as a Name property. Generally speaking, if you cannot find a Nameproperty in the members table for your chosen element/type, use x:Name instead. The x:Name values will provide an identifier to a XAML element that can be used at run time, either by specific subsystems or by utility methods such as FindName.

The following example sets Name on a StackPanel element. Then, a handler on a Button within that StackPanel references the StackPanel through its instance reference buttonContainer as set by Name.

<StackPanel Name="buttonContainer">

  ...

  <Button Click="RemoveThis">Click to remove this button</Button>

</StackPanel>

void RemoveThis(object sender, RoutedEventArgs e)
{
    FrameworkElement fe = e.Source as FrameworkElement;
    if (buttonContainer.Children.Contains(fe))
    {
        buttonContainer.Children.Remove(fe);
    }

}

Just like a variable, the XAML name for an instance is governed by a concept of scope, so that names can be enforced to be unique within a certain scope that is predictable. The primary markup that defines a page denotes one unique XAML namescope, with the XAML namescope boundary being the root element of that page. However, other markup sources can interact with a page at run time, such as styles or templates within styles, and such markup sources often have their own XAML namescopes that do not necessarily connect with the XAML namescope of the page. For more information on x:Name and XAML namescopes, see Namex:Name Directive, or WPF XAML Namescopes.

Attached Properties and Attached Events

XAML specifies a language feature that enables certain properties or events to be specified on any element, regardless of whether the property or event exists in the type's definitions for the element it is being set on. The properties version of this feature is called an attached property, the events version is called an attached event. Conceptually, you can think of attached properties and attached events as global members that can be set on any XAML element/object instance. However, that element/class or a larger infrastructure must support a backing property store for the attached values.

Attached properties in XAML are typically used through attribute syntax. In attribute syntax, you specify an attached property in the formownerType.propertyName.

Superficially, this resembles a property element usage, but in this case the ownerType you specify is always a different type than the object element where the attached property is being set. ownerType is the type that provides the accessor methods that are required by a XAML processor in order to get or set the attached property value.

The most common scenario for attached properties is to enable child elements to report a property value to their parent element.

The following example illustrates the DockPanel.Dock attached property. The DockPanel class defines the accessors for DockPanel.Dock and therefore owns the attached property. The DockPanel class also includes logic that iterates its child elements and specifically checks each element for a set value of DockPanel.Dock. If a value is found, that value is used during layout to position the child elements. Use of the DockPanel.Dock attached property and this positioning capability is in fact the motivating scenario for the DockPanel class.

<DockPanel>
  <Button DockPanel.Dock="Left" Width="100" Height="20">I am on the left</Button>
  <Button DockPanel.Dock="Right" Width="100" Height="20">I am on the right</Button>
</DockPanel>

In WPF, most or all the attached properties are also implemented as dependency properties. For details, see Attached Properties Overview.

Attached events use a similar ownerType.eventName form of attribute syntax. Just like the non-attached events, the attribute value for an attached event in XAML specifies the name of the handler method that is invoked when the event is handled on the element. Attached event usages in WPF XAML are less common. For more information, see Attached Events Overview.

Base Types and XAML

Underlying WPF XAML and its XAML namespace is a collection of types that correspond to CLR objects in addition to markup elements for XAML. However, not all classes can be mapped to elements. Abstract classes, such as ButtonBase, and certain nonabstract base classes are used for inheritance in the CLR objects model. Base classes, including abstract ones, are still important to XAML development because each of the concrete XAML elements inherits members from some base class in its hierarchy. Often these members include properties that can be set as attributes on the element, or events that can be handled. FrameworkElement is the concrete base UI class of WPF at the WPF framework level. When designing UI, you will use various shape, panel, decorator, or control classes, which all derive from FrameworkElement. A related base class, FrameworkContentElement, supports document-oriented elements that work well for a flow layout presentation, using APIs that deliberately mirror the APIs inFrameworkElement. The combination of attributes at the element level and a CLR object model provides you with a set of common properties that are settable on most concrete XAML elements, regardless of the specific XAML element and its underlying type.

XAML Security

XAML is a markup language that directly represents object instantiation and execution. Therefore, elements created in XAML have the same ability to interact with system resources (network access, file system IO, for example) as the equivalent generated code does.

WPF supports the  .NET Framework 4 security framework Code Access Security (CAS). This means that WPF content running in the internet zone has reduced execution permissions. "Loose XAML" (pages of noncompiled XAML interpreted at load time by a XAML viewer) and XAML browser application (XBAP) are usually run in this internet zone and use the same permission set. However, XAML loaded in to a fully trusted application has the same access to the system resources as the hosting application does. For more information, see WPF Partial Trust Security.

Loading XAML from Code

XAML can be used to define all of the UI, but it is sometimes also appropriate to define just a piece of the UI in XAML. This capability could be used to enable partial customization, local storage of information, using XAML to provide a business object, or a variety of possible scenarios. The key to these scenarios is the XamlReader class and its Load method. The input is a XAML file, and the output is an object that represents all of the run-time tree of objects that was created from that markup. You then can insert the object to be a property of another object that already exists in the application. So long as the property is an appropriate property in the content model that has eventual display capabilities and that will notify the execution engine that new content has been added into the application, you can modify a running application's contents very easily by loading in XAML. Note that this capability is generally only available in full-trust applications, because of the obvious security implications of loading files into applications as they run.

What's Next

This topic provides a basic introduction to XAML syntax concepts and terminology as it applies to WPF. For more information about the terms used here, see XAML Syntax In Detail.

If you have not already done this, try the exercises in the tutorial topic Walkthrough: My First WPF Desktop Application. When you create the markup-centric application described by the tutorial, the exercise will help reinforce many of the concepts described in this topic.

WPF uses a particular application model that is based on the Application class. For details, see Application Management Overview.

Building a WPF Application (WPF) gives you more details about how to build XAML inclusive applications from the command line and with Microsoft Visual Studio.

Dependency Properties Overview gives more information about the versatility of properties in WPF, and introduces the concept of dependency properties.



XAML Syntax In Detail


This topic defines the terms that are used to describe the elements of XAML syntax. These terms are used frequently throughout the remainder of this documentation, both for WPF documentation specifically and for the other frameworks that use XAML or the basic XAML concepts enabled by the XAML language support at the System.Xaml level. This topic expands on the basic terminology introduced in the topic XAML Overview (WPF).

The XAML Language Specification

The XAML syntax terminology defined here is also defined or referenced within the XAML language specification. XAML is a language based on XML and follows or expands upon XML structural rules. Some of the terminology is shared from or is based on the terminology commonly used when describing the XML language or the XML document object model.

For more information about the XAML language specification, download [MS-XAML] from the Microsoft Download Center.

XAML and CLR

XAML is a markup language. The common language runtime (CLR), as implied by its name, enables runtime execution. XAML is not by itself one of the common languages that is directly consumed by the CLR runtime. Instead, you can think of XAML as supporting its own type system. The particular XAML parsing system that is used by WPF is built on the CLR and the CLR type system. XAML types are mapped to CLR types to instantiate a run time representation when the XAML for WPF is parsed. For this reason, the remainder of discussion of syntax in this document will include references to the CLR type system, even though the equivalent syntax discussions in the XAML language specification do not. (Per the XAML language specification level, XAML types could be mapped to any other type system, which does not have to be the CLR, but that would require the creation and use of a different XAML parser.)

Members of Types and Class Inheritance

Properties and events as they appear as XAML members of a WPF type are often inherited from base types. For example, consider this example:<Button Background="Blue" .../>. The Background property is not an immediately declared property on the Button class, if you were to look at the class definition, reflection results, or the documentation. Instead, Background is inherited from the base Control class.

The class inheritance behavior of WPF XAML elements is a significant departure from a schema-enforced interpretation of XML markup. Class inheritance can become complex, particularly when intermediate base classes are abstract, or when interfaces are involved. This is one reason that the set of XAML elements and their permissible attributes is difficult to represent accurately and completely using the schema types that are typically used for XML programming, such as DTD or XSD format. Another reason is that extensibility and type-mapping features of the XAML language itself preclude completeness of any fixed representation of the permissible types and members.

Object Element Syntax

Object element syntax is the XAML markup syntax that instantiates a CLR class or structure by declaring an XML element. This syntax resembles the element syntax of other markup languages such as HTML. Object element syntax begins with a left angle bracket (<), followed immediately by the type name of the class or structure being instantiated. Zero or more spaces can follow the type name, and zero or more attributes may also be declared on the object element, with one or more spaces separating each attribute name="value" pair. Finally, one of the following must be true:

  • The element and tag must be closed by a forward slash (/) followed immediately by a right angle bracket (>).

  • The opening tag must be completed by a right angle bracket (>). Other object elements, property elements, or inner text, can follow the opening tag. Exactly what content may be contained here is typically constrained by the object model of the element. The equivalent closing tag for the object element must also exist, in proper nesting and balance with other opening and closing tag pairs.

XAML as implemented by .NET has a set of rules that map object elements into types, attributes into properties or events, and XAML namespaces to CLR namespaces plus assembly. For WPF and the .NET Framework, XAML object elements map to Microsoft .NET types as defined in referenced assemblies, and the attributes map to members of those types. When you reference a CLR type in XAML, you have access to the inherited members of that type as well.

For example, the following example is object element syntax that instantiates a new instance of the Button class, and also specifies a Name attribute and a value for that attribute:

<Button Name="CheckoutButton"/>

The following example is object element syntax that also includes XAML content property syntax. The inner text contained within will be used to set the TextBox XAML content property, Text.

<TextBox>This is a Text Box</TextBox>

Content Models

A class might support a usage as a XAML object element in terms of the syntax, but that element will only function properly in an application or page when it is placed in an expected position of an overall content model or element tree. For example, a MenuItem should typically only be placed as a child of a MenuBase derived class such as Menu. Content models for specific elements are documented as part of the remarks on the class pages for controls and other WPF classes that can be used as XAML elements.

Properties of Object Elements

Properties in XAML are set by a variety of possible syntaxes. Which syntax can be used for a particular property will vary, based on the underlying type system characteristics of the property that you are setting.

By setting values of properties, you add features or characteristics to objects as they exist in the run time object graph. The initial state of the created object from a object element is based on the default constructor behavior. Typically, your application will use something other than a completely default instance of any given object.

Attribute Syntax (Properties)

Attribute syntax is the XAML markup syntax that sets a value for a property by declaring an attribute on an existing object element. The attribute name must match the CLR member name of the property of the class that backs the relevant object element. The attribute name is followed by an assignment operator (=). The attribute value must be a string enclosed within quotes.

System_CAPS_noteNote

You can use alternating quotes to place a literal quotation mark within an attribute. For instance you can use single quotes as a means to declare a string that contains a double quote character within it. Whether you use single or double quotes, you should use a matching pair for opening and closing the attribute value string. There are also escape sequences or other techniques available for working around character restrictions imposed by any particular XAML syntax. See XML Character Entities and XAML.

In order to be set through attribute syntax, a property must be public and must be writeable. The value of the property in the backing type system must be a value type, or must be a reference type that can be instantiated or referenced by a XAML processor when accessing the relevant backing type.

For WPF XAML events, the event that is referenced as the attribute name must be public and have a public delegate.

The property or event must be a member of the class or structure that is instantiated by the containing object element.

Processing of Attribute Values

The string value contained within the opening and closing quotation marks is processed by a XAML processor. For properties, the default processing behavior is determined by the type of the underlying CLR property.

The attribute value is filled by one of the following, using this processing order:

  1. If the XAML processor encounters a curly brace, or an object element that derives from MarkupExtension, then the referenced markup extension is evaluated first rather than processing the value as a string, and the object returned by the markup extension is used as the value. In many cases the object returned by a markup extension will be a reference to an existing object, or an expression that defers evaluation until run time, and is not a newly instantiated object.

  2. If the property is declared with an attributed TypeConverter, or the value type of that property is declared with an attributed TypeConverter, the string value of the attribute is submitted to the type converter as a conversion input, and the converter will return a new object instance.

  3. If there is no TypeConverter, a direct conversion to the property type is attempted. This final level is a direct conversion at the parser-native value between XAML language primitive types, or a check for the names of named constants in an enumeration (the parser then accesses the matching values).

Enumeration Attribute Values

Enumerations in XAML are processed intrinsically by XAML parsers, and the members of an enumeration should be specified by specifying the string name of one of the enumeration's named constants.

For nonflag enumeration values, the native behavior is to process the string of an attribute value and resolve it to one of the enumeration values. You do not specify the enumeration in the format Enumeration.Value, as you do in code. Instead, you specify only Value, andEnumeration is inferred by the type of the property you are setting. If you specify an attribute in the Enumeration.Value form, it will not resolve correctly.

For flagwise enumerations, the behavior is based on the Enum.Parse method. You can specify multiple values for a flagwise enumeration by separating each value with a comma. However, you cannot combine enumeration values that are not flagwise. For instance, you cannot use the comma syntax to attempt to create a Trigger that acts on multiple conditions of a nonflag enumeration:

<!--This will not compile, because Visibility is not a flagwise enumeration.-->
...
<Trigger Property="Visibility" Value="Collapsed,Hidden">
  <Setter ... />
</Trigger>
...

Flagwise enumerations that support attributes that are settable in XAML are rare in WPF. However, one such enumeration is StyleSimulations. You could, for instance, use the comma-delimited flagwise attribute syntax to modify the example provided in the Remarks for the Glyphs class;StyleSimulations = "BoldSimulation" could become StyleSimulations = "BoldSimulation,ItalicSimulation".KeyBinding.Modifiers is another property where more than one enumeration value can be specified. However, this property happens to be a special case, because the ModifierKeys enumeration supports its own type converter. The type converter for modifiers uses a plus sign (+) as a delimiter rather than a comma (,). This conversion supports the more traditional syntax to represent key combinations in Microsoft Windows programming, such as "Ctrl+Alt".

Properties and Event Member Name References

When specifying an attribute, you can reference any property or event that exists as a member of the CLR type you instantiated for the containing object element.

Or, you can reference an attached property or attached event, independent of the containing object element. (Attached properties are discussed in an upcoming section.)

You can also name any event from any object that is accessible through the default namespace by using a typeName.event partially qualified name; this syntax supports attaching handlers for routed events where the handler is intended to handle events routing from child elements, but the parent element does not also have that event in its members table. This syntax resembles an attached event syntax, but the event here is not a true attached event. Instead, you are referencing an event with a qualified name. For more information, see Routed Events Overview.

For some scenarios, property names are sometimes provided as the value of an attribute, rather than the attribute name. That property name can also include qualifiers, such as the property specified in the form ownerType.dependencyPropertyName. This scenario is common when writing styles or templates in XAML. The processing rules for property names provided as an attribute value are different, and are governed by the type of the property being set or by the behaviors of particular WPF subsystems. For details, see Styling and Templating.

Another usage for property names is when an attribute value describes a property-property relationship. This feature is used for data binding and for storyboard targets, and is enabled by the PropertyPath class and its type converter. For a more complete description of the lookup semantics, see PropertyPath XAML Syntax.

Property Element Syntax

Property element syntax is a syntax that diverges somewhat from the basic XML syntax rules for elements. In XML, the value of an attribute is a de facto string, with the only possible variation being which string encoding format is being used. In XAML, you can assign other object elements to be the value of a property. This capability is enabled by the property element syntax. Instead of the property being specified as an attribute within the element tag, the property is specified using an opening element tag in elementTypeName.propertyName form, the value of the property is specified within, and then the property element is closed.

Specifically, the syntax begins with a left angle bracket (<), followed immediately by the type name of the class or structure that the property element syntax is contained within. This is followed immediately by a single dot (.), then by the name of a property, then by a right angle bracket (>). As with attribute syntax, that property must exist within the declared public members of the specified type. The value to be assigned to the property is contained within the property element. Typically, the value is given as one or more object elements, because specifying objects as values is the scenario that property element syntax is intended to address. Finally, an equivalent closing tag specifying the same elementTypeName.propertyNamecombination must be provided, in proper nesting and balance with other element tags.

For example, the following is property element syntax for the ContextMenu property of a Button.

<Button>
  <Button.ContextMenu>
    <ContextMenu>
      <MenuItem Header="1">First item</MenuItem>
      <MenuItem Header="2">Second item</MenuItem>
    </ContextMenu>
  </Button.ContextMenu>
  Right-click me!</Button>

The value within a property element can also be given as inner text, in cases where the property type being specified is a primitive value type, such asString, or an enumeration where a name is specified. These two usages are somewhat uncommon, because each of these cases could also use a simpler attribute syntax. One scenario for filling a property element with a string is for properties that are not the XAML content property but still are used for representation of UI text, and particular whitespace elements such as linefeeds are required to appear in that UI text. Attribute syntax cannot preserve linefeeds, but property element syntax can, so long as significant whitespace preservation is active (for details, see Whitespace Processing in XAML). Another scenario is so that x:Uid Directive can be applied to the property element and thus mark the value within as a value that should be localized in the WPF output BAML or by other techniques.

A property element is not represented in the WPF logical tree. A property element is just a particular syntax for setting a property, and is not an element that has an instance or object backing it. (For details on the logical tree concept, see Trees in WPF.)

For properties where both attribute and property element syntax are supported, the two syntaxes generally have the same result, although subtleties such as whitespace handling can vary slightly between syntaxes.

Collection Syntax

The XAML specification requires XAML processor implementations to identify properties where the value type is a collection. The general XAML processor implementation in .NET is based on managed code and the CLR, and it identifies collection types through one of the following:

If the type of a property is a collection, then the inferred collection type does not need to be specified in the markup as an object element. Instead, the elements that are intended to become the items in the collection are specified as one or more child elements of the property element. Each such item is evaluated to an object during loading and added to the collection by calling the Add method of the implied collection. For example, theTriggers property of Style takes the specialized collection type TriggerCollection, which implements IList. It is not necessary to instantiate aTriggerCollection object element in the markup. Instead, you specify one or more Trigger items as elements within the Style.Triggers property element, where Trigger (or a derived class) is the type expected as the item type for the strongly typed and implicit TriggerCollection.

<Style x:Key="SpecialButton" TargetType="{x:Type Button}">
  <Style.Triggers>
    <Trigger Property="Button.IsMouseOver" Value="true">
      <Setter Property = "Background" Value="Red"/>
    </Trigger>
    <Trigger Property="Button.IsPressed" Value="true">
      <Setter Property = "Foreground" Value="Green"/>
    </Trigger>
  </Style.Triggers>
</Style>

A property may be both a collection type and the XAML content property for that type and derived types, which is discussed in the next section of this topic.

An implicit collection element creates a member in the logical tree representation, even though it does not appear in the markup as an element. Usually the constructor of the parent type performs the instantiation for the collection that is one of its properties, and the initially empty collection becomes part of the object tree.

System_CAPS_noteNote

The generic list and dictionary interfaces (IList<T> and IDictionary<TKey, TValue>) are not supported for collection detection. However, you can use the List<T> class as a base class, because it implements IList directly, or Dictionary<TKey, TValue> as a base class, because it implementsIDictionary directly.

In the .NET Reference pages for collection types, this syntax with the deliberate omission of the object element for a collection is occasionally noted in the XAML syntax sections as Implicit Collection Syntax.

With the exception of the root element, every object element in a XAML file that is nested as a child element of another element is really an element that is one or both of the following cases: a member of an implicit collection property of its parent element, or an element that specifies the value of the XAML content property for the parent element (XAML content properties will be discussed in an upcoming section). In other words, the relationship of parent elements and child elements in a markup page is really a single object at the root, and every object element beneath the root is either a single instance that provides a property value of the parent, or one of the items within a collection that is also a collection-type property value of the parent. This single-root concept is common with XML, and is frequently reinforced in the behavior of APIs that load XAML such as Load.

The following example is a syntax with the object element for a collection (GradientStopCollection) specified explicitly.

<LinearGradientBrush>
  <LinearGradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Offset="0.0" Color="Red" />
      <GradientStop Offset="1.0" Color="Blue" />
    </GradientStopCollection>
  </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

Note that it is not always possible to explicitly declare the collection. For instance, attempting to declare TriggerCollection explicitly in the previously shown Triggers example would fail. Explicitly declaring the collection requires that the collection class must support a default constructor, andTriggerCollection does not have a default constructor.

XAML Content Properties

XAML content syntax is a syntax that is only enabled on classes that specify the ContentPropertyAttribute as part of their class declaration. TheContentPropertyAttribute references the property name that is the content property for that type of element (including derived classes). When processed by a XAML processor, any child elements or inner text that are found between the opening and closing tags of the object element will be assigned to be the value of the XAML content property for that object. You are permitted to specify explicit property elements for the content property, but this usage is not generally shown in the XAML syntax sections in the .NET reference. The explicit/verbose technique has occasional value for markup clarity or as a matter of markup style, but usually the intent of a content property is to streamline the markup so that elements that are intuitively related as parent-child can be nested directly. Property element tags for other properties on an element are not assigned as "content" per a strict XAML language definition; they are processed previously in the XAML parser's processing order and are not considered to be "content".

XAML Content Property Values Must Be Contiguous

The value of a XAML content property must be given either entirely before or entirely after any other property elements on that object element. This is true whether the value of a XAML content property is specified as a string, or as one or more objects. For example, the following markup does not parse:

<Button>I am a 
  <Button.Background>Blue</Button.Background>
  blue button</Button>

This is illegal essentially because if this syntax were made explicit by using property element syntax for the content property, then the content property would be set twice:

<Button>
  <Button.Content>I am a </Button.Content>
  <Button.Background>Blue</Button.Background>
  <Button.Content> blue button</Button.Content>
</Button>

A similarly illegal example is if the content property is a collection, and child elements are interspersed with property elements:

<StackPanel>
  <Button>This example</Button>
  <StackPanel.Resources>
    <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
  </StackPanel.Resources>
  <Button>... is illegal XAML</Button>
</StackPanel>

Content Properties and Collection Syntax Combined

In order to accept more than a single object element as content, the type of the content property must specifically be a collection type. Similar to property element syntax for collection types, a XAML processor must identify types that are collection types. If an element has a XAML content property and the type of the XAML content property is a collection, then the implied collection type does not need to be specified in the markup as an object element and the XAML content property does not need to be specified as a property element. Therefore the apparent content model in the markup can now have more than one child element assigned as the content. The following is content syntax for a Panel derived class. All Panelderived classes establish the XAML content property to be Children, which requires a value of type UIElementCollection.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <StackPanel>
    <Button>Button 1</Button>
    <Button>Button 2</Button>
    <Button>Button 3</Button>
  </StackPanel>
</Page>

Note that neither the property element for Children nor the element for the UIElementCollection is required in the markup. This is a design feature of XAML so that recursively contained elements that define a UI are more intuitively represented as a tree of nested elements with immediate parent-child element relationships, without intervening property element tags or collection objects. In fact, UIElementCollection cannot be specified explicitly in markup as an object element, by design. Because its only intended use is as an implicit collection, UIElementCollection does not expose a public default constructor and thus cannot be instantiated as an object element.

Mixing Property Elements and Object Elements in an Object with a Content Property

The XAML specification declares that a XAML processor can enforce that object elements that are used to fill the XAML content property within an object element must be contiguous, and must not be mixed. This restriction against mixing property elements and content is enforced by the WPF XAML processors.

You can have a child object element as the first immediate markup within an object element. Then you can introduce property elements. Or, you can specify one or more property elements, then content, then more property elements. But once a property element follows content, you cannot introduce any further content, you can only add property elements.

This content / property element order requirement does not apply to inner text used as content. However, it is still a good markup style to keep inner text contiguous, because significant whitespace will be difficult to detect visually in the markup if property elements are interspersed with inner text.

XAML Namespaces

None of the preceding syntax examples specified a XAML namespace other than the default XAML namespace. In typical WPF applications, the default XAML namespace is specified to be the WPF namespace. You can specify XAML namespaces other than the default XAML namespace and still use similar syntax. But then, anywhere where a class is named that is not accessible within the default XAML namespace, that class name must be preceded with the prefix of the XAML namespace as mapped to the corresponding CLR namespace. For example, <custom:Example/> is object element syntax to instantiate an instance of the Example class, where the CLR namespace containing that class (and possibly the external assembly information that contains backing types) was previously mapped to the custom prefix.

For more information about XAML namespaces, see XAML Namespaces and Namespace Mapping for WPF XAML.

Markup Extensions

XAML defines a markup extension programming entity that enables an escape from the normal XAML processor handling of string attribute values or object elements, and defers the processing to a backing class. The character that identifies a markup extension to a XAML processor when using attribute syntax is the opening curly brace ({), followed by any character other than a closing curly brace (}). The first string following the opening curly brace must reference the class that provides the particular extension behavior, where the reference may omit the substring "Extension" if that substring is part of the true class name. Thereafter, a single space may appear, and then each succeeding character is used as input by the extension implementation, up until the closing curly brace is encountered.

The .NET XAML implementation uses the MarkupExtension abstract class as the basis for all of the markup extensions supported by WPF as well as other frameworks or technologies. The markup extensions that WPF specifically implements are often intended to provide a means to reference other existing objects, or to make deferred references to objects that will be evaluated at run time. For example, a simple WPF data binding is accomplished by specifying the {Binding} markup extension in place of the value that a particular property would ordinarily take. Many of the WPF markup extensions enable an attribute syntax for properties where an attribute syntax would not otherwise be possible. For example, a Style object is a relatively complex type that contains a nested series of objects and properties. Styles in WPF are typically defined as a resource in aResourceDictionary, and then referenced through one of the two WPF markup extensions that request a resource. The markup extension defers the evaluation of the property value to a resource lookup and enables providing the value of the Style property, taking type Style, in attribute syntax as in the following example:

<Button Style="{StaticResource MyStyle}">My button</Button>

Here, StaticResource identifies the StaticResourceExtension class providing the markup extension implementation. The next string MyStyle is used as the input for the non-default StaticResourceExtension constructor, where the parameter as taken from the extension string declares the requestedResourceKeyMyStyle is expected to be the x:Key value of a Style defined as a resource. The StaticResource Markup Extension usage requests that the resource be used to provide the Style property value through static resource lookup logic at load time.

For more information about markup extensions, see Markup Extensions and WPF XAML. For a reference of markup extensions and other XAML programming features enabled in the general .NET XAML implementation, see XAML Namespace (x:) Language Features. For WPF-specific markup extensions, see WPF XAML Extensions.

Attached Properties

Attached properties are a programming concept introduced in XAML whereby properties can be owned and defined by a particular type, but set as attributes or property elements on any element. The primary scenario that attached properties are intended for is to enable child elements in a markup structure to report information to a parent element without requiring an extensively shared object model across all elements. Conversely, attached properties can be used by parent elements to report information to child elements. For more information on the purpose of attached properties and how to create your own attached properties, see Attached Properties Overview.

Attached properties use a syntax that superficially resembles property element syntax, in that you also specify a typeName.propertyNamecombination. There are two important differences:

  • You can use the typeName.propertyName combination even when setting an attached property through attribute syntax. Attached properties are the only case where qualifying the property name is a requirement in an attribute syntax.

  • You can also use property element syntax for attached properties. However, for typical property element syntax, the typeName you specify is the object element that contains the property element. If you are referring to an attached property, then the typeName is the class that defines the attached property, not the containing object element.

Attached Events

Attached events are another programming concept introduced in XAML where events can be defined by a specific type, but handlers may be attached on any object element. In the WOF implementation, often the type that defines an attached event is a static type that defines a service, and sometimes those attached events are exposed by a routed event alias in types that expose the service. Handlers for attached events are specified through attribute syntax. As with attached events, the attribute syntax is expanded for attached events to allow a typeName.eventName usage, wheretypeName is the class that provides Add and Remove event handler accessors for the attached event infrastructure, and eventName is the event name.

Anatomy of a XAML Root Element

The following table shows a typical XAML root element broken down, showing the specific attributes of a root element:

<Page

Opening object element of the root element

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

The default (WPF) XAML namespace

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

The XAML language XAML namespace

x:Class="ExampleNamespace.ExampleCode"

The partial class declaration that connects markup to any code-behind defined for the partial class

>

End of object element for the root. Object is not closed yet because the element contains child elements

Optional and Nonrecommended XAML Usages

The following sections describe XAML usages that are technically supported by XAML processors, but that produce verbosity or other aesthetic issues that interfere with XAML files remaining human-readable when your develop applications that contain XAML sources.

Optional Property Element Usages

Optional property element usages include explicitly writing out element content properties that the XAML processor considers implicit. For example, when you declare the contents of a Menu, you could choose to explicitly declare the Items collection of the Menu as a <Menu.Items>property element tag, and place each MenuItem within <Menu.Items>, rather than using the implicit XAML processor behavior that all child elements of a Menu must be a MenuItem and are placed in the Items collection. Sometimes the optional usages can help to visually clarify the object structure as represented in the markup. Or sometimes an explicit property element usage can avoid markup that is technically functional but visually confusing, such as nested markup extensions within an attribute value.

Full typeName.memberName Qualified Attributes

The typeName.memberName form for an attribute actually works more universally than just the routed event case. But in other situations that form is superfluous and you should avoid it, if only for reasons of markup style and readability. In the following example, each of the three references to the Background attribute are completely equivalent:

<Button Background="Blue">Background</Button>
<Button Button.Background="Blue">Button.Background</Button>
<Button Control.Background="Blue">Control.Background</Button>

Button.Background works because the qualified lookup for that property on Button is successful (Background was inherited from Control) andButton is the class of the object element or a base class. Control.Background works because the Control class actually defines Background andControl is a Button base class.

However, the following typeName.memberName form example does not work and is thus shown commented:

<!--<Button Label.Background="Blue">Does not work</Button> -->

Label is another derived class of Control, and if you had specified Label.Background within a Label object element, this usage would have worked. However, because Label is not the class or base class of Button, the specified XAML processor behavior is to then processLabel.Background as an attached property. Label.Background is not an available attached property, and this usage fails.

baseTypeName.memberName Property Elements

In an analogous way to how the typeName.memberName form works for attribute syntax, a baseTypeName.memberName syntax works for property element syntax. For instance, the following syntax works:

<Button>Control.Background PE
  <Control.Background>
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
      <GradientStop Color="Yellow" Offset="0.0" />
      <GradientStop Color="LimeGreen" Offset="1.0" />
    </LinearGradientBrush>
    </Control.Background>
</Button>

Here, the property element was given as Control.Background even though the property element was contained in Button.

But just like typeName.memberName form for attributes, baseTypeName.memberName is poor style in markup, and you should avoid it.



Code-Behind and XAML in WPF


Code-behind is a term used to describe the code that is joined with markup-defined objects, when a XAML page is markup-compiled. This topic describes requirements for code-behind as well as an alternative inline code mechanism for code in XAML.

This topic contains the following sections:

Prerequisites

This topic assumes that you have read the XAML Overview (WPF) and have some basic knowledge of the CLR and object-oriented programming.

Code-Behind and the XAML Language

The XAML language includes language-level features that make it possible to associate code files with markup files, from the markup file side. Specifically, the XAML language defines the language features x:Class Directivex:Subclass Directive, and x:ClassModifier Directive. Exactly how the code should be produced, and how to integrate markup and code, is not part of what the XAML language specifies. It is left up to frameworks such as WPF to determine how to integrate the code, how to use XAML in the application and programming models, and the build actions or other support that all this requires.

Code-behind, Event Handler, and Partial Class Requirements in WPF

  • The partial class must derive from the type that backs the root element.

  • Note that under the default behavior of the markup compile build actions, you can leave the derivation blank in the partial class definition on the code-behind side. The compiled result will assume the page root's backing type to be the basis for the partial class, even if it not specified. However, relying on this behavior is not a best practice.

  • The event handlers you write in the code behind must be instance methods and cannot be static methods. These methods must be defined by the partial class within the CLR namespace identified by x:Class. You cannot qualify the name of an event handler to instruct a XAML processor to look for an event handler for event wiring in a different class scope.

  • The handler must match the delegate for the appropriate event in the backing type system.

  • For the Microsoft Visual Basic language specifically, you can use the language-specific Handles keyword to associate handlers with instances and events in the handler declaration, instead of attaching handlers with attributes in XAML. However, this technique does have some limitations because the Handles keyword cannot support all of the specific features of the WPF event system, such as certain routed event scenarios or attached events. For details, see Visual Basic and WPF Event Handling.

x:Code

x:Code is a directive element defined in XAML. An x:Code directive element can contain inline programming code. The code that is defined inline can interact with the XAML on the same page. The following example illustrates inline C# code. Notice that the code is inside the x:Code element and that the code must be surrounded by <CDATA[...]]> to escape the contents for XML, so that a XAML processor (interpreting either the XAML schema or the WPF schema) will not try to interpret the contents literally as XML.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="MyNamespace.MyCanvasCodeInline"
>
  <Button Name="button1" Click="Clicked">Click Me!</Button>
  <x:Code><![CDATA[
    void Clicked(object sender, RoutedEventArgs e)
    {
        button1.Content = "Hello World";
    }
  ]]></x:Code>
</Page>

Inline Code Limitations

You should consider avoiding or limiting the use of inline code. In terms of architecture and coding philosophy, maintaining a separation between markup and code-behind keeps the designer and developer roles much more distinct. On a more technical level, the code that you write for inline code can be awkward to write, because you are always writing into the XAML generated partial class, and can only use the default XML namespace mappings. Because you cannot add using statements, you must fully qualify many of the API calls that you make. The default WPF mappings include most but not all CLR namespaces that are present in the WPF assemblies; you will have to fully qualify calls to types and members contained within the other CLR namespaces. You also cannot define anything beyond the partial class in the inline code, and all user code entities you reference must exist as a member or variable within the generated partial class. Other language specific programming features, such as macros or #ifdef against global variables or build variables, are also not available. For more information, see x:Code Intrinsic XAML Type.



XAML and Custom Classes for WPF


XAML as implemented in common language runtime (CLR) frameworks supports the ability to define a custom class or structure in any common language runtime (CLR) language, and then access that class using XAML markup. You can use a mixture of Windows Presentation Foundation (WPF)-defined types and your custom types within the same markup file, typically by mapping the custom types to a XAML namespace prefix. This topic discusses the requirements that a custom class must satisfy to be usable as a XAML element.

Custom Classes in Applications or Assemblies

Custom classes that are used in XAML can be defined in two distinct ways: within the code-behind or other code that produces the primary Windows Presentation Foundation (WPF) application, or as a class in a separate assembly, such as an executable or DLL used as a class library. Each of these approaches has particular advantages and disadvantages.

  • The advantage of creating a class library is that any such custom classes can be shared across many different possible applications. A separate library also makes versioning issues of applications easier to control, and simplifies creating a class where the intended class usage is as a root element on a XAML page.

  • The advantage of defining the custom classes in the application is that this technique is relatively lightweight and minimizes the deployment and testing issues encountered when you introduce separate assemblies beyond the main application executable.

  • Whether defined in the same or different assembly, custom classes need to be mapped between CLR namespace and XML namespace in order to be used in XAML as elements. See XAML Namespaces and Namespace Mapping for WPF XAML.

Requirements for a Custom Class as a XAML Element

In order to be able to be instantiated as an object element, your class must meet the following requirements:

  • Your custom class must be public and support a default (parameterless) public constructor. (See following section for notes regarding structures.)

  • Your custom class must not be a nested class. Nested classes and the "dot" in their general CLR usage syntax interfere with other WPF and/or XAML features such as attached properties.

In addition to enabling object element syntax, your object definition also enables property element syntax for any other public properties that take that object as the value type. This is because the object can now be instantiated as an object element and can fill the property element value of such a property.

Structures

Structures that you define as custom types are always able to be constructed in XAML in WPF .This is because the CLR compilers implicitly create a default constructor for a structure that initializes all property values to their defaults. In some cases, the default construction behavior and/or object element usage for a structure is not desirable. This might be because the structure is intended to fill values and function conceptually as a union, where the values contained might have mutually exclusive interpretations and thus none of its properties are settable. A WPF example of such a structure is GridLength. Generally, such structures should implement a type converter such that the values can be expressed in attribute form, using string conventions that create the different interpretations or modes of the structure's values. The structure should also expose similar behavior for code construction through a non-default constructor.

Requirements for Properties of a Custom Class as XAML Attributes

Properties must reference a by-value type (such as a primitive), or use a class for type that has either a default constructor or a dedicated type converter that a XAML processor can access. In the CLR XAML implementation, XAML processors either find such converters through native support for language primitives, or through application of TypeConverterAttribute to a type or member in backing type definitions

Alternatively, the property may reference an abstract class type, or an interface. For abstract classes or interfaces, the expectation for XAML parsing is that the property value must be filled with practical class instances that implement the interface, or instances of types that derive from the abstract class.

Properties can be declared on an abstract class, but can only be set on practical classes that derive from the abstract class. This is because creating the object element for the class at all requires a public default constructor on the class.

TypeConverter Enabled Attribute Syntax

If you provide a dedicated, attributed type converter at the class level, the applied type conversion enables attribute syntax for any property that needs to instantiate that type. A type converter does not enable object element usage of the type; only the presence of a default constructor for that type enables object element usage. Therefore, properties that are type-converter enabled are generally speaking not usable in property syntax, unless the type itself also supports object element syntax. The exception to this is that you can specify a property element syntax, but have the property element contain a string. That usage is really essentially equivalent to an attribute syntax usage, and such a usage is not common unless there is a need for more robust whitespace handling of the attribute value. For example, the following is a property element usage that takes a string, and the attribute usage equivalent:

<Button>Hallo!
  <Button.Language>
    de-DE
  </Button.Language>
</Button>
<Button Language="de-DE">Hallo!</Button>

Examples of properties where attribute syntax is allowed but property element syntax that contains an object element is disallowed through XAML are various properties that take the Cursor type. The Cursor class has a dedicated type converter CursorConverter, but does not expose a default constructor, so the Cursor property can only be set through attribute syntax even though the actual Cursor type is a reference type.

Per-Property Type Converters

Alternatively, the property itself may declare a type converter at the property level. This enables a "mini language" that instantiates objects of the type of the property inline, by processing incoming string values of the attribute as input for a ConvertFrom operation based on the appropriate type. Typically this is done to provide a convenience accessor, and not as the sole means to enable setting a property in XAML. However, it is also possible to use type converters for attributes where you want to use existing CLR types that do not supply either a default constructor or an attributed type converter. Examples from the WPF API are certain properties that take the CultureInfo type. In this case, WPF used the existing Microsoft .NET Framework CultureInfo type to better address compatibility and migration scenarios that were used in earlier versions of frameworks, but the CultureInfo type did not support the necessary constructors or type-level type conversion to be usable as a XAML property value directly.

Whenever you expose a property that has a XAML usage, particularly if you are a control author, you should strongly consider backing that property with a dependency property. This is particularly true if you use the existing Windows Presentation Foundation (WPF) implementation of the XAML processor, because you can improve performance by using DependencyProperty backing. A dependency property will expose property system features for your property that users will come to expect for a XAML accessible property. This includes features such as animation, data binding, and style support. For more information, see Custom Dependency Properties and XAML Loading and Dependency Properties.

Writing and Attributing a Type Converter

You occasionally will need to write a custom TypeConverter derived class to provide type conversion for your property type. For instructions on how to derive from and create a type converter that can support XAML usages, and how to apply the TypeConverterAttribute, see TypeConverters and XAML.

Requirements for XAML Event Handler Attribute Syntax on Events of a Custom Class

To be usable as a CLR event, the event must be exposed as a public event on a class that supports a default constructor, or on an abstract class where the event can be accessed on derived classes. In order to be used conveniently as a routed event, your CLR event should implement explicit add and remove methods, which add and remove handlers for the CLR event signature and forward those handlers to the AddHandler andRemoveHandler methods. These methods add or remove the handlers to the routed event handler store on the instance that the event is attached to.

System_CAPS_noteNote

It is possible to register handlers directly for routed events using AddHandler, and to deliberately not define a CLR event that exposes the routed event. This is not generally recommended because the event will not enable XAML attribute syntax for attaching handlers, and your resulting class will offer a less transparent XAML view of that type's capabilities.

Writing Collection Properties

Properties that take a collection type have a XAML syntax that enables you to specify objects that are added to the collection. This syntax has two notable features.

  • The object that is the collection object does not need to be specified in object element syntax. The presence of that collection type is implicit whenever you specify a property in XAML that takes a collection type.

  • Child elements of the collection property in markup are processed to become members of the collection. Ordinarily, the code access to the members of a collection is performed through list/dictionary methods such as Add, or through an indexer. But XAML syntax does not support methods or indexers (exception: XAML 2009 can support methods, but using XAML 2009 restricts the possible WPF usages; see XAML 2009 Language Features). Collections are obviously a very common requirement for building a tree of elements, and you need some way to populate these collections in declarative XAML. Therefore, child elements of a collection property are processed by adding them to the collection that is the collection property type value.

The .NET Framework XAML Services implementation and thus the WPF XAML processor uses the following definition for what constitutes a collection property. The property type of the property must implement one of the following:

Each of these types in CLR has an Add method, which is used by the XAML processor to add items to the underlying collection when creating the object graph.

System_CAPS_noteNote

The generic List and Dictionary interfaces (IList<T> and IDictionary<TKey, TValue>) are not supported for collection detection by the WPF XAML processor. However, you can use the List<T> class as a base class, because it implements IList directly, or Dictionary<TKey, TValue> as a base class, because it implements IDictionary directly.

When you declare a property that takes a collection, be cautious about how that property value is initialized in new instances of the type. If you are not implementing the property as a dependency property, then having the property use a backing field that calls the collection type constructor is adequate. If your property is a dependency property, then you may need to initialize the collection property as part of the default type constructor. This is because a dependency property takes its default value from metadata, and you typically do not want the initial value of a collection property to be a static, shared collection. There should be a collection instance per each containing type instance. For more information, see Custom Dependency Properties.

You can implement a custom collection type for your collection property. Because of implicit collection property treatment, the custom collection type does not need to provide a default constructor in order to be used in XAML implicitly. However, you can optionally provide a default constructor for the collection type. This can be a worthwhile practice. Unless you do provide a default constructor, you cannot explicitly declare the collection as an object element. Some markup authors might prefer to see the explicit collection as a matter of markup style. Also, a default constructor can simplify the initialization requirements when you create new objects that use your collection type as a property value.

Declaring XAML Content Properties

The XAML language defines the concept of a XAML content property. Each class that is usable in object syntax can have exactly one XAML content property. To declare a property to be the XAML content property for your class, apply the ContentPropertyAttribute as part of the class definition. Specify the name of the intended XAML content property as the Name in the attribute. The property is specified as a string by name, not as a reflection construct such asPropertyInfo.

You can specify a collection property to be the XAML content property. This results in a usage for that property whereby the object element can have one or more child elements, without any intervening collection object elements or property element tags. These elements are then treated as the value for the XAML content property and added to the backing collection instance.

Some existing XAML content properties use the property type of Object. This enables a XAML content property that can take primitive values such as a String as well as taking a single reference object value. If you follow this model, your type is responsible for type determination as well as the handling of possible types. The typical reason for an Object content type is to support both a simple means of adding object content as a string (which receives a default presentation treatment), or an advanced means of adding object content that specifies a non-default presentation or additional data.

Serializing XAML

For certain scenarios, such as if you are a control author, you may also want to assure that any object representation that can be instantiated in XAML can also be serialized back to equivalent XAML markup. Serialization requirements are not described in this topic. See Control Authoring Overview and Element Tree and Serialization.



Markup Extensions and WPF XAML


This topic introduces the concept of markup extensions for XAML, including their syntax rules, purpose, and the class object model that underlies them. Markup extensions are a general feature of the XAML language and of the .NET implementation of XAML services. This topic specifically details markup extensions for use in WPF XAML.

XAML Processors and Markup Extensions

Generally speaking, a XAML parser can either interpret an attribute value as a literal string that can be converted to a primitive, or convert it to an object by some means. One such means is by referencing a type converter; this is documented in the topic TypeConverters and XAML. However, there are scenarios where different behavior is required. For example, a XAML processor can be instructed that a value of an attribute should not result in a new object in the object graph. Instead, the attribute should result in an object graph that makes a reference to an already constructed object in another part of the graph, or a static object. Another scenario is that a XAML processor can be instructed to use a syntax that provides non-default arguments to the constructor of an object. These are the types of scenarios where a markup extension can provide the solution.

Basic Markup Extension Syntax

A markup extension can be implemented to provide values for properties in an attribute usage, properties in a property element usage, or both.

When used to provide an attribute value, the syntax that distinguishes a markup extension sequence to a XAML processor is the presence of the opening and closing curly braces ({ and }). The type of markup extension is then identified by the string token immediately following the opening curly brace.

When used in property element syntax, a markup extension is visually the same as any other element used to provide a property element value: a XAML element declaration that references the markup extension class as an element, enclosed within angle brackets (<>).

XAML-Defined Markup Extensions

Several markup extensions exist that are not specific to the WPF implementation of XAML, but are instead implementations of intrinsics or features of XAML as a language. These markup extensions are implemented in the System.Xaml assembly as part of the general .NET Framework XAML services, and are within the XAML language XAML namespace. In terms of common markup usage, these markup extensions are typically identifiable by the x: prefix in the usage. The MarkupExtension base class (also defined in System.Xaml) provides the pattern that all markup extensions should use in order to be supported in XAML readers and XAML writers, including in WPF XAML.

  • x:Type supplies the Type object for the named type. This facility is used most frequently in styles and templates. For details, see x:Type Markup Extension.

  • x:Static produces static values. The values come from value-type code entities that are not directly the type of a target property's value, but can be evaluated to that type. For details, see x:Static Markup Extension.

  • x:Null specifies null as a value for a property and can be used either for attributes or property element values. For details, see x:Null Markup Extension.

  • x:Array provides support for creation of general arrays in XAML syntax, for cases where the collection support provided by WPF base elements and control models is deliberately not used. For details, see x:Array Markup Extension.

System_CAPS_noteNote

The x: prefix is used for the typical XAML namespace mapping of the XAML language intrinsics, in the root element of a XAML file or production. For example, the Visual Studio templates for WPF applications initiate a XAML file using this x: mapping. You could choose a different prefix token in your own XAML namespace mapping, but this documentation will assume the default x: mapping as a means of identifying those entities that are a defined part of the XAML namespace for the XAML language, as opposed to the WPF default namespace or other XAML namespaces not related to a specific framework.

WPF-Specific Markup Extensions

The most common markup extensions used in WPF programming are those that support resource references (StaticResource andDynamicResource), and those that support data binding (Binding).

  • StaticResource provides a value for a property by substituting the value of an already defined resource. A StaticResource evaluation is ultimately made at XAML load time and does not have access to the object graph at run time. For details, see StaticResource Markup Extension.

  • DynamicResource provides a value for a property by deferring that value to be a run-time reference to a resource. A dynamic resource reference forces a new lookup each time that such a resource is accessed and has access to the object graph at run time. In order to get this access, DynamicResource concept is supported by dependency properties in the WPF property system, and evaluated expressions. Therefore you can only use DynamicResource for a dependency property target. For details, see DynamicResource Markup Extension.

  • Binding provides a data bound value for a property, using the data context that applies to the parent object at run time. This markup extension is relatively complex, because it enables a substantial inline syntax for specifying a data binding. For details, see Binding Markup Extension.

  • RelativeSource provides source information for a Binding that can navigate several possible relationships in the run-time object tree. This provides specialized sourcing for bindings that are created in multi-use templates or created in code without full knowledge of the surrounding object tree. For details, see RelativeSource MarkupExtension.

  • TemplateBinding enables a control template to use values for templated properties that come from object-model-defined properties of the class that will use the template. In other words, the property within the template definition can access a context that only exists once the template is applied. For details, see TemplateBinding Markup Extension. For more information on the practical use of TemplateBinding, seeStyling with ControlTemplates Sample.

  • ColorConvertedBitmap supports a relatively advanced imaging scenario. For details, see ColorConvertedBitmap Markup Extension.

  • ComponentResourceKey and ThemeDictionary support aspects of resource lookup, particularly for resources and themes that are packaged with custom controls. For more information, see ComponentResourceKey Markup ExtensionThemeDictionary Markup Extension, or Control Authoring Overview.

*Extension Classes

For both the general XAML language and WPF-specific markup extensions, the behavior of each markup extension is identified to a XAML processor through a *Extension class that derives from MarkupExtension, and provides an implementation of the ProvideValue method. This method on each extension provides the object that is returned when the markup extension is evaluated. The returned object is typically evaluated based on the various string tokens that are passed to the markup extension.

For example, the StaticResourceExtension class provides the surface implementation of actual resource lookup so that its ProvideValueimplementation returns the object that is requested, with the input of that particular implementation being a string that is used to look up the resource by its x:Key. Much of this implementation detail is unimportant if you are using an existing markup extension.

Some markup extensions do not use string token arguments. This is either because they return a static or consistent value, or because context for what value should be returned is available through one of the services passed through the serviceProvider parameter.

The *Extension naming pattern is for convenience and consistency. It is not necessary in order for a XAML processor to identify that class as support for a markup extension. So long as your codebase includes System.Xaml and uses .NET Framework XAML Services implementations, all that is necessary to be recognized as a XAML markup extension is to derive from MarkupExtension and to support a construction syntax. WPF defines markup extension-enabling classes that do not follow the *Extension naming pattern, for example Binding. Typically the reason for this is that the class supports scenarios beyond pure markup extension support. In the case of Binding, that class supports run-time access to methods and properties of the object for scenarios that have nothing to do with XAML.

Extension Class Interpretation of Initialization Text

The string tokens following the markup extension name and still within the braces are interpreted by a XAML processor in one of the following ways:

  • A comma always represents the separator or delimiter of individual tokens.

  • If the individual separated tokens do not contain any equals signs, each token is treated as a constructor argument. Each constructor parameter must be given as the type expected by that signature, and in the proper order expected by that signature.

    System_CAPS_noteNote

    A XAML processor must call the constructor that matches the argument count of the number of pairs. For this reason, if you are implementing a custom markup extension, do not provide multiple parameters with the same argument count. The behavior for how a XAML processor behaves if more than one markup extension constructor path with the same parameter count exists is not defined, but you should anticipate that a XAML processor is permitted to throw an exception on usage if this situation exists in the markup extension type definitions.

  • If the individual separated tokens contain equals signs, then a XAML processor first calls the default constructor for the markup extension. Then, each name=value pair is interpreted as a property name that exists on the markup extension, and a value to assign to that property.

  • If there is a parallel result between the constructor behavior and the property setting behavior in a markup extension, it does not matter which behavior you use. It is more common usage to use the property=value pairs for markup extensions that have more than one settable property, if only because it makes your markup more intentional and you are less likely to accidentally transpose constructor parameters. (When you specify property=value pairs, those properties may be in any order.) Also, there is no guarantee that a markup extension supplies a constructor parameter that sets every one of its settable properties. For example, Binding is a markup extension, with many properties that are settable through the extension in property=value form, but Binding only supports two constructors: a default constructor, and one that sets an initial path.

  • A literal comma cannot be passed to a markup extension without escapement.

Escape Sequences and Markup Extensions

Attribute handling in a XAML processor uses the curly braces as indicators of a markup extension sequence. It is also possible to produce a literal curly brace character attribute value if necessary, by entering an escape sequence using an empty curly brace pair followed by the literal curly brace. See {} Escape Sequence / Markup Extension.

Nesting Markup Extensions in XAML Usage

Nesting of multiple markup extensions is supported, and each markup extension will be evaluated deepest first. For example, consider the following usage:

<Setter Property="Background"
  Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />

In this usage, the x:Static statement is evaluated first and returns a string. That string is then used as the argument for DynamicResource.

Markup Extensions and Property Element Syntax

When used as an object element that fills a property element value, a markup extension class is visually indistinguishable from a typical type-backed object element that can be used in XAML. The practical difference between a typical object element and a markup extension is that the markup extension is either evaluated to a typed value or deferred as an expression. Therefore the mechanisms for any possible type errors of property values for the markup extension will be different, similar to how a late-bound property is treated in other programming models. An ordinary object element will be evaluated for type match against the target property it is setting when the XAML is parsed.

Most markup extensions, when used in object element syntax to fill a property element, would not have content or any further property element syntax within. Thus you would close the object element tag, and provide no child elements. Whenever any object element is encountered by a XAML processor, the constructor for that class is called, which instantiates the object created from the parsed element. A markup extension class is no different: if you want your markup extension to be usable in object element syntax, you must provide a default constructor. Some existing markup extensions have at least one required property value that must be specified for effective initialization. If so, that property value is typically given as a property attribute on the object element. In the XAML Namespace (x:) Language Features and WPF XAML Extensions reference pages, markup extensions that have required properties (and the names of required properties) will be noted. Reference pages will also note if either object element syntax or attribute syntax is disallowed for particular markup extensions. A notable case is x:Array Markup Extension, which cannot support attribute syntax because the contents of that array must be specified within the tagging as content. The array contents are handled as general objects, therefore no default type converter for the attribute is feasible. Also, x:Array Markup Extension requires a type parameter.



XAML Namespaces and Namespace Mapping for WPF XAML


This topic further explains the presence and purpose of the two XAML namespace mappings as often found in the root tag of a WPF XAML file. It also describes how to produce similar mappings for using elements that are defined in your own code, and/or within separate assemblies.

What is a XAML Namespace?

A XAML namespace is really an extension of the concept of an XML namespace. The techniques of specifying a XAML namespace rely on the XML namespace syntax, the convention of using URIs as namespace identifiers, using prefixes to provide a means to reference multiple namespaces from the same markup source, and so on. The primary concept that is added to the XAML definition of the XML namespace is that a XAML namespace implies both a scope of uniqueness for the markup usages, and also influences how markup entities are potentially backed by specific CLR namespaces and referenced assemblies. This latter consideration is also influenced by the concept of a XAML schema context. But for purposes of how WPF works with XAML namespaces, you can generally think of XAML namespaces in terms of a default XAML namespace, the XAML language namespace, and any further XAML namespaces as mapped by your XAML markup directly to specific backing CLR namespaces and referenced assemblies.

The WPF and XAML Namespace Declarations

Within the namespace declarations in the root tag of many XAML files, you will see that there are typically two XML namespace declarations. The first declaration maps the overall WPF client / framework XAML namespace as the default:

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

The second declaration maps a separate XAML namespace, mapping it (typically) to the x: prefix.

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

The relationship between these declarations is that the x: prefix mapping supports the intrinsics that are part of the XAML language definition, and WPF is one implementation that uses XAML as a language and defines a vocabulary of its objects for XAML. Because the WPF vocabulary's usages will be far more common than the XAML intrinsics usages, the WPF vocabulary is mapped as the default.

The x: prefix convention for mapping the XAML language intrinsics support is followed by project templates, sample code, and the documentation of language features within this SDK. The XAML namespace defines many commonly-used features that are necessary even for basic WPF applications. For instance, in order to join any code-behind to a XAML file through a partial class, you must name that class as the x:Class attribute in the root element of the relevant XAML file. Or, any element as defined in a XAML page that you wish to access as a keyed resource should have the x:Keyattribute set on the element in question. For more information on these and other aspects of XAML see XAML Overview (WPF) or XAML Syntax In Detail.

Mapping to Custom Classes and Assemblies

You can map XML namespaces to assemblies using a series of tokens within an xmlns prefix declaration, similar to how the standard WPF and XAML-intrinsics XAML namespaces are mapped to prefixes.

The syntax takes the following possible named tokens and following values:

clr-namespace: The CLR namespace declared within the assembly that contains the public types to expose as elements.

assembly= The assembly that contains some or all of the referenced CLR namespace. This value is typically just the name of the assembly, not the path, and does not include the extension (such as .dll or .exe). The path to that assembly must be established as a project reference in the project file that contains the XAML you are trying to map. In order to incorporate versioning and strong-name signing, the assembly value can be a string as defined by AssemblyName, rather than the simple string name.

Note that the character separating the clr-namespace token from its value is a colon (:) whereas the character separating the assembly token from its value is an equals sign (=). The character to use between these two tokens is a semicolon. Also, do not include any whitespace anywhere in the declaration.

A Basic Custom Mapping Example

The following code defines an example custom class:

namespace SDKSample {
    public class ExampleClass : ContentControl {
        public ExampleClass() {
        ...
        }
    }
}

This custom class is then compiled into a library, which per the project settings (not shown) is named SDKSampleLibrary.

In order to reference this custom class, you also need to include it as a reference for your current project, which you would typically do using the Solution Explorer UI in Visual Studio.

Now that you have a library containing a class, and a reference to it in project settings, you can add the following prefix mapping as part of your root element in XAML:

xmlns:custom="clr-namespace:SDKSample;assembly=SDKSampleLibrary"

To put it all together, the following is XAML that includes the custom mapping along with the typical default and x: mappings in the root tag, then uses a prefixed reference to instantiate ExampleClass in that UI:

<Page x:Class="WPFApplication1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:custom="clr-namespace:SDKSample;assembly=SDKSampleLibrary">
  ...
  <custom:ExampleClass/>
...
</Page>

Mapping to Current Assemblies

assembly can be omitted if the clr-namespace referenced is being defined within the same assembly as the application code that is referencing the custom classes. Or, an equivalent syntax for this case is to specify assembly=, with no string token following the equals sign.

Custom classes cannot be used as the root element of a page if defined in the same assembly. Partial classes do not need to be mapped; only classes that are not the partial class of a page in your application need to be mapped if you intend to reference them as elements in XAML.

Mapping CLR Namespaces to XML Namespaces in an Assembly

WPF defines a CLR attribute that is consumed by XAML processors in order to map multiple CLR namespaces to a single XAML namespace. This attribute, XmlnsDefinitionAttribute, is placed at the assembly level in the source code that produces the assembly. The WPF assembly source code uses this attribute to map the various common namespaces, such as System.Windows and System.Windows.Controls, to the http://schemas.microsoft.com/winfx/2006/xaml/presentation namespace.

The XmlnsDefinitionAttribute takes two parameters: the XML/XAML namespace name, and the CLR namespace name. More than oneXmlnsDefinitionAttribute can exist to map multiple CLR namespaces to the same XML namespace. Once mapped, members of those namespaces can also be referenced without full qualification if desired by providing the appropriate using statement in the partial-class code-behind page. For more details, see XmlnsDefinitionAttribute.

Designer Namespaces and Other Prefixes From XAML Templates

If you are working with development environments and/or design tools for WPF XAML, you may notice that there are other defined XAML namespaces / prefixes within the XAML markup.

WPF Designer for Visual Studio uses a designer namespace that is typically mapped to the prefix d:. More recent project templates for WPF might pre-map this XAML namespace to support interchange of the XAML between WPF Designer for Visual Studio and other design environments. This design XAML namespace is used to perpetuate design state while roundtripping XAML-based UI in the designer. It is also used for features such asd:IsDataSource, which enable runtime data sources in a designer. 

Another prefix you might see mapped is mc:mc: is for markup compatibility, and is leveraging a markup compatibility pattern that is not necessarily XAML-specific. To some extent, the markup compatibility features can be used to exchange XAML between frameworks or across other boundaries of backing implementation, work between XAML schema contexts, provide compatibility for limited modes in designers, and so on. For more information on markup compatibility concepts and how they relate to WPF, see Markup Compatibility (mc:) Language Features.

WPF and Assembly Loading

The XAML schema context for WPF integrates with the WPF application model, which in turn uses the CLR-defined concept of AppDomain. The following sequence describes how XAML schema context interprets how to either load assemblies or find types at run time or design time, based on the WPF use of AppDomain and other factors.

  1. Iterate through the AppDomain, looking for an already-loaded assembly that matches all aspects of the name, starting from the most recently loaded assembly.

  2. If the name is qualified, call Assembly.Load(String) on the qualified name.

  3. If the short name + public key token of a qualified name matches the assembly that the markup was loaded from, return that assembly.

  4. Use the short name + public key token to call Assembly.Load(String).

  5. If the name is unqualified, call Assembly.LoadWithPartialName.

Loose XAML does not use Step 3; there is no loaded-from assembly.

Compiled XAML for WPF (generated via XamlBuildTask) does not use the already-loaded assemblies from AppDomain (Step 1). Also, the name should never be unqualified from XamlBuildTask output, so Step 5 does not apply.

Compiled BAML (generated via PresentationBuildTask) uses all steps, although BAML also should not contain unqualified assembly names.



WPF XAML Namescopes


XAML namescopes are a concept that identifies objects that are defined in XAML. The names in a XAML namescope can be used to establish relationships between the XAML-defined names of objects and their instance equivalents in an object tree. Typically, XAML namescopes in WPF managed code are created when loading the individual XAML page roots for a XAML application. XAML namescopes as the programming object are defined by the INameScope interface and are also implemented by the practical class NameScope.

Namescopes in Loaded XAML Applications

In a broader programming or computer science context, programming concepts often include the principle of a unique identifier or name that can be used to access an object. For systems that use identifiers or names, the namescope defines the boundaries within which a process or technique will search if an object of that name is requested, or the boundaries wherein uniqueness of identifying names is enforced. These general principles are true for XAML namescopes. In WPF, XAML namescopes are created on the root element for a XAML page when the page is loaded. Each name specified within the XAML page starting at the page root is added to a pertinent XAML namescope.

In WPF XAML, elements that are common root elements (such as Page, and Window) always control a XAML namescope. If an element such asFrameworkElement or FrameworkContentElement is the root element of the page in markup, a XAML processor adds a Page root implicitly so that the Page can provide a working XAML namescope.

System_CAPS_noteNote

WPF build actions create a XAML namescope for a XAML production even if no Name or x:Name attributes are defined on any elements in the XAML markup.

If you try to use the same name twice in any XAML namescope, an exception is raised. For WPF XAML that has code-behind and is part of a compiled application, the exception is raised at build time by WPF build actions, when creating the generated class for the page during the initial markup compile. For XAML that is not markup-compiled by any build action, exceptions related to XAML namescope issues might be raised when the XAML is loaded. XAML designers might also anticipate XAML namescope issues at design time.

Adding Objects to Runtime Object Trees

The moment that XAML is parsed represents the moment in time that a WPF XAML namescope is created and defined. If you add an object to an object tree at a point in time after the XAML that produced that tree was parsed, a Name or x:Name value on the new object does not automatically update the information in a XAML namescope. To add a name for an object into a WPF XAML namescope after XAML is loaded, must call the appropriate implementation of RegisterName on the object that defines the XAML namescope, which is typically the XAML page root. If the name is not registered, the added object cannot be referenced by name through methods such as FindName, and you cannot use that name for animation targeting.

The most common scenario for application developers is that you will use RegisterName to register names into the XAML namescope on the current root of the page. RegisterName is part of an mportant scenario for storyboards that target objects for animations. For more information, see Storyboards Overview.

If you call RegisterName on an object other than the object that defines the XAML namescope, the name is still registered to the XAML namescope that the calling object is held within, as if you had called RegisterName on the XAML namescope defining object.

XAML Namescopes in Code

You can create and then use XAML namescopes in code. The APIs and the concepts involved in XAML namescope creation are the same even for a pure code usage, because the XAML processor for WPF uses these APIs and concepts when it processes XAML itself. The concepts and API exist mainly for the purpose of being able to find objects by name within an object tree that is typically defined partially or entirely in XAML.

For applications that are created programmatically, and not from loaded XAML, the object that defines a XAML namescope must implementINameScope, or be a FrameworkElement or FrameworkContentElement derived class, in order to support creation of a XAML namescope on its instances.

Also, for any element that is not loaded and processed by a XAML processor, the XAML namescope for the object is not created or initialized by default. You must explicitly create a new XAML namescope for any object that you intend to register names into subsequently. To create a XAML namescope, you call the static SetNameScope method. Specify the object that will own it as the dependencyObject parameter, and a newNameScope constructor call as the value parameter.

If the object provided as dependencyObject for SetNameScope is not a INameScope implementation, FrameworkElement orFrameworkContentElement, calling RegisterName on any child elements will have no effect. If you fail to create the new XAML namescope explicitly, then calls to RegisterName will raise an exception.

For an example of using XAML namescope APIs in code, see How to: Define a Name Scope.

XAML Namescopes in Styles and Templates

Styles and templates in WPF provide the ability to reuse and reapply content in a straightforward way. However, styles and templates might also include elements with XAML names defined at the template level. That same template might be used multiple times in a page. For this reason, styles and templates both define their own XAML namescopes, independent of whatever location in an object tree where the style or template is applied.

Consider the following example:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <Page.Resources>
    <ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
      <Border BorderBrush="Red" Name="TheBorder" BorderThickness="2">
        <ContentPresenter/>
      </Border>      
    </ControlTemplate>
  </Page.Resources>
  <StackPanel>
    <Button Template="{StaticResource MyButtonTemplate}">My first button</Button>
    <Button Template="{StaticResource MyButtonTemplate}">My second button</Button>
  </StackPanel>
</Page>

Here, the same template is applied to two different buttons. If templates did not have discrete XAML namescopes, the TheBorder name used in the template would cause a name collision in the XAML namescope. Each instantiation of the template has its own XAML namescope, so in this example each instantiated template's XAML namescope would contain exactly one name.

Styles also define their own XAML namescope, mostly so that parts of storyboards can have particular names assigned. These names enable control specific behaviors that will target elements of that name, even if the template was re-defined as part of control customization.

Because of the separate XAML namescopes, finding named elements in a template is more challenging than finding a non-templated named element in a page. You first need to determine the applied template, by getting the Template property value of the control where the template is applied. Then, you call the template version of FindName, passing the control where the template was applied as the second parameter.

If you are a control author and you are generating a convention where a particular named element in an applied template is the target for a behavior that is defined by the control itself, you can use the GetTemplateChild method from your control implementation code. The GetTemplateChildmethod is protected, so only the control author has access to it.

If you are working from within a template, and need to get to the XAML namescope where the template is applied, get the value of TemplatedParent, and then call FindName there. An example of working within the template would be if you are writing the event handler implementation where the event will be raised from an element in an applied template.

XAML Namescopes and Name-related APIs

FrameworkElement has FindNameRegisterName and UnregisterName methods. If the object you call these methods on owns a XAML namescope, the methods call into the methods of the relevant XAML namescope. Otherwise, the parent element is checked to see if it owns a XAML namescope, and this process continues recursively until a XAML namescope is found (because of the XAML processor behavior, there is guaranteed to be a XAML namescope at the root). FrameworkContentElement has analogous behaviors, with the exception that no FrameworkContentElement will ever own a XAML namescope. The methods exist on FrameworkContentElement so that the calls can be forwarded eventually to a FrameworkElement parent element.

SetNameScope is used to map a new XAML namescope to an existing object. You can call SetNameScope more than once in order to reset or clear the XAML namescope, but that is not a common usage. Also, GetNameScope is not typically used from code.

XAML Namescope Implementations

The following classes implement INameScope directly:

ResourceDictionary does not use XAML names or namescopes ; it uses keys instead, because it is a dictionary implementation. The only reason that ResourceDictionary implements INameScope is so it can raise exceptions to user code that help clarify the distinction between a true XAML namescope and how a ResourceDictionary handles keys, and also to assure that XAML namescopes are not applied to a ResourceDictionary by parent elements.

FrameworkTemplate and Style implement INameScope through explicit interface definitions. The explicit implementations allow these XAML namescopes to behave conventionally when they are accessed through the INameScope interface, which is how XAML namescopes are communicated by WPF internal processes. But the explicit interface definitions are not part of the conventional API surface of FrameworkTemplateand Style, because you seldom need to call the INameScope methods on FrameworkTemplate and Style directly, and instead would use other API such as GetTemplateChild.

The following classes define their own XAML namescope, by using the System.Windows.NameScope helper class and connecting to its XAML namescope implementation through the NameScope.NameScope attached property:



Inline Styles and Templates


Windows Presentation Foundation (WPF) provides Style objects and template objects (FrameworkTemplate subclasses) as a way to define the visual appearance of an element in resources, so that they can be used multiple times. For this reason, attributes in XAML that take the types Style andFrameworkTemplate almost always make resource references to existing styles and templates rather than define new ones inline.

Limitations of Inline Styles and Templates

In Extensible Application Markup Language (XAML), style and template properties can technically be set in one of two ways. You can use attribute syntax to reference a style that was defined within a resource, for example <object Style="{StaticResource myResourceKey}" .../>. Or you can use property element syntax to define a style inline, for instance:

<object>

<object.Style>

<Style .../>

</object.Style>

</object>

The attribute usage is much more common. A style that is defined inline and not defined in resources is necessarily scoped to the containing element only, and cannot be re-used as easily because it has no resource key. In general a resource-defined style is more versatile and useful, and is more in keeping with the general Windows Presentation Foundation (WPF) programming model principle of separating program logic in code from design in markup.

Usually there is no reason to set a style or template inline, even if you only intend to use that style or template in that location. Most elements that can take a style or template also support a content property and a content model. If you are only using whatever logical tree you create through styling or templating once, it would be even easier to just fill that content property with the equivalent child elements in direct markup. This would bypass the style and template mechanisms altogether.

Other syntaxes enabled by markup extensions that return an object are also possible for styles and templates. Two such extensions that have possible scenarios include TemplateBinding and Binding.



TypeConverters and XAML


This topic introduces the purpose of type conversion from string as a general XAML language feature. In the .NET Framework, the TypeConverter class serves a particular purpose as part of the implementation for a managed custom class that can be used as a property value in XAML attribute usage. If you write a custom class, and you want instances of your class to be usable as XAML settable attribute values, you might need to apply aTypeConverterAttribute to your class, write a custom TypeConverter class, or both.

Type Conversion Concepts

XAML and String Values

When you set an attribute value in a XAML file, the initial type of that value is a string in pure text. Even other primitives such as Double are initially text strings to a XAML processor.

A XAML processor needs two pieces of information in order to process an attribute value. The first piece of information is the value type of the property that is being set. Any string that defines an attribute value and that is processed in XAML must ultimately be converted or resolved to a value of that type. If the value is a primitive that is understood by the XAML parser (such as a numeric value), a direct conversion of the string is attempted. If the value is an enumeration, the string is used to check for a name match to a named constant in that enumeration. If the value is neither a parser-understood primitive nor an enumeration, then the type in question must be able to provide an instance of the type, or a value, based on a converted string. This is done by indicating a type converter class. The type converter is effectively a helper class for providing values of another class, both for the XAML scenario and also potentially for code calls in .NET code.

Using Existing Type Conversion Behavior in XAML

Depending on your familiarity with the underlying XAML concepts, you may already be using type conversion behavior in basic application XAML without realizing it. For instance, WPF defines literally hundreds of properties that take a value of type Point. A Point is a value that describes a coordinate in a two-dimensional coordinate space, and it really just has two important properties: X and Y. When you specify a point in XAML, you specify it as a string with a delimiter (typically a comma) between the X and Y values you provide. For example: <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">.

Even this simple type of Point and its simple usage in XAML involve a type converter. In this case that is the class PointConverter.

The type converter for Point defined at the class level streamlines the markup usages of all properties that take Point. Without a type converter here, you would need the following much more verbose markup for the same example shown previously:

<LinearGradientBrush>

<LinearGradientBrush.StartPoint>

<Point X="0" Y="0"/>

</LinearGradientBrush.StartPoint>

<LinearGradientBrush.EndPoint>

<Point X="1" Y="1"/>

</LinearGradientBrush.EndPoint>

<LinearGradientBrush>

Whether to use the type conversion string or a more verbose equivalent syntax is generally a coding style choice. Your XAML tooling workflow might also influence how values are set. Some XAML tools tend to emit the most verbose form of the markup because it is easier to round-trip to designer views or its own serialization mechanism.

Existing type converters can generally be discovered on WPF and .NET Framework types by checking a class (or property) for the presence of an applied TypeConverterAttribute. This attribute will name the class that is the supporting type converter for values of that type, for XAML purposes as well as potentially other purposes.

Type Converters and Markup Extensions

Markup extensions and type converters fill orthogonal roles in terms of XAML processor behavior and the scenarios that they are applied to. Although context is available for markup extension usages, type conversion behavior of properties where a markup extension provides a value is generally is not checked in the markup extension implementations. In other words, even if a markup extension returns a text string as itsProvideValue output, type conversion behavior on that string as applied to a specific property or property value type is not invoked, Generally, the purpose of a markup extension is to process a string and return an object without any type converter involved.

One common situation where a markup extension is necessary rather than a type converter is to make a reference to an object that already exists. At best, a stateless type converter could only generate a new instance, which might not be desirable. For more information on markup extensions, see Markup Extensions and WPF XAML.

Native Type Converters

In the WPF and .NET Framework implementation of the XAML parser, there are certain types that have native type conversion handling, yet are not types that might conventionally be thought of as primitives. An example of such a type is DateTime. The reason for this is based on how the .NET Framework architecture works: the type DateTime is defined in mscorlib, the most basic library in .NET. DateTime is not permitted to be attributed with an attribute that comes from another assembly that introduces a dependency (TypeConverterAttribute is from System) so the usual type converter discovery mechanism by attributing cannot be supported. Instead, the XAML parser has a list of types that need such native processing and processes these similarly to how the true primitives are processed. (In the case of DateTime this involves a call to Parse.

Implementing a Type Converter

TypeConverter

In the Point example given previously, the class PointConverter was mentioned. For .NET implementations of XAML, all type converters that are used for XAML purposes are classes that derive from the base class TypeConverter. The TypeConverter class existed in versions of .NET Framework that precede the existence of XAML; one of its original usages was to provide string conversion for property dialogs in visual designers. For XAML, the role of TypeConverter is expanded to include being the base class for to-string and from-string conversions that enable parsing a string attribute value, and possibly processing a run-time value of a particular object property back into a string for serialization as an attribute.

TypeConverter defines four members that are relevant for converting to and from strings for XAML processing purposes:

Of these, the most important method is ConvertFrom. This method converts the input string to the required object type. Strictly speaking, theConvertFrom method could be implemented to convert a much wider range of types into the converter's intended destination type, and thus serve purposes that extend beyond XAML such as supporting run-time conversions, but for XAML purposes it is only the code path that can process a String input that matters.

The next most important method is ConvertTo. If an application is converted to a markup representation (for instance, if it is saved to XAML as a file), ConvertTo is responsible for producing a markup representation. In this case, the code path that matters for XAML is when you pass adestinationType of String .

CanConvertTo and CanConvertFrom are support methods that are used when a service queries the capabilities of the TypeConverterimplementation. You must implement these methods to return true for type-specific cases that the equivalent conversion methods of your converter support. For XAML purposes, this generally means the String type.

Culture Information and Type Converters for XAML

Each TypeConverter implementation can have its own interpretation of what constitutes a valid string for a conversion, and can also use or ignore the type description passed as parameters. There is an important consideration with regard to culture and XAML type conversion. Using localizable strings as attribute values is entirely supported by XAML. But using that localizable string as type converter input with specific culture requirements is not supported, because type converters for XAML attribute values involve a necessarily fixed-language parsing behavior, using en-US culture. For more information on the design reasons for this restriction, you should consult the XAML language specification ([MS-XAML]).

As an example where culture can be an issue, some cultures use a comma as their decimal point delimiter for numbers. This will collide with the behavior that many of the WPF XAML type converters have, which is to use a comma as a delimiter (based on historical precedents such as the common X,Y form, or comma delimited lists). Even passing a culture in the surrounding XAML (setting Language or xml:lang to the sl-SIculture, an example of a culture that uses a comma for decimal in this way) does not solve the issue.

Implementing ConvertFrom

To be usable as a TypeConverter implementation that supports XAML, the ConvertFrom method for that converter must accept a string as thevalue parameter. If the string was in valid format, and can be converted by the TypeConverter implementation, then the returned object must support a cast to the type expected by the property. Otherwise, the ConvertFrom implementation must return null.

Each TypeConverter implementation can have its own interpretation of what constitutes a valid string for a conversion, and can also use or ignore the type description or culture contexts passed as parameters. However, the WPF XAML processing might not pass values to the type description context in all cases, and also might not pass culture based on xml:lang.

System_CAPS_noteNote

Do not use the curly brace characters, particularly {, as a possible element of your string format. These characters are reserved as the entry and exit for a markup extension sequence.

Implementing ConvertTo

ConvertTo is potentially used for serialization support. Serialization support through ConvertTo for your custom type and its type converter is not an absolute requirement. However, if you are implementing a control, or using serialization of as part of the features or design of your class, you should implement ConvertTo.

To be usable as a TypeConverter implementation that supports XAML, the ConvertTo method for that converter must accept an instance of the type (or a value) being supported as the value parameter. When the destinationType parameter is the type String, then the returned object must be able to be cast as String. The returned string must represent a serialized value of value. Ideally, the serialization format you choose should be capable of generating the same value if that string were passed to the ConvertFrom implementation of the same converter, without significant loss of information.

If the value cannot be serialized, or the converter does not support serialization, the ConvertTo implementation must return null, and is permitted to throw an exception in this case. But if you do throw exceptions, you should report the inability to use that conversion as part of yourCanConvertTo implementation so that the best practice of checking with CanConvertTo first to avoid exceptions is supported.

If destinationType parameter is not of type String, you can choose your own converter handling. Typically, you would revert to base implementation handling, which in the basemost ConvertTo raises a specific exception.

Implementing CanConvertTo

Your CanConvertTo implementation should return true for destinationType of type String, and otherwise defer to the base implementation.

Implementing CanConvertFrom

Your CanConvertFrom implementation should return true for sourceType of type String, and otherwise defer to the base implementation.

Applying the TypeConverterAttribute

In order for your custom type converter to be used as the acting type converter for a custom class by a XAML processor, you must apply the .NET Framework attribute TypeConverterAttribute to your class definition. The ConverterTypeName that you specify through the attribute must be the type name of your custom type converter. With this attribute applied, when a XAML processor handles values where the property type uses your custom class type, it can input strings and return object instances.

You can also provide a type converter on a per-property basis. Instead of applying a .NET Framework attribute TypeConverterAttribute to the class definition, apply it to a property definition (the main definition, not the get/set implementations within it). The type of the property must match the type that is processed by your custom type converter. With this attribute applied, when a XAMLprocessor handles values of that property, it can process input strings and return object instances. The per-property type converter technique is particularly useful if you choose to use a property type from Microsoft .NET Framework or from some other library where you cannot control the class definition and cannot apply aTypeConverterAttribute there.





WPF XAML Extensions



Binding Markup Extension


Defers a property value to be a data-bound value, creating an intermediate expression object and interpreting the data context that applies to the element and its binding at run time.

Binding Expression Usage

<object property="{Binding}" .../>
-or-
<object property="{Binding bindProp1=value1[, bindPropN=valueN]*}" ...
/>
-or-
<object property="{Binding path}" .../>
-or
<object property="{Binding path[, bindPropN=valueN]*}" .../>

Syntax Notes

In these syntaxes, the [] and * are not literals. They are part of a notation to indicate that zero or more bindProp=value pairs can be used, with a ,separator between them and preceding bindProp=value pairs.

Any of the properties listed in the "Binding Properties That Can Be Set with the Binding Extension" section could instead be set using attributes of aBinding object element. However, that is not truly the markup extension usage of Binding, it is just the general XAML processing of attributes that set properties of the CLR Binding class. In other words, <Binding bindProp1="value1"[ bindPropN="valueN"]*/> is an equivalent syntax for attributes ofBinding object element usage instead of a Binding expression usage. To learn about the XAML attribute usage of specific properties of Binding, see the "XAML Attribute Usage" section of the relevant property of Binding in the .NET Framework Class Library.

XAML Values

bindProp1, bindPropN

The name of the Binding or BindingBase property to set. Not all Binding properties can be set with the Binding extension, and some properties are settable within a Binding expression only by using further nested markup extensions. See "Binding Properties That Can Be Set with the Binding Extension" section.

value1, valueN

The value to set the property to. The handling of the attribute value is ultimately specific to the type and logic of the specific Bindingproperty being set.

path

The path string that sets the implicit Binding.Path property. See also PropertyPath XAML Syntax.

Unqualified {Binding}

The {Binding} usage shown in "Binding Expression Usage" creates a Binding object with default values, which includes an initial Binding.Path of null. This is still useful in many scenarios, because the created Binding might be relying on key data binding properties such as Binding.Path andBinding.Source being set in the run-time data context. For more information on the concept of data context, see Data Binding (WPF).

Implicit Path

The Binding markup extension uses Binding.Path as a conceptual "default property", where Path= does not need to appear in the expression. If you specify a Binding expression with an implicit path, the implicit path must appear first in the expression, prior to any other bindProp=value pairs where the Binding property is specified by name. For example: {Binding PathString}, where PathString is a string that is evaluated to be the value ofBinding.Path in the Binding created by the markup extension usage. You can append an implicit path with other named properties after the comma separator, for example, {Binding LastName, Mode=TwoWay}.

Binding Properties That Can Be Set with the Binding Extension

The syntax shown in this topic uses the generic bindProp=value approximation, because there are many read/write properties of BindingBase or Bindingthat can be set through the Binding markup extension / expression syntax. They can be set in any order, with the exception of an implicit Binding.Path. (You do have the option to explicitly specify Path=, in which case it can be set in any order). Basically, you can set zero or more of the properties in the list below, using bindProp=value pairs separated by commas.

Several of these property values require object types that do not support a native type conversion from a text syntax in XAML, and thus require markup extensions in order to be set as an attribute value. Check the XAML Attribute Usage section in the .NET Framework Class Library for each property for more information; the string you use for XAML attribute syntax with or without further markup extension usage is basically the same as the value you specify in a Binding expression, with the exception that you do not place quotation marks around each bindProp=value in the Binding expression.

The following are properties of Binding that cannot be set using the Binding markup extension/{Binding} expression form.

  • UpdateSourceExceptionFilter: this property expects a reference to a callback implementation. Callbacks/methods other than event handlers cannot be referenced in XAML syntax.

  • ValidationRules: the property takes a generic collection of ValidationRule objects. This could be expressed as a property element in a Bindingobject element, but has no readily available attribute-parsing technique for usage in a Binding expression. See reference topic forValidationRules.

  • XmlNamespaceManager

Remarks

System_CAPS_importantImportant

In terms of dependency property precedence, a Binding expression is equivalent to a locally set value. If you set a local value for a property that previously had a Binding expression, the Binding is completely removed. For details, see Dependency Property Value Precedence.

Describing data binding at a basic level is not covered in this topic. See Data Binding Overview.

System_CAPS_noteNote

MultiBinding and PriorityBinding do not support a XAML extension syntax. You would instead use property elements. See reference topics forMultiBinding and PriorityBinding.

Boolean values for XAML are case insensitive. For example you could specify either {Binding NotifyOnValidationError=true} or{Binding NotifyOnValidationError=True}.

Bindings that involve data validation are typically specified by an explicit Binding element rather than as a {Binding ...} expression, and settingValidatesOnDataErrors or ValidatesOnExceptions in an expression is uncommon. This is because the companion property ValidationRules cannot be readily set in the expression form. For more information, see How to: Implement Binding Validation.

Binding is a markup extension. Markup extensions are typically implemented when there is a requirement to escape attribute values to be other than literal values or handler names, and the requirement is more global than type converters attributed on certain types or properties. All markup extensions in XAML use the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes that a markup extension must process the string contents. For more information, see Markup Extensions and WPF XAML.

Binding is an atypical markup extension in that the Binding class that implements the extension functionality for WPF's XAML implementation also implements several other methods and properties that are not related to XAML. The other members are intended to make Binding a more versatile and self-contained class that can address many data binding scenarios in addition to functioning as a XAML markup extension.



ColorConvertedBitmap Markup Extension


Provides a way to specify a bitmap source that does not have an embedded profile. Color contexts / profiles are specified by URI, as is the image source URI.

XAML Attribute Usage

<object property="{ColorConvertedBitmap imageSource sourceIIC destinationIIC}" .../>

XAML Values

imageSource

The URI of the nonprofiled bitmap.

sourceIIC

The URI of the source profile configuration.

destinationIIC

The URI of the destination profile configuration

Remarks

This markup extension is intended to fill a related set of image-source property values such as UriSource.

Attribute syntax is the most common syntax used with this markup extension. ColorConvertedBitmap (or ColorConvertedBitmapExtension) cannot be used in property element syntax, because the values can only be set as values on the initial constructor, which is the string following the extension identifier.

ColorConvertedBitmap is a markup extension. Markup extensions are typically implemented when there is a requirement to escape attribute values to be other than literal values or handler names, and the requirement is more global than just putting type converters on certain types or properties. All markup extensions in XAML use the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes that a markup extension must process the attribute. For more information, see Markup Extensions and WPF XAML.



ComponentResourceKey Markup Extension


Defines and references keys for resources that are loaded from external assemblies. This enables a resource lookup to specify a target type in an assembly, rather than an explicit resource dictionary in an assembly or on a class.

XAML Attribute Usage (setting key, compact)

<object x:Key="{ComponentResourceKey {x:Type targetTypeName}, targetID}" .../>

XAML Attribute Usage (setting key, verbose)

<object x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type targetTypeName}, ResourceID=targetID}" .../>

XAML Attribute Usage (requesting resource, compact)

<object property="{DynamicResource {ComponentResourceKey {x:Type targetTypeName}, targetID}}" .../>

XAML Attribute Usage (requesting resource, verbose)

<object property="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type targetTypeName}, ResourceID=targetID}}" .../>

XAML Values

targetTypeName

The name of the public common language runtime (CLR) type that is defined in the resource assembly.

targetID

The key for the resource. When resources are looked up, targetID will be analogous to the x:Key Directive of the resource.

Remarks

As seen in the usages above, a {ComponentResourceKey} markup extension usage is found in two places:

  • The definition of a key within a theme resource dictionary, as provided by a control author.

  • Accessing a theme resource from the assembly, when you are retemplating the control but want to use property values that come from resources provided by the control's themes.

For referencing component resources that come from themes, it is generally recommended that you use {DynamicResource} rather than{StaticResource}. This is shown in the usages. {DynamicResource} is recommended because the theme itself can be changed by the user. If you want the component resource that most closely matches the control author's intent for supporting a theme, you should enable your component resource reference to be dynamic also.

The TypeInTargetAssembly identifies a type that exists in the target assembly where the resource is actually defined. A ComponentResourceKey can be defined and used independently of knowing exactly where the TypeInTargetAssembly is defined, but eventually must resolve the type through referenced assemblies.

A common usage for ComponentResourceKey is to define keys that are then exposed as members of a class. For this usage, you use theComponentResourceKey class constructor, not the markup extension. For more information, see ComponentResourceKey, or the "Defining and Referencing Keys for Theme Resources" section of the topic Control Authoring Overview.

For both establishing keys and referencing keyed resources, attribute syntax is commonly used for the ComponentResourceKey markup extension.

The compact syntax shown relies on the ComponentResourceKey.ComponentResourceKey constructor signature and positional parameter usage of a markup extension. The order in which the targetTypeName and targetID are given is important. The verbose syntax relies on theComponentResourceKey.ComponentResourceKey default constructor, and then sets the TypeInTargetAssembly and ResourceId in a way that is analogous to a true attribute syntax on an object element. In the verbose syntax, the order in which the properties are set is not important. The relationship and mechanisms of these two alternatives (compact and verbose) is described in more detail in the topic Markup Extensions and WPF XAML.

Technically, the value for targetID can be any object, it does not have to be a string. However, the most common usage in WPF is to align the targetIDvalue with forms that are strings, and where such strings are valid in the XamlName Grammar.

ComponentResourceKey can be used in object element syntax. In this case, specifying the value of both the TypeInTargetAssembly and ResourceIdproperties is required to properly initialize the extension.

In the WPF XAML reader implementation, the handling for this markup extension is defined by the ComponentResourceKey class.

ComponentResourceKey is a markup extension. Markup extensions are typically implemented when there is a requirement to escape attribute values to be other than literal values or handler names, and the requirement is more global than just putting type converters on certain types or properties. All markup extensions in XAML use the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes that a markup extension must process the attribute. For more information, see Markup Extensions and WPF XAML.



DateTime XAML Syntax


Some controls, such as Calendar and DatePicker, have properties that use the DateTime type. Although you typically specify an initial date or time for these controls in the code-behind at run time, you can specify an initial date or time in XAML. The WPF XAML parser handles parsing of DateTime values using a built-in XAML text syntax. This topic describes the specifics of the DateTime XAML text syntax.

When To Use DateTime XAML Syntax

Setting dates in XAML is not always necessary and may not even be desirable. For example, you could use the DateTime.Now property to initialize a date at run time, or you could do all your date adjustments for a calendar in the code-behind based on user input. However, there are scenarios where you may want to hard-code dates into a Calendar and DatePicker in a control template. The DateTime XAML syntax must be used for these scenarios.

DateTime XAML Syntax is a Native Behavior

DateTime is a class that is defined in the base class libraries of the CLR. Because of how the base class libraries relate to the rest of the CLR, it is not possible to apply TypeConverterAttribute to the class and use a type converter to process strings from XAML and convert them to DateTime in the run time object model. There is no DateTimeConverter class that provides the conversion behavior; the conversion behavior described in this topic is native to the WPF XAML parser.

Format Strings for DateTime XAML Syntax

You can specify the format of a DateTime with a format string. Format strings formalize the text syntax that can be used to create a value. DateTimevalues for the existing WPF controls generally only use the date components of DateTime and not the time components.

When specifying a DateTime in XAML, you can use any of the format strings interchangeably.

You can also use formats and format strings that are not specifically shown in this topic. Technically, the XAML for any DateTime value that is specified and then parsed by the WPF XAML parser uses an internal call to DateTime.Parse, therefore you could use any string accepted by DateTime.Parse for your XAML input. For more information, see DateTime.Parse.

System_CAPS_importantImportant

The DateTime XAML syntax always uses en-us as the CultureInfo for its native conversion. This is not influenced by Language value or xml:lang value in the XAML, because XAML attribute-level type conversion acts without that context. Do not attempt to interpolate the format strings shown here due to cultural variations, such as the order in which day and month appear. The format strings shown here are the exact format strings used when parsing the XAML regardless of other culture settings.

The following sections describe some of the common DateTime format strings.

Short Date Pattern ("d")

The following shows the short date format for a DateTime in XAML:

M/d/YYYY

This is the simplest form that specifies all necessary information for typical usages by WPF controls, and cannot be influenced by accidental time zone offsets versus a time component, and is therefore recommended over the other formats.

For example, to specify the date of June 1, 2010, use the following string:

3/1/2010

For more information, see DateTimeFormatInfo.ShortDatePattern.

Sortable DateTime Pattern ("s")

The following shows the sortable DateTime pattern in XAML:

yyyy'-'MM'-'dd'T'HH':'mm':'ss

For example, to specify the date of June 1, 2010, use the following string (time components are all entered as 0):

2010-06-01T000:00:00

RFC1123 Pattern ("r")

The RFC1123 pattern is useful because it could be a string input from other date generators that also use the RFC1123 pattern for culture invariant reasons. The following shows the RFC1123 DateTime pattern in XAML:

ddd, dd MMM yyyy HH':'mm':'ss 'UTC'

For example, to specify the date of June 1, 2010, use the following string (time components are all entered as 0):

Mon, 01 Jun 2010 00:00:00 UTC

Other Formats and Patterns

As stated previously, a DateTime in XAML can be specified as any string that is acceptable as input for DateTime.Parse. This includes other formalized formats (for example UniversalSortableDateTimePattern), and formats that are not formalized as a particular DateTimeFormatInfo form. For example, the form YYYY/mm/dd is acceptable as input for DateTime.Parse. This topic does not attempt to describe all possible formats that work, and instead recommends the short date pattern as a standard practice.



DynamicResource Markup Extension


Provides a value for any XAML property attribute by deferring that value to be a reference to a defined resource. Lookup behavior for that resource is analogous to run-time lookup.

XAML Attribute Usage

<object property="{DynamicResource key}" .../>

XAML Property Element Usage

<object>
  <object.property>
    <DynamicResource ResourceKey="key" .../>
  </object.property>
</object>

XAML Values

key

The key for the requested resource. This key was initially assigned by the x:Key Directive if a resource was created in markup, or was provided as the key parameter when calling ResourceDictionary.Add if the resource was created in code.

Remarks

DynamicResource will create a temporary expression during the initial compilation and thus defer lookup for resources until the requested resource value is actually required in order to construct an object. This may potentially be after the XAML page is loaded. The resource value will be found based on key search against all active resource dictionaries starting from the current page scope, and is substituted for the placeholder expression from compilation.

System_CAPS_importantImportant

In terms of dependency property precedence, a DynamicResource expression is equivalent to the position where the dynamic resource reference is applied. If you set a local value for a property that previously had a DynamicResource expression as the local value, the DynamicResource is completely removed. For details, see Dependency Property Value Precedence.

Certain resource access scenarios are particularly appropriate for DynamicResource as opposed to a StaticResource Markup Extension. See XAML Resources for a discussion about the relative merits and performance implications of DynamicResource and StaticResource.

The specified ResourceKey should correspond to an existing resource determined by x:Key Directive at some level in your page, application, the available control themes and external resources, or system resources, and the resource lookup will happen in that order. For more information about resource lookup for static and dynamic resources, see XAML Resources.

A resource key may be any string defined in the XamlName Grammar. A resource key may also be other object types, such as a Type. A Type key is fundamental to how controls can be styled by themes. For more information, see Control Authoring Overview.

APIs for lookup of resource values, such as FindResource, follow the same resource lookup logic as used by DynamicResource.

The alternative declarative means of referencing a resource is as a StaticResource Markup Extension.

Attribute syntax is the most common syntax used with this markup extension. The string token provided after the DynamicResource identifier string is assigned as the ResourceKey value of the underlying DynamicResourceExtension extension class.

DynamicResource can be used in object element syntax. In this case, specifying the value of the ResourceKey property is required.

DynamicResource can also be used in a verbose attribute usage that specifies the ResourceKey property as a property=value pair:

<object property="{DynamicResource ResourceKey=key}" .../>

The verbose usage is often useful for extensions that have more than one settable property, or if some properties are optional. BecauseDynamicResource has only one settable property, which is required, this verbose usage is not typical.

In the WPF XAML processor implementation, the handling for this markup extension is defined by the DynamicResourceExtension class.

DynamicResource is a markup extension. Markup extensions are typically implemented when there is a requirement to escape attribute values to be other than literal values or handler names, and the requirement is more global than just putting type converters on certain types or properties. All markup extensions in XAML use the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes that a markup extension must process the attribute. For more information, see Markup Extensions and WPF XAML.



RelativeSource MarkupExtension


Specifies properties of a RelativeSource binding source, to be used within a Binding Markup Extension, or when setting the RelativeSource property of aBinding element established in XAML.

XAML Attribute Usage

<Binding RelativeSource="{RelativeSource modeEnumValue}" .../>

XAML Attribute Usage (nested within Binding extension)

<object property="{Binding RelativeSource={RelativeSource modeEnumValue} ...}" .../>

XAML Object Element Usage

<Binding>
  <Binding.RelativeSource>
    <RelativeSource Mode="modeEnumValue"/>
  </Binding.RelativeSource>
</Binding>
- or 
<Binding>
  <Binding.RelativeSource>
    <RelativeSource
      Mode="FindAncestor"
      AncestorType="{x:Type typeName}"
      AncestorLevel="intLevel"
    />
  </Binding.RelativeSource>
</Binding>

XAML Values

modeEnumValue

One of the following:

FindAncestor

The string token FindAncestor. Using this token enters a mode whereby a RelativeSource specifies an ancestor type and optionally an ancestor level. This corresponds to a RelativeSource as created with its Mode property set to FindAncestor.

typeName

Required for FindAncestor mode. The name of a type, which fills the AncestorType property.

intLevel

Optional for FindAncestor mode. An ancestor level (evaluated towards the parent direction in the logical tree).

Remarks

{RelativeSource TemplatedParent} binding usages are a key technique that addresses a larger concept of the separation of a control's UI and a control's logic. This enables binding from within the template definition to the templated parent (the run time object instance where the template is applied). For this case, the TemplateBinding Markup Extension is in fact a shorthand for the following binding expression: {Binding RelativeSource={RelativeSource TemplatedParent}}TemplateBinding or {RelativeSource TemplatedParent} usages are both only relevant within the XAML that defines a template. For more information, see TemplateBinding Markup Extension

{RelativeSource FindAncestor} is mainly used in control templates or predictable self-contained UI compositions, for cases where a control is always expected to be in a visual tree of a certain ancestor type. For example, items of an items control might use FindAncestor usages to bind to properties of their items control parent ancestor. Or, elements that are part of control composition in a template can use FindAncestor bindings to the parent elements in that same composition structure.

In the object element syntax for FindAncestor mode shown in the XAML Syntax sections, the second object element syntax is used specifically forFindAncestor mode. FindAncestor mode requires an AncestorType value. You must set AncestorType as an attribute using an x:Type Markup Extension reference to the type of ancestor to look for. The AncestorType value is used when the binding request is processed at run-time.

For FindAncestor mode, the optional property AncestorLevel can help disambiguate the ancestor lookup in cases where there is possibly more than one ancestor of that type existing in the element tree.

For more information on how to use the FindAncestor mode, see RelativeSource.

{RelativeSource Self} is useful for scenarios where one property of an instance should depend on the value of another property of the same instance, and no general dependency property relationship (such as coercion) already exists between those two properties. Although it is rare that two properties exist on an object such that the values are literally identical (and are identically typed), you can also apply a Converter parameter to a binding that has {RelativeSource Self}, and use the converter to convert between source and target types. Another scenario for {RelativeSource Self} is as part of a MultiDataTrigger.

For example, the following XAML defines a Rectangle element such that no matter what value is entered for Width, the Rectangle is always a square:<Rectangle Width="200" Height="{Binding RelativeSource={RelativeSource Self}, Path=Width}" .../>

{RelativeSource PreviousData} is useful either in data templates, or in cases where bindings are using a collection as the data source. You can use{RelativeSource PreviousData} to highlight relationships between adjacent data items in the collection. A related technique is to establish aMultiBinding between the current and previous items in the data source, and use a converter on that binding to determine the difference between the two items and their properties.

In the following example, the first TextBlock in the items template displays the current number. The second TextBlock binding is a MultiBinding that nominally has two Binding consistuents: the current record, and a binding that deliberately uses the previous data record by using {RelativeSource PreviousData}. Then, a converter on the MultiBinding calculates the difference and returns it to the binding.

<ListBox Name="fibolist">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding}"/>
            <TextBlock>, difference = </TextBlock>
                <TextBlock>
                    <TextBlock.Text>
                        <MultiBinding Converter="{StaticResource DiffConverter}">
                            <Binding/>
                            <Binding RelativeSource="{RelativeSource PreviousData}"/>
                        </MultiBinding>
                    </TextBlock.Text>
                </TextBlock>
            </StackPanel>
            </DataTemplate>
    </ListBox.ItemTemplate>

Describing data binding as a concept is not covered here, see Data Binding Overview.

In the WPF XAML processor implementation, the handling for this markup extension is defined by the RelativeSource class.

RelativeSource is a markup extension. Markup extensions are typically implemented when there is a requirement to escape attribute values to be other than literal values or handler names, and the requirement is more global than just putting type converters on certain types or properties. All markup extensions in XAML use the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes that a markup extension must process the attribute. For more information, see Markup Extensions and WPF XAML.



StaticResource Markup Extension


Provides a value for any XAML property attribute by looking up a reference to an already defined resource. Lookup behavior for that resource is analogous to load-time lookup, which will look for resources that were previously loaded from the markup of the current XAML page as well as other application sources, and will generate that resource value as the property value in the run-time objects.

XAML Attribute Usage

<object property="{StaticResource key}" .../>

XAML Object Element Usage

<object>
  <object.property>
<StaticResource ResourceKey="key" .../>
  </object.property>
</object>

XAML Values

key

The key for the requested resource. This key was initially assigned by the x:Key Directive if a resource was created in markup, or was provided as the key parameter when calling ResourceDictionary.Add if the resource was created in code.

Remarks

System_CAPS_importantImportant

StaticResource must not attempt to make a forward reference to a resource that is defined lexically further within the XAML file. Attempting to do so is not supported, and even if such a reference does not fail, attempting the forward reference will incur a load time performance penalty when the internal hash tables representing a ResourceDictionary are searched. For best results, adjust the composition of your resource dictionaries such that forward references can be avoided. If you cannot avoid a forward reference, use DynamicResource Markup Extension instead.

The specified ResourceKey should correspond to an existing resource, identified with an x:Key Directive at some level in your page, application, the available control themes and external resources, or system resources. The resource lookup occurs in that order. For more information about resource lookup behavior for static and dynamic resources, see XAML Resources.

A resource key can be any string defined in the XamlName Grammar. A resource key can also be other object types, such as a Type. A Type key is fundamental to how controls can be styled by themes, through an implicit style key. For more information, see Control Authoring Overview.

The alternative declarative means of referencing a resource is as a DynamicResource Markup Extension.

Attribute syntax is the most common syntax used with this markup extension. The string token provided after the StaticResource identifier string is assigned as the ResourceKey value of the underlying StaticResourceExtension extension class.

StaticResource can be used in object element syntax. In this case, specifying the value of the ResourceKey property is required.

StaticResource can also be used in a verbose attribute usage that specifies the ResourceKey property as a property=value pair:

<object property="{StaticResource ResourceKey=key}" .../>

The verbose usage is often useful for extensions that have more than one settable property, or if some properties are optional. Because StaticResourcehas only one settable property, which is required, this verbose usage is not typical.

In the WPF XAML processor implementation, the handling for this markup extension is defined by the StaticResourceExtension class.

StaticResource is a markup extension. Markup extensions are typically implemented when there is a requirement to escape attribute values to be other than literal values or handler names, and the requirement is more global than just putting type converters on certain types or properties. All markup extensions in XAML use the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes that a markup extension must process the attribute. For more information, see Markup Extensions and WPF XAML.



TemplateBinding Markup Extension


Links the value of a property in a control template to be the value of another property on the templated control.

XAML Attribute Usage

<object property="{TemplateBinding sourceProperty}" .../>

XAML Attribute Usage (for Setter property in template or style)

<Setter Property="propertyName" Value="{TemplateBinding sourceProperty}" .../>

XAML Values

propertyName

DependencyProperty.Name of the property being set in the setter syntax.

sourceProperty

Another dependency property that exists on the type being templated, specified by its DependencyProperty.Name.

- or -

A "dotted-down" property name that is defined by a different type than the target type being templated. This is actually aPropertyPath. See PropertyPath XAML Syntax.

Remarks

TemplateBinding is an optimized form of a Binding for template scenarios, analogous to a Binding constructed with {Binding RelativeSource={RelativeSource TemplatedParent}}. A TemplateBinding is always a one-way binding, even if properties involved default to two-way binding. Both properties involved must be dependency properties.

RelativeSource is another markup extension that is sometimes used in conjunction with or instead of TemplateBinding in order to perform relative property binding within a template.

Describing control templates as a concept is not covered here; for more information, see Control Styles and Templates.

Attribute syntax is the most common syntax used with this markup extension. The string token provided after the TemplateBinding identifier string is assigned as the Property value of the underlying TemplateBindingExtension extension class.

Object element syntax is possible, but it is not shown because it has no realistic application. TemplateBinding is used to fill values within setters, using evaluated expressions, and using object element syntax for TemplateBinding to fill <Setter.Property> property element syntax is unnecessarily verbose.

TemplateBinding can also be used in a verbose attribute usage that specifies the Property property as a property=value pair:

<object property="{TemplateBinding Property=sourceProperty}" .../>

The verbose usage is often useful for extensions that have more than one settable property, or if some properties are optional. BecauseTemplateBinding has only one settable property, which is required, this verbose usage is not typical.

In the WPF XAML processor implementation, the handling for this markup extension is defined by the TemplateBindingExtension class.

TemplateBinding is a markup extension. Markup extensions are typically implemented when there is a requirement to escape attribute values to be other than literal values or handler names, and the requirement is more global than just putting type converters on certain types or properties. All markup extensions in XAML use the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes that a markup extension must process the attribute. For more information, see Markup Extensions and WPF XAML.



ThemeDictionary Markup Extension


Provides a way for custom control authors or applications that integrate third-party controls to load theme-specific resource dictionaries to use in styling the control.

XAML Attribute Usage

<object property="{ThemeDictionary assemblyUri}" .../>

XAML Object Element Usage

<object>
  <object.property>
    <ThemeDictionary AssemblyName="assemblyUri"/>
  <object.property>
<object>

XAML Values

assemblyUri

The uniform resource identifier (URI) of the assembly that contains theme information. Typically, this is a pack URI that references an assembly in the larger package. Assembly resources and pack URIs simplify deployment issues. For more information see Pack URIs in WPF.

Remarks

This extension is intended to fill only one specific property value: a value for ResourceDictionary.Source.

By using this extension, you can specify a single resources-only assembly that contains some styles to use only when the Windows Aero theme is applied to the user's system, other styles when Luna theme is active, and so on. By using this extension, the contents of a control-specific resource dictionary can be automatically invalidated and reloaded to be specific for another theme when required.

The assemblyUri string (AssemblyName property value) forms the basis of a naming convention that identifies which dictionary applies for a particular theme. The ProvideValue logic for ThemeDictionary completes the convention by generating a uniform resource identifier (URI) that points to a particular theme dictionary variant, as contained within a precompiled resource assembly. Describing this convention, or theme interactions with general control styling and page/application level styling as a concept, is not covered fully here. The basic scenario for using ThemeDictionary is to specify theSource property of a ResourceDictionary declared at the application level. When you provide a URI for the assembly through a ThemeDictionaryextension rather than as a direct URI, the extension logic will provide invalidation logic that applies whenever the system theme changes.

Attribute syntax is the most common syntax used with this markup extension. The string token provided after the ThemeDictionary identifier string is assigned as the AssemblyName value of the underlying ThemeDictionaryExtension extension class.

ThemeDictionary may also be used in object element syntax. In this case, specifying the value of the AssemblyName property is required.

ThemeDictionary can also be used in a verbose attribute usage that specifies the Member property as a property=value pair:

<object property="{ThemeDictionary AssemblyName=assemblyUri}" .../>

The verbose usage is often useful for extensions that have more than one settable property, or if some properties are optional. BecauseThemeDictionary has only one settable property, which is required, this verbose usage is not typical.

In the WPF XAML processor implementation, the handling for this markup extension is defined by the ThemeDictionaryExtension class.

ThemeDictionary is a markup extension. Markup extensions are typically implemented when there is a requirement to escape attribute values to be other than literal values or handler names, and the requirement is more global than just putting type converters on certain types or properties. All markup extensions in XAML use the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes that a markup extension must process the attribute. For more information, see Markup Extensions and WPF XAML.



PropertyPath XAML Syntax


The PropertyPath object supports a complex inline XAML syntax for setting various properties that take the PropertyPath type as their value. This topic documents the PropertyPath syntax as applied to binding and animation syntaxes.

Where PropertyPath Is Used

PropertyPath is a common object that is used in several Windows Presentation Foundation (WPF) features. Despite using the common PropertyPath to convey property path information, the usages for each feature area where PropertyPath is used as a type vary. Therefore, it is more practical to document the syntaxes on a per-feature basis.

Primarily, WPF uses PropertyPath to describe object-model paths for traversing the properties of an object data source, and to describe the target path for targeted animations.

Some style and template properties such as Setter.Property take a qualified property name that superficially resembles a PropertyPath. But this is not a true PropertyPath; instead it is a qualified owner.property string format usage that is enabled by the WPF XAML processor in combination with the type converter for DependencyProperty.

PropertyPath for Objects in Data Binding

Data binding is a WPF feature whereby you can bind to the target value of any dependency property. However, the source of such a data binding need not be a dependency property; it can be any property type that is recognized by the applicable data provider. Property paths are particularly used for the ObjectDataProvider, which is used for obtaining binding sources from common language runtime (CLR) objects and their properties.

Note that data binding to XML does not use PropertyPath, because it does not use Path in the Binding. Instead, you use XPath and specify valid XPath syntax into the XML Document Object Model (DOM) of the data. XPath is also specified as a string, but is not documented here; see How to: Bind to XML Data Using an XMLDataProvider and XPath Queries.

A key to understanding property paths in data binding is that you can target the binding to an individual property value, or you can instead bind to target properties that take lists or collections. If you are binding collections, for instance binding a ListBox that will expand depending on how many data items are in the collection, then your property path should reference the collection object, not individual collection items. The data binding engine will match the collection used as the data source to the type of the binding target automatically, resulting in behavior such as populating a ListBox with an items array.

Single Property on the Immediate Object as Data Context

<Binding Path="propertyName" .../>

propertyName must resolve to be the name of a property that is in the current DataContext for a Path usage. If your binding updates the source, that property must be read/write and the source object must be mutable.

Single Indexer on the Immediate Object as Data Context

<Binding Path="[key]" .../>

key must be either the typed index to a dictionary or hash table, or the integer index of an array. Also, the value of the key must be a type that is directly bindable to the property where it is applied. For instance, a hash table that contains string keys and string values can be used this way to bind to Text for a TextBox. Or, if the key points to a collection or subindex, you could use this syntax to bind to a target collection property. Otherwise, you need to reference a specific property, through a syntax such as <Binding Path="[key].propertyName" .../>.

You can specify the type of the index if necessary. For details on this aspect of an indexed property path, see Binding.Path.

Multiple Property (Indirect Property Targeting)

<Binding Path="propertyName.propertyName2" .../>

propertyName must resolve to be the name of a property that is the current DataContext. The path properties propertyName and propertyName2 can be any properties that exist in a relationship, where propertyName2 is a property that exists on the type that is the value of propertyName.

Single Property, Attached or Otherwise Type-Qualified

<object property="(ownerType.propertyName)" .../>

The parentheses indicate that this property in a PropertyPath should be constructed using a partial qualification. It can use an XML namespace to find the type with an appropriate mapping. The ownerType searches types that a XAML processor has access to, through the XmlnsDefinitionAttributedeclarations in each assembly. Most applications have the default XML namespace mapped to the http://schemas.microsoft.com/winfx/2006/xaml/presentation namespace, so a prefix is usually only necessary for custom types or types otherwise outside that namespace. propertyName must resolve to be the name of a property existing on the ownerType. This syntax is generally used for one of the following cases:

  • The path is specified in XAML that is in a style or template that does not have a specified Target Type. A qualified usage is generally not valid for cases other than this, because in non-style, non-template cases, the property exists on an instance, not a type.

  • The property is an attached property.

  • You are binding to a static property.

For use as storyboard target, the property specified as propertyName must be a DependencyProperty.

Source Traversal (Binding to Hierarchies of Collections)

<object Path="propertyName/propertyNameX" .../>

The / in this syntax is used to navigate within a hierarchical data source object, and multiple steps into the hierarchy with successive / characters are supported. The source traversal accounts for the current record pointer position, which is determined by synchronizing the data with the UI of its view. For details on binding with hierarchical data source objects, and the concept of current record pointer in data binding, see How to: Use the Master-Detail Pattern with Hierarchical Data or Data Binding Overview.

System_CAPS_noteNote

Superficially, this syntax resembles XPath. A true XPath expression for binding to an XML data source is not used as a Path value and should instead be used for the mutually exclusive XPath property.

Collection Views

To reference a named collection view, prefix the collection view name with the hash character (#).

Current Record Pointer

To reference the current record pointer for a collection view or master detail data binding scenario, start the path string with a forward slash (/). Any path past the forward slash is traversed starting from the current record pointer.

Multiple Indexers

<object Path="[index1,index2...]" .../>
or
<object Path="propertyName[index,index2...]" .../>

If a given object supports multiple indexers, those indexers can be specified in order, similar to an array referencing syntax. The object in question can be either the current context or the value of a property that contains a multiple index object.

By default, the indexer values are typed by using the characteristics of the underlying object. You can specify the type of the index if necessary. For details on typing the indexers, see Binding.Path.

Mixing Syntaxes

Each of the syntaxes shown above can be interspersed. For instance, the following is an example that creates a property path to the color at a particular x,y of a ColorGrid property that contains a pixel grid array of SolidColorBrush objects:

<Rectangle Fill="{Binding ColorGrid[20,30].SolidColorBrushResult}" .../>

Escapes for Property Path Strings

For certain business objects, you might encounter a case where the property path string requires an escape sequence in order to parse correctly. The need to escape should be rare, because many of these characters have similar naming-interaction issues in languages that would typically be used to define the business object.

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

  • You must 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 ">".

  • You must escape (using backslash \) characters that are special to the WPF XAML parser behavior for processing a markup extension.

    • 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.

System_CAPS_noteNote

Technically, these escapes work for a storyboard property path also, but you are usually traversing object models for existing WPF objects, and escaping should be unnecessary.

PropertyPath for Animation Targets

The target property of an animation must be a dependency property that takes either a Freezable or a primitive type. However, the targeted property on a type and the eventual animated property can exist on different objects. For animations, a property path is used to define the connection between the named animation target object's property and the intended target animation property, by traversing object-property relationships in the property values.

General Object-Property Considerations for Animations

For more information on animation concepts in general, see Storyboards Overview and Animation Overview.

The value type or the property being animated must be either a Freezable type or a primitive. The property that starts the path must resolve to be the name of a dependency property that exists on the specified TargetName type.

In order to support cloning for animating a Freezable that is already frozen, the object specified by TargetName must be a FrameworkElement orFrameworkContentElement derived class.

Single Property on the Target Object

<animation Storyboard.TargetProperty="propertyName" .../>

propertyName must resolve to be the name of a dependency property that exists on the specified TargetName type.

Indirect Property Targeting

<animation Storyboard.TargetProperty="propertyName.propertyName2" .../>

propertyName must be a property that is either a Freezable value type or a primitive, which exists on the specified TargetName type.

propertyName2 must be the name of a dependency property that exists on the object that is the value of propertyName. In other words,propertyName2 must exist as a dependency property on the type that is the propertyName PropertyType.

Indirect targeting of animations is necessary because of applied styles and templates. In order to target an animation, you need a TargetName on a target object, and that name is established by x:Name or Name. Although template and style elements also can have names, those names are only valid within the namescope of the style and template. (If templates and styles did share namescopes with application markup, names couldn't be unique. The styles and templates are literally shared between instances and would perpetuate duplicate names.) Thus, if the individual properties of an element that you might wish to animate came from a style or template, you need to start with a named element instance that is not from a style template, and then target into the style or template visual tree to arrive at the property you wish to animate.

For instance, the Background property of a Panel is a complete Brush (actually a SolidColorBrush) that came from a theme template. To animate aBrush completely, there would need to be a BrushAnimation (probably one for every Brush type) and there is no such type. To animate a Brush, you instead animate properties of a particular Brush type. You need to get from SolidColorBrush to its Color to apply a ColorAnimation there. The property path for this example would be Background.Color.

Attached Properties

<animation Storyboard.TargetProperty="(ownerType.propertyName)" .../>

The parentheses indicate that this property in a PropertyPath should be constructed using a partial qualification. It can use an XML namespace to find the type. The ownerType searches types that a XAML processor has access to, through the XmlnsDefinitionAttribute declarations in each assembly. Most applications have the default XML namespace mapped to the http://schemas.microsoft.com/winfx/2006/xaml/presentation namespace, so a prefix is usually only necessary for custom types or types otherwise outside that namespace. propertyName must resolve to be the name of a property existing on the ownerType. The property specified as propertyName must be a DependencyProperty. (All WPF attached properties are implemented as dependency properties, so this issue is only of concern for custom attached properties.)

Indexers

<animation Storyboard.TargetProperty="propertyName.propertyName2[index].propertyName3" .../>

Most dependency properties or Freezable types do not support an indexer. Therefore, the only usage for an indexer in an animation path is at an intermediate position between the property that starts the chain on the named target and the eventual animated property. In the provided syntax, that is propertyName2. For instance, an indexer usage might be necessary if the intermediate property is a collection such as TransformGroup, in a property path such as RenderTransform.Children[1].Angle.

PropertyPath in Code

Code usage for PropertyPath, including how to construct a PropertyPath, is documented in the reference topic for PropertyPath.

In general, PropertyPath is designed to use two different constructors, one for the binding usages and simplest animation usages, and one for the complex animation usages. Use the PropertyPath(Object) signature for binding usages, where the object is a string. Use the PropertyPath(Object)signature for one-step animation paths, where the object is a DependencyProperty. Use the PropertyPath(String, Object[]) signature for complex animations. This latter constructor uses a token string for the first parameter and an array of objects that fill positions in the token string to define a property path relationship.



PresentationOptions:Freeze Attribute


Sets the IsFrozen state to true on the containing Freezable element. Default behavior for a Freezable without the PresentationOptions:Freeze attribute specified is that IsFrozen is false at load time, and dependent on general Freezable behavior at runtime.

XAML Attribute Usage

<object
  xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="PresentationOptions">
    <freezableElement PresentationOptions:Freeze="true"/>
</object>

XAML Values

PresentationOptions

An XML namespace prefix, which can be any valid prefix string, per the XML 1.0 specification. The prefix PresentationOptions is used for identification purposes in this documentation.

freezableElement

An element that instantiates any derived class of Freezable.

Remarks

The Freeze attribute is the only attribute or other programming element defined in thehttp://schemas.microsoft.com/winfx/2006/xaml/presentation/options XML namespace. The Freeze attribute exists in this special namespace specifically so that it can be designated as ignorable, using mc:Ignorable Attribute as part of the root element declarations. The reason that Freeze must be able to be ignorable is because not all XAML processor implementations are able to freeze a Freezable at load time; this capability is not part of the XAML specification.

The ability to process the Freeze attribute is specifically built in to the XAML processor that processes XAML for compiled applications. The attribute is not supported by any class, and the attribute syntax is not extensible or modifiable. If you are implementing your own XAML processor you can choose to parallel the freezing behavior of the WPF XAML processor when processing the Freeze attribute on Freezable elements at load time.

Any value for the Freeze attribute other than true (not case sensitive) generates a load time error. (Specifying the Freeze attribute as false is not an error, but that is already the default, so setting to false does nothing).




Markup Compatibility (mc:) Language Features



mc:Ignorable Attribute


Specifies which XML namespace prefixes encountered in a markup file may be ignored by a XAML processor. The mc:Ignorable attribute supports markup compatibility both for custom namespace mapping and for XAML versioning.

XAML Attribute Usage (Single Prefix)

<object
  xmlns:ignorablePrefix="ignorableUri"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="ignorablePrefix"...>
    <ignorablePrefix1:ThisElementCanBeIgnored/>
</object>

XAML Attribute Usage (Two Prefixes)

<object
  xmlns:ignorablePrefix1="ignorableUri"
  xmlns:ignorablePrefix2="ignorableUri2"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="ignorablePrefix1 ignorablePrefix2"...>
    <ignorablePrefix1:ThisElementCanBeIgnored/>
</object>

XAML Values

ignorablePrefix, ignorablePrefix1, etc.

Any valid prefix string, per the XML 1.0 specification.

ignorableUri

Any valid URI for designating a namespace, per the XML 1.0 specification.

ThisElementCanBeIgnored

An element that can be ignored by Extensible Application Markup Language (XAML) processor implementations, if the underlying type cannot be resolved.

Remarks

The mc XML namespace prefix is the recommended prefix convention to use when mapping the XAML compatibility namespace http://schemas.openxmlformats.org/markup-compatibility/2006.

Elements or attributes where the prefix portion of the element name are identified as mc:Ignorable will not raise errors when processed by a XAML processor. If that attribute could not be resolved to an underlying type or programming construct, then that element is ignored. Note however that ignored elements might still generate additional parsing errors for additional element requirements that are side effects of that element not being processed. For instance, a particular element content model might require exactly one child element, but if the specified child element was in anmc:Ignorable prefix, and the specified child element could not be resolved to a type, then the XAML processor might raise an error.

mc:Ignorable only applies to namespace mappings to identifier strings. mc:Ignorable does not apply to namespace mappings into assemblies, which specify a CLR namespace and an assembly (or default to the current executable as the assembly).

If you are implementing a XAML processor, your processor implementation must not raise parsing or processing errors on type resolution for any element or attribute that is qualified by a prefix that is identified as mc:Ignorable. But your processor implementation can still raise exceptions that are a secondary result of an element failing to load or be processed, such as the one-child element example given earlier.

By default, a XAML processor will ignore content within an ignored element. However, you can specify an additional attribute, mc:ProcessContent Attribute, to require continued processing of content within an ignored element by the next available parent element.

Multiple prefixes can be specified in the attribute, using one or more whitespace characters as the separator, for example:mc:Ignorable="ignore1 ignore2".

The http://schemas.openxmlformats.org/markup-compatibility/2006 namespace defines other elements and attributes that are not documented within this area of the software development kit (SDK). For more information, see XML Markup Compatibility Specification.



mc:ProcessContent Attribute


Specifies which XAML elements should still have content processed by relevant parent elements, even if the immediate parent element may be ignored by a XAML processor due to specifying mc:Ignorable Attribute. The mc:ProcessContent attribute supports markup compatibility both for custom namespace mapping and for XAML versioning.

XAML Attribute Usage

<object
  xmlns:ignorablePrefix="ignorableUri"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="ignorablePrefix"...
  mc:ProcessContent="ignorablePrefix:ThisElementCanBeIgnored"
>
    <ignorablePrefix:ThisElementCanBeIgnored>
        [content]
    </ignorablePrefix:ThisElementCanBeIgnored>
</object>

XAML Values

ignorablePrefix

Any valid prefix string, per the XML 1.0 specification.

ignorableUri

Any valid URI for designating a namespace, per the XML 1.0 specification.

ThisElementCanBeIgnored

An element that can be ignored by Extensible Application Markup Language (XAML) processor implementations, if the underlying type cannot be resolved.

[content]

ThisElementCanBeIgnored is marked ignorable. If the processor ignores that element, [content] is processed by object.

Remarks

By default, a XAML processor will ignore content within an ignored element. You can specify a specific element by mc:ProcessContent, and a XAML processor will continue to process the content within the ignored element. This would typically be used if the content is nested within several tags, at least one of which is ignorable and at least one of which is not ignorable.

Multiple prefixes may be specified in the attribute, using a space separator, for example: mc:ProcessContent="ignore:Element1 ignore:Element2".

The http://schemas.openxmlformats.org/markup-compatibility/2006 namespace defines other elements and attributes that are not documented within this area of the software development kit (SDK). For more information, see XML Markup Compatibility Specification.






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

WPF 고급 - 입력 (Input)  (0) 2016.10.15
ObservableCollection<T>, INotifyPropertyChanged Interface  (0) 2016.10.15
WPF - Application Development  (1) 2016.09.08
Data Binding (WPF)  (0) 2016.09.04
Windows Presentation Foundation  (0) 2016.08.26
:
Posted by 지훈2