22// The .NET Foundation licenses this file to you under the MIT license.
33// See the LICENSE file in the project root for more information.
44
5+ using System . Globalization ;
56using System . Numerics ;
67using Windows . UI . Composition ;
78using Windows . UI . Xaml ;
@@ -115,10 +116,10 @@ public static void SetOffset(DependencyObject obj, string value)
115116 }
116117
117118 /// <summary>
118- /// Gets the <see cref="Visual.TransformMatrix"/>. <see cref="Matrix4x4.Translation "/> property of a <see cref="UIElement"/> in a <see cref="string"/> form.
119+ /// Gets the <c>"Translation"</c> property of the underlying <see cref="Visual "/> object for a <see cref="UIElement"/>, in <see cref="string"/> form.
119120 /// </summary>
120121 /// <param name="obj">The <see cref="DependencyObject"/> instance.</param>
121- /// <returns>A <see cref="Vector3"/> <see cref=" string"/> representation of the <see cref="Visual.TransformMatrix"/>.<see cref="Matrix4x4. Translation"/> property.</returns>
122+ /// <returns>The <see cref="string"/> representation of the <c>" Translation"</c> property property.</returns>
122123 public static string GetTranslation ( DependencyObject obj )
123124 {
124125 if ( ! DesignTimeHelpers . IsRunningInLegacyDesignerMode && obj is UIElement element )
@@ -130,10 +131,10 @@ public static string GetTranslation(DependencyObject obj)
130131 }
131132
132133 /// <summary>
133- /// Sets the <see cref="Visual.TransformMatrix"/>. <see cref="Matrix4x4.Translation "/> property of a <see cref="UIElement"/> in a <see cref="string"/> form.
134+ /// Sets the <c>"Translation"</c> property of the underlying <see cref="Visual "/> object for a <see cref="UIElement"/>, in <see cref="string"/> form.
134135 /// </summary>
135136 /// <param name="obj">The <see cref="DependencyObject"/> instance.</param>
136- /// <param name="value">The <see cref="string"/> representation of the <see cref="Vector3"/> to be set.</param>
137+ /// <param name="value">The <see cref="string"/> representation of the <c>"Translation"</c> property property to be set.</param>
137138 public static void SetTranslation ( DependencyObject obj , string value )
138139 {
139140 if ( ! DesignTimeHelpers . IsRunningInLegacyDesignerMode && obj is UIElement element )
@@ -549,19 +550,33 @@ private static void SetOffsetForElement(string value, UIElement element)
549550
550551 private static string GetTranslationForElement ( UIElement element )
551552 {
552- return GetVisual ( element ) . TransformMatrix . Translation . ToString ( ) ;
553+ CompositionGetValueStatus result = GetVisual ( element ) . Properties . TryGetVector3 ( "Translation" , out Vector3 translation ) ;
554+
555+ return result switch
556+ {
557+ // The ("G", CultureInfo.InvariantCulture) combination produces a string with the default numeric
558+ // formatting style, and using ',' as component separator, so that the resulting text can safely
559+ // be parsed back if needed with the StringExtensions.ToVector3(string) extension, which uses
560+ // the invariant culture mode by default so that the syntax will always match that from XAML.
561+ CompositionGetValueStatus . Succeeded => translation . ToString ( "G" , CultureInfo . InvariantCulture ) ,
562+ _ => "<0, 0, 0>"
563+ } ;
553564 }
554565
555566 private static void SetTranslationForElement ( string value , UIElement element )
556567 {
557568 ElementCompositionPreview . SetIsTranslationEnabled ( element , true ) ;
558569
559- Visual visual = GetVisual ( element ) ;
560- Matrix4x4 transform = visual . TransformMatrix ;
561-
562- transform . Translation = value . ToVector3 ( ) ;
563-
564- visual . TransformMatrix = transform ;
570+ // The "Translation" attached property refers to the "hidden" property that is enabled
571+ // through "ElementCompositionPreview.SetIsTranslationEnabled". The value for this property
572+ // is not available directly on the Visual class and can only be accessed through its property
573+ // set. Note that this "Translation" value is not the same as Visual.TransformMatrix.Translation.
574+ // In fact, the latter doesn't require to be explicitly enabled and is actually combined with
575+ // this at runtime (ie. the whole transform matrix is combined with the additional translation
576+ // from the "Translation" property, if any), and the two can be set and animated independently.
577+ // In this case we're just interested in the "Translation" property, which is more commonly used
578+ // as it can also be animated directly with a Vector3 animation instead of a Matrix4x4 one.
579+ GetVisual ( element ) . Properties . InsertVector3 ( "Translation" , value . ToVector3 ( ) ) ;
565580 }
566581
567582 private static double GetOpacityForElement ( UIElement element )
0 commit comments