|
2 | 2 | // The .NET Foundation licenses this file to you under the MIT license.
|
3 | 3 | // See the LICENSE file in the project root for more information.
|
4 | 4 |
|
| 5 | +using System.Globalization; |
5 | 6 | using System.Numerics;
|
6 | 7 | using Windows.UI.Composition;
|
7 | 8 | using Windows.UI.Xaml;
|
@@ -114,6 +115,36 @@ public static void SetOffset(DependencyObject obj, string value)
|
114 | 115 | obj.SetValue(OffsetProperty, value);
|
115 | 116 | }
|
116 | 117 |
|
| 118 | + /// <summary> |
| 119 | + /// Gets the <c>"Translation"</c> property of the underlying <see cref="Visual"/> object for a <see cref="UIElement"/>, in <see cref="string"/> form. |
| 120 | + /// </summary> |
| 121 | + /// <param name="obj">The <see cref="DependencyObject"/> instance.</param> |
| 122 | + /// <returns>The <see cref="string"/> representation of the <c>"Translation"</c> property property.</returns> |
| 123 | + public static string GetTranslation(DependencyObject obj) |
| 124 | + { |
| 125 | + if (!DesignTimeHelpers.IsRunningInLegacyDesignerMode && obj is UIElement element) |
| 126 | + { |
| 127 | + return GetTranslationForElement(element); |
| 128 | + } |
| 129 | + |
| 130 | + return (string)obj.GetValue(TranslationProperty); |
| 131 | + } |
| 132 | + |
| 133 | + /// <summary> |
| 134 | + /// Sets the <c>"Translation"</c> property of the underlying <see cref="Visual"/> object for a <see cref="UIElement"/>, in <see cref="string"/> form. |
| 135 | + /// </summary> |
| 136 | + /// <param name="obj">The <see cref="DependencyObject"/> instance.</param> |
| 137 | + /// <param name="value">The <see cref="string"/> representation of the <c>"Translation"</c> property property to be set.</param> |
| 138 | + public static void SetTranslation(DependencyObject obj, string value) |
| 139 | + { |
| 140 | + if (!DesignTimeHelpers.IsRunningInLegacyDesignerMode && obj is UIElement element) |
| 141 | + { |
| 142 | + SetTranslationForElement(value, element); |
| 143 | + } |
| 144 | + |
| 145 | + obj.SetValue(TranslationProperty, value); |
| 146 | + } |
| 147 | + |
117 | 148 | /// <summary>
|
118 | 149 | /// Gets the <see cref="Visual.Opacity"/> of a UIElement
|
119 | 150 | /// </summary>
|
@@ -334,6 +365,12 @@ public static void SetNormalizedCenterPoint(DependencyObject obj, string value)
|
334 | 365 | public static readonly DependencyProperty OffsetProperty =
|
335 | 366 | DependencyProperty.RegisterAttached("Offset", typeof(string), typeof(VisualExtensions), new PropertyMetadata(null, OnOffsetChanged));
|
336 | 367 |
|
| 368 | + /// <summary> |
| 369 | + /// Identifies the Translation attached property. |
| 370 | + /// </summary> |
| 371 | + public static readonly DependencyProperty TranslationProperty = |
| 372 | + DependencyProperty.RegisterAttached("Translation", typeof(string), typeof(VisualExtensions), new PropertyMetadata(null, OnTranslationChanged)); |
| 373 | + |
337 | 374 | /// <summary>
|
338 | 375 | /// Identifies the Opacity attached property.
|
339 | 376 | /// </summary>
|
@@ -400,6 +437,14 @@ private static void OnOffsetChanged(DependencyObject d, DependencyPropertyChange
|
400 | 437 | }
|
401 | 438 | }
|
402 | 439 |
|
| 440 | + private static void OnTranslationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
| 441 | + { |
| 442 | + if (e.NewValue is string str) |
| 443 | + { |
| 444 | + SetTranslation(d, str); |
| 445 | + } |
| 446 | + } |
| 447 | + |
403 | 448 | private static void OnOpacityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
404 | 449 | {
|
405 | 450 | if (e.NewValue is double dbl)
|
@@ -503,6 +548,37 @@ private static void SetOffsetForElement(string value, UIElement element)
|
503 | 548 | visual.Offset = value.ToVector3();
|
504 | 549 | }
|
505 | 550 |
|
| 551 | + private static string GetTranslationForElement(UIElement element) |
| 552 | + { |
| 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 | + }; |
| 564 | + } |
| 565 | + |
| 566 | + private static void SetTranslationForElement(string value, UIElement element) |
| 567 | + { |
| 568 | + ElementCompositionPreview.SetIsTranslationEnabled(element, true); |
| 569 | + |
| 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()); |
| 580 | + } |
| 581 | + |
506 | 582 | private static double GetOpacityForElement(UIElement element)
|
507 | 583 | {
|
508 | 584 | var visual = GetVisual(element);
|
|
0 commit comments