Skip to content

Commit 19e6680

Browse files
committed
feat(WPF): Add support for visual properties on WPF TextBox, clear button
- Some of the visual properties of TextBox now properly flow to WPF TextBox - Clear button now works right
1 parent 3c61d3c commit 19e6680

16 files changed

+128
-47
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.Windows.Controls;
2+
using WpfFrameworkPropertyMetadata = System.Windows.FrameworkPropertyMetadata;
3+
4+
namespace Uno.UI.Runtime.Skia.WPF.Controls
5+
{
6+
public class WpfTextViewTextBox : TextBox
7+
{
8+
static WpfTextViewTextBox()
9+
{
10+
DefaultStyleKeyProperty.OverrideMetadata(typeof(WpfTextViewTextBox),
11+
new WpfFrameworkPropertyMetadata(typeof(WpfTextViewTextBox)));
12+
}
13+
14+
public override void OnApplyTemplate() => base.OnApplyTemplate();
15+
}
16+
}

src/Uno.UI.Runtime.Skia.Wpf/WPF/Extensions/CursorExtensions.cs renamed to src/Uno.UI.Runtime.Skia.Wpf/Extensions/CursorExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ internal static class CursorExtensions
77
{
88
public static CoreCursor ToCoreCursor(this Cursor cursor)
99
{
10-
CoreCursorType cursorType = CoreCursorType.Arrow;
10+
var cursorType = CoreCursorType.Arrow;
1111
if (cursor == Cursors.Wait)
1212
{
1313
cursorType = CoreCursorType.Wait;

src/Uno.UI.Runtime.Skia.Wpf/WPF/Extensions/UI/Xaml/Controls/TextBoxViewExtension.cs renamed to src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/TextBoxViewExtension.cs

Lines changed: 67 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
#nullable enable
22

33
using System;
4+
using System.Windows;
5+
using System.Windows.Media;
46
using Windows.UI.Xaml.Controls;
7+
using Uno.UI.Runtime.Skia.WPF.Controls;
58
using Uno.UI.Skia.Platform;
69
using Uno.UI.Xaml.Controls.Extensions;
7-
using Windows.Foundation;
10+
using Point = Windows.Foundation.Point;
11+
using SolidColorBrush = Windows.UI.Xaml.Media.SolidColorBrush;
812
using WpfCanvas = System.Windows.Controls.Canvas;
913
using WpfTextBox = System.Windows.Controls.TextBox;
1014

@@ -14,7 +18,7 @@ internal class TextBoxViewExtension : ITextBoxViewExtension
1418
{
1519
private readonly TextBoxView _owner;
1620
private ContentControl? _contentElement;
17-
private WpfTextBox? _currentInputWidget;
21+
private WpfTextViewTextBox? _currentInputWidget;
1822

1923
public TextBoxViewExtension(TextBoxView owner)
2024
{
@@ -38,40 +42,28 @@ public void StartEntry()
3842
EnsureWidgetForAcceptsReturn();
3943
textInputLayer.Children.Add(_currentInputWidget!);
4044

41-
_contentElement.SizeChanged += _contentElement_SizeChanged;
42-
_contentElement.LayoutUpdated += _contentElement_LayoutUpdated;
45+
_contentElement.SizeChanged += ContentElementSizeChanged;
46+
_contentElement.LayoutUpdated += ContentElementLayoutUpdated;
4347
UpdateNativeView();
44-
SetInputText(textBox.Text);
48+
SetTextNative(textBox.Text);
4549

4650
UpdateSize();
4751
UpdatePosition();
4852

4953
_currentInputWidget!.Focus();
5054
}
5155

52-
private void _contentElement_LayoutUpdated(object sender, object e)
53-
{
54-
UpdateSize();
55-
UpdatePosition();
56-
}
57-
58-
private void _contentElement_SizeChanged(object sender, Windows.UI.Xaml.SizeChangedEventArgs args)
59-
{
60-
UpdateSize();
61-
UpdatePosition();
62-
}
63-
6456
public void EndEntry()
6557
{
6658
if (GetInputText() is { } inputText)
6759
{
68-
_owner.UpdateText(inputText);
60+
_owner.UpdateTextFromNative(inputText);
6961
}
7062

7163
if (_contentElement != null)
7264
{
73-
_contentElement.SizeChanged -= _contentElement_SizeChanged;
74-
_contentElement.LayoutUpdated -= _contentElement_LayoutUpdated;
65+
_contentElement.SizeChanged -= ContentElementSizeChanged;
66+
_contentElement.LayoutUpdated -= ContentElementLayoutUpdated;
7567
}
7668

7769
var textInputLayer = GetWindowTextInputLayer();
@@ -95,26 +87,20 @@ public void UpdateNativeView()
9587

9688
EnsureWidgetForAcceptsReturn();
9789

90+
//_currentInputWidget.Margin = new Thickness(
91+
// textBox.ContentElement.Margin.Left,
92+
// textBox.ContentElement.Margin.Top,
93+
// textBox.ContentElement.Margin.Right,
94+
// textBox.ContentElement.Margin.Bottom);
9895
_currentInputWidget.FontSize = textBox.FontSize;
99-
}
100-
101-
private void EnsureWidgetForAcceptsReturn()
102-
{
103-
_currentInputWidget ??= CreateInputControl();
104-
}
105-
106-
private WpfTextBox CreateInputControl()
107-
{
108-
return new WpfTextBox();
109-
}
110-
111-
private string? GetInputText() => _currentInputWidget?.Text;
112-
113-
private void SetInputText(string text)
114-
{
115-
if (_currentInputWidget != null)
96+
_currentInputWidget.FontWeight = FontWeight.FromOpenTypeWeight(textBox.FontWeight.Weight);
97+
_currentInputWidget.AcceptsReturn = textBox.AcceptsReturn;
98+
_currentInputWidget.TextWrapping = textBox.AcceptsReturn ? TextWrapping.Wrap : TextWrapping.NoWrap;
99+
_currentInputWidget.MaxLength = textBox.MaxLength;
100+
if (textBox.Foreground is SolidColorBrush colorBrush)
116101
{
117-
_currentInputWidget.Text = text;
102+
var unoColor = colorBrush.Color;
103+
_currentInputWidget.Foreground = new System.Windows.Media.SolidColorBrush(Color.FromArgb(unoColor.A, unoColor.R, unoColor.G, unoColor.B));
118104
}
119105
}
120106

@@ -149,5 +135,48 @@ public void UpdatePosition()
149135
WpfCanvas.SetTop(_currentInputWidget, point.Y);
150136
}
151137
}
138+
139+
public void SetTextNative(string text)
140+
{
141+
if (_currentInputWidget != null)
142+
{
143+
_currentInputWidget.Text = text;
144+
}
145+
}
146+
147+
private void EnsureWidgetForAcceptsReturn()
148+
{
149+
_currentInputWidget ??= CreateInputControl();
150+
}
151+
152+
private WpfTextViewTextBox CreateInputControl()
153+
{
154+
var textView = new WpfTextViewTextBox();
155+
textView.TextChanged += WpfTextViewTextChanged;
156+
return textView;
157+
}
158+
159+
private void WpfTextViewTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
160+
{
161+
if (_currentInputWidget != null)
162+
{
163+
_owner.UpdateTextFromNative(_currentInputWidget.Text);
164+
}
165+
}
166+
167+
private string? GetInputText() => _currentInputWidget?.Text;
168+
169+
private void ContentElementLayoutUpdated(object? sender, object e)
170+
{
171+
UpdateSize();
172+
UpdatePosition();
173+
}
174+
175+
private void ContentElementSizeChanged(object sender, Windows.UI.Xaml.SizeChangedEventArgs args)
176+
{
177+
UpdateSize();
178+
UpdatePosition();
179+
}
180+
152181
}
153182
}

