Skip to content

Commit 3808c00

Browse files
committed
fix: [TextBlock] Prevent Text value overriding when it isn't necessary
- Once the Inlines collection is initialized, changes to Text via binding no longer causes the binding to be overridden. - The inlines text cached on the TextBlock is no longer updated when non-Text properties change on Runs. - WASM Inlines collections now properly invalidate their owners when changed.
1 parent dcb83be commit 3808c00

File tree

6 files changed

+67
-30
lines changed

6 files changed

+67
-30
lines changed

src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.cs

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public partial class TextBlock : DependencyObject
3636
private string _inlinesText; // Text derived from the content of Inlines
3737
private readonly SerialDisposable _foregroundChanged = new SerialDisposable();
3838

39+
private bool _skipInlinesChangedTextSetter;
3940

4041
#if !UNO_REFERENCE_API
4142
public TextBlock()
@@ -87,15 +88,29 @@ public InlineCollection Inlines
8788
}
8889
}
8990

90-
internal void InvalidateInlines() => OnInlinesChanged();
91-
92-
private void OnInlinesChanged()
93-
{
94-
Text = _inlinesText = string.Concat(Inlines.Select(InlineExtensions.GetText));
95-
UpdateHyperlinks();
91+
internal void InvalidateInlines(bool updateText)
92+
{
93+
if (updateText)
94+
{
95+
if (Inlines.Count == 1 && Inlines[0] is Run run)
96+
{
97+
_inlinesText = run.Text;
98+
}
99+
else
100+
{
101+
_inlinesText = string.Concat(Inlines.Select(InlineExtensions.GetText));
102+
}
103+
104+
if (!_skipInlinesChangedTextSetter)
105+
{
106+
Text = _inlinesText;
107+
}
108+
109+
UpdateHyperlinks();
110+
}
96111

97112
OnInlinesChangedPartial();
98-
InvalidateTextBlock();
113+
InvalidateTextBlock();
99114
}
100115

101116
partial void OnInlinesChangedPartial();
@@ -700,16 +715,21 @@ private void UpdateInlines(string text)
700715
}
701716

702717
if (ReadLocalValue(TextProperty) is UnsetValue)
703-
{
704-
Inlines.Clear();
718+
{
719+
_skipInlinesChangedTextSetter = true;
720+
Inlines.Clear();
721+
_skipInlinesChangedTextSetter = false;
705722
ClearTextPartial();
706723
}
707724
else if (text != _inlinesText)
708-
{
709-
// Inlines must be updated
725+
{
726+
// Inlines must be updated
727+
_skipInlinesChangedTextSetter = true;
710728
Inlines.Clear();
711-
ClearTextPartial();
712-
Inlines.Add(new Run { Text = text });
729+
ClearTextPartial();
730+
_skipInlinesChangedTextSetter = true;
731+
Inlines.Add(new Run { Text = text });
732+
_skipInlinesChangedTextSetter = false;
713733
}
714734
}
715735

src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.skia.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public TextBlock()
3030

3131
private int GetCharacterIndexAtPoint(Point point)
3232
{
33-
throw new NotSupportedException();
33+
return -1; // Not supported yet
3434
}
3535

3636
protected override Size MeasureOverride(Size availableSize)

src/Uno.UI/UI/Xaml/Documents/Inline.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ namespace Windows.UI.Xaml.Documents
88
{
99
public abstract partial class Inline : TextElement
1010
{
11-
internal void InvalidateInlines()
11+
internal void InvalidateInlines(bool updateText)
1212
{
1313
#if !NET461
1414
switch (this.GetParent())
1515
{
1616
case Span span:
17-
span.InvalidateInlines();
17+
span.InvalidateInlines(updateText);
1818
break;
1919
case TextBlock textBlock:
20-
textBlock.InvalidateInlines();
20+
textBlock.InvalidateInlines(updateText);
2121
break;
2222
default:
2323
break;

src/Uno.UI/UI/Xaml/Documents/InlineCollection.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ private void OnCollectionChanged()
2424
switch (_collection.GetParent())
2525
{
2626
case TextBlock textBlock:
27-
textBlock.InvalidateInlines();
27+
textBlock.InvalidateInlines(true);
2828
break;
2929
case Inline inline:
30-
inline.InvalidateInlines();
30+
inline.InvalidateInlines(true);
3131
break;
3232
default:
3333
break;

src/Uno.UI/UI/Xaml/Documents/InlineCollection.wasm.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Collections.Specialized;
45
using System.Linq;
56
using Windows.UI.Xaml.Controls;
67

@@ -13,8 +14,24 @@ partial class InlineCollection : IList<Inline>, IEnumerable<Inline>
1314
internal InlineCollection(UIElement containerElement)
1415
{
1516
_collection = new UIElementCollection(containerElement);
16-
}
17-
17+
_collection.CollectionChanged += OnCollectionChanged;
18+
}
19+
20+
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
21+
{
22+
switch (_collection.Owner)
23+
{
24+
case TextBlock textBlock:
25+
textBlock.InvalidateInlines(true);
26+
break;
27+
case Inline inline:
28+
inline.InvalidateInlines(true);
29+
break;
30+
default:
31+
break;
32+
}
33+
}
34+
1835
/// <inheritdoc />
1936
public IEnumerator<Inline> GetEnumerator() => _collection.OfType<Inline>().GetEnumerator();
2037

src/Uno.UI/UI/Xaml/Documents/Run.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public string Text
3333
public void OnTextChanged()
3434
{
3535
OnTextChangedPartial();
36-
InvalidateInlines();
36+
InvalidateInlines(true);
3737
InvalidateSegmentsPartial();
3838
}
3939

@@ -44,54 +44,54 @@ public void OnTextChanged()
4444
protected override void OnForegroundChanged()
4545
{
4646
base.OnForegroundChanged();
47-
InvalidateInlines();
47+
InvalidateInlines(false);
4848
}
4949

5050
protected override void OnFontFamilyChanged()
5151
{
5252
base.OnFontFamilyChanged();
53-
InvalidateInlines();
53+
InvalidateInlines(false);
5454
InvalidateSegmentsPartial();
5555
}
5656

5757
protected override void OnFontSizeChanged()
5858
{
5959
base.OnFontSizeChanged();
60-
InvalidateInlines();
60+
InvalidateInlines(false);
6161
InvalidateSegmentsPartial();
6262
}
6363

6464
protected override void OnFontStyleChanged()
6565
{
6666
base.OnFontStyleChanged();
67-
InvalidateInlines();
67+
InvalidateInlines(false);
6868
InvalidateSegmentsPartial();
6969
}
7070

7171
protected override void OnFontWeightChanged()
7272
{
7373
base.OnFontWeightChanged();
74-
InvalidateInlines();
74+
InvalidateInlines(false);
7575
InvalidateSegmentsPartial();
7676
}
7777

7878
protected override void OnBaseLineAlignmentChanged()
7979
{
8080
base.OnBaseLineAlignmentChanged();
81-
InvalidateInlines();
81+
InvalidateInlines(false);
8282
}
8383

8484
protected override void OnCharacterSpacingChanged()
8585
{
8686
base.OnCharacterSpacingChanged();
87-
InvalidateInlines();
87+
InvalidateInlines(false);
8888
InvalidateSegmentsPartial();
8989
}
9090

9191
protected override void OnTextDecorationsChanged()
9292
{
9393
base.OnTextDecorationsChanged();
94-
InvalidateInlines();
94+
InvalidateInlines(false);
9595
}
9696

9797
partial void InvalidateSegmentsPartial();

0 commit comments

Comments
 (0)