Skip to content

Commit 29837fd

Browse files
committed
[FIX] ClearIcon's ContentView needs to be initially visible in order to receive Binding updates
1 parent bcc70c2 commit 29837fd

File tree

3 files changed

+40
-18
lines changed

3 files changed

+40
-18
lines changed

src/UraniumUI.Material/Controls/TextField.BindableProperties.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public partial class TextField
1616
typeof(TextField),
1717
string.Empty,
1818
BindingMode.TwoWay,
19-
propertyChanging: (bindable, oldValue, newValue) =>
19+
propertyChanged: (bindable, oldValue, newValue) =>
2020
{
2121
(bindable as TextField).UpdateClearIconState();
2222
});

src/UraniumUI.Material/Controls/TextField.cs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.Extensions.Logging;
2+
using Microsoft.Maui.Controls;
23
using Plainer.Maui.Controls;
34
using System.Windows.Input;
45
using UraniumUI.Converters;
@@ -167,7 +168,7 @@ protected virtual View CreateIconClear()
167168
{
168169
VerticalOptions = LayoutOptions.Center,
169170
HorizontalOptions = LayoutOptions.End,
170-
IsVisible = false,
171+
IsVisible = true, // this is important; having initial state of false will have SetBinding have no effect, since it will not receive input events
171172
Padding = new Thickness(5, 0),
172173
Margin = new Thickness(0, 0, 5, 0),
173174
TappedCommand = new Command(OnClearTapped),
@@ -178,12 +179,14 @@ protected virtual View CreateIconClear()
178179
Fill = ColorResource.GetColor("OnBackground", "OnBackgroundDark", Colors.DarkGray).WithAlpha(.5f),
179180
}
180181
};
182+
181183
contentView.SetId("ClearIcon");
182184
contentView.SetBinding(StatefulContentView.IsFocusableProperty, new Binding(nameof(DisallowClearButtonFocus), source: this));
183-
contentView.SetBinding(StatefulContentView.IsVisibleProperty, new Binding(nameof(Text), converter: UraniumConverters.StringIsNotNullOrEmptyConverter, source: this));
185+
contentView.SetBinding(IsVisibleProperty, new Binding(nameof(Text), converter: UraniumConverters.StringIsNotNullOrEmptyConverter, source: this));
186+
184187
return contentView;
185188
}
186-
189+
187190
/// <summary>
188191
/// Input has be be already focused when this method is called.
189192
/// </summary>

test/UraniumUI.Material.Tests/Controls/TextField_Test.cs

+33-14
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using System.Windows.Input;
55
using UraniumUI.Material.Controls;
66
using UraniumUI.Tests.Core;
7+
using UraniumUI.ViewExtensions;
8+
using UraniumUI.Views;
79

810
namespace UraniumUI.Material.Tests.Controls;
911
public class TextField_Test
@@ -40,23 +42,23 @@ public void Text_Binding_FromSource()
4042
control.Text.ShouldBe(viewModel.Text);
4143
}
4244

43-
[Fact]
44-
public void Text_Binding_RaisesPropertyChangedEvent_ExactlyOnce()
45-
{
46-
var control = AnimationReadyHandler.Prepare(new TextField());
47-
var viewModel = new TestViewModel { Text = "Text Initial Value" };
48-
control.BindingContext = viewModel;
49-
control.SetBinding(TextField.TextProperty, new Binding(nameof(TestViewModel.Text)));
45+
[Fact]
46+
public void Text_Binding_RaisesPropertyChangedEvent_ExactlyOnce()
47+
{
48+
var control = AnimationReadyHandler.Prepare(new TextField());
49+
var viewModel = new TestViewModel { Text = "Text Initial Value" };
50+
control.BindingContext = viewModel;
51+
control.SetBinding(TextField.TextProperty, new Binding(nameof(TestViewModel.Text)));
5052

51-
var monitoredSubject = control.Monitor();
52-
// Act
53-
viewModel.Text = "Changed Value";
53+
var monitoredSubject = control.Monitor();
54+
// Act
55+
viewModel.Text = "Changed Value";
5456

55-
// Assert
56-
monitoredSubject.Should().RaisePropertyChangeFor(x => x.Text).ShouldHaveSingleItem();
57-
}
57+
// Assert
58+
monitoredSubject.Should().RaisePropertyChangeFor(x => x.Text).ShouldHaveSingleItem();
59+
}
5860

59-
[Fact]
61+
[Fact]
6062
public void Text_Binding_ToSource()
6163
{
6264
var control = AnimationReadyHandler.Prepare(new TextField());
@@ -91,6 +93,23 @@ public void TextProperty_Parent_ShouldTwoWayBind_Child()
9193
control.Text.ShouldBe(control.EntryView.Text);
9294
}
9395

96+
[Fact]
97+
public void TextChanges_ShouldShouldCorrectlyUpdateClearButtonVisibility()
98+
{
99+
var control = AnimationReadyHandler.Prepare(new TextField() { AllowClear = true });
100+
// Currently no easier way provided by TextField/InputField to access this control
101+
var clearIcon = control.FindByViewQueryIdInVisualTreeDescendants<StatefulContentView>("ClearIcon");
102+
103+
// Since we initialized with AllowClear = true
104+
clearIcon.Should().NotBeNull();
105+
// TextField initialized without text -> clear icon should be initially hidden
106+
clearIcon.IsVisible.ShouldBeFalse();
107+
control.Text = "Test";
108+
clearIcon.IsVisible.ShouldBeTrue();
109+
control.Text = "";
110+
clearIcon.IsVisible.ShouldBeFalse();
111+
}
112+
94113
[Fact]
95114
public void SelectionLength_ShouldBeSent_ToViewModel()
96115
{

0 commit comments

Comments
 (0)