src/Uno.UI.Runtime.Skia.Wpf/Themes/Generic.xaml

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<ResourceDictionary
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4-
xmlns:platform="clr-namespace:Uno.UI.Skia.Platform">
4+
xmlns:platform="clr-namespace:Uno.UI.Skia.Platform"
5+
xmlns:controls="clr-namespace:Uno.UI.Runtime.Skia.WPF.Controls">
56

67
<Style TargetType="{x:Type platform:WpfHost}">
78
<Setter Property="Template">
@@ -17,6 +18,35 @@
1718
</Setter>
1819
</Style>
1920

20-
<Style x:Key="UnoTextBoxViewOverlayStyle" TargetType="TextBox">
21+
<Style TargetType="{x:Type controls:WpfTextViewTextBox}">
22+
<Setter Property="SnapsToDevicePixels" Value="True" />
23+
<Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
24+
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
25+
<Setter Property="MinWidth" Value="0" />
26+
<Setter Property="MinHeight" Value="0" />
27+
<Setter Property="AllowDrop" Value="true" />
28+
<Setter Property="Template">
29+
<Setter.Value>
30+
<ControlTemplate TargetType="{x:Type controls:WpfTextViewTextBox}">
31+
<Border Name="Border" CornerRadius="0" Margin="{TemplateBinding Margin}" Padding="{TemplateBinding Padding}" BorderThickness="0">
32+
<Border.Background>
33+
<SolidColorBrush Color="Transparent" />
34+
</Border.Background>
35+
<Border.BorderBrush>
36+
<SolidColorBrush Color="Transparent" />
37+
</Border.BorderBrush>
38+
<VisualStateManager.VisualStateGroups>
39+
<VisualStateGroup x:Name="CommonStates">
40+
<VisualState x:Name="Normal" />
41+
<VisualState x:Name="Disabled" />
42+
<VisualState x:Name="ReadOnly" />
43+
<VisualState x:Name="MouseOver" />
44+
</VisualStateGroup>
45+
</VisualStateManager.VisualStateGroups>
46+
<ScrollViewer Margin="0" x:Name="PART_ContentHost" />
47+
</Border>
48+
</ControlTemplate>
49+
</Setter.Value>
50+
</Setter>
2151
</Style>
2252
</ResourceDictionary>

src/Uno.UI.Runtime.Skia.Wpf/WPF/WpfHost.cs renamed to src/Uno.UI.Runtime.Skia.Wpf/WpfHost.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ void CreateApp(WinUI.ApplicationInitializationCallbackParams _)
8181

8282
bool EnqueueNative(DispatcherQueuePriority priority, DispatcherQueueHandler callback)
8383
{
84-
if(priority == DispatcherQueuePriority.Normal)
84+
if (priority == DispatcherQueuePriority.Normal)
8585
{
8686
dispatcher.BeginInvoke(callback);
8787
}
@@ -166,7 +166,7 @@ protected override void OnRender(DrawingContext drawingContext)
166166
return;
167167
}
168168

169-
169+
170170
int width, height;
171171
var dpi = VisualTreeHelper.GetDpi(WpfApplication.Current.MainWindow);
172172
double dpiScaleX = dpi.DpiScaleX;

src/Uno.UI/UI/Xaml/Controls/TextBox/ITextBoxExtension.skia.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,7 @@ internal interface ITextBoxViewExtension
1313
void UpdateSize();
1414

1515
void UpdatePosition();
16+
17+
void SetTextNative(string text);
1618
}
1719
}

src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.Skia.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Windows.UI.Xaml.Controls
1111
{
1212
internal class TextBoxView
1313
{
14-
private ITextBoxViewExtension _textBoxExtension = null;
14+
private readonly ITextBoxViewExtension _textBoxExtension;
1515

1616
private readonly WeakReference<TextBox> _textBox;
1717

@@ -43,7 +43,11 @@ public TextBox? TextBox
4343

4444
public TextBlock DisplayBlock { get; } = new TextBlock();
4545

46-
internal void SetTextNative(string text) => DisplayBlock.Text = text;
46+
internal void SetTextNative(string text)
47+
{
48+
DisplayBlock.Text = text;
49+
_textBoxExtension?.SetTextNative(text);
50+
}
4751

4852
internal void OnForegroundChanged(Brush brush) => DisplayBlock.Foreground = brush;
4953

@@ -61,13 +65,13 @@ internal void OnFocusStateChanged(FocusState focusState)
6165
}
6266
}
6367

64-
internal void UpdateText(string newText)
68+
internal void UpdateTextFromNative(string newText)
6569
{
6670
var textBox = _textBox?.GetTarget();
6771
if (textBox != null)
6872
{
6973
var text = textBox.ProcessTextInput(newText);
70-
SetTextNative(newText);
74+
SetTextNative(text);
7175
}
7276
}
7377

0 commit comments

Comments
 (0)