Skip to content

Commit 0f3edba

Browse files
authored
Merge branch 'MaterialDesignInXAML:master' into master
2 parents bac3b9e + 3cb7dc9 commit 0f3edba

File tree

6 files changed

+127
-14
lines changed

6 files changed

+127
-14
lines changed

.github/workflows/get_versions.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ jobs:
2323
getting_versions:
2424
env:
2525
#Update these base version numbers
26-
mdix-version: "5.1.1"
27-
mdix-colors-version: "3.1.1"
28-
mdix-mahapps-version: "3.1.1"
26+
mdix-version: "5.2.1"
27+
mdix-colors-version: "5.2.1"
28+
mdix-mahapps-version: "5.2.1"
2929
name: Set version numbers
3030
runs-on: ubuntu-latest
3131
defaults:

.github/workflows/release.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,14 +258,15 @@ jobs:
258258
steps:
259259
# Doing a checkout, until this issue is resolved.
260260
# https://github.com/valeriobelli/gh-milestone/issues/15
261+
# As of version 2.1.0 the -R doesn't appear to output valid json when filtering. So still using the checkout.
261262
- uses: actions/checkout@v4
262263

263264
- name: Close Milestone
264265
run: |
265266
gh extension install valeriobelli/gh-milestone
266267
Write-Host "Using extension version $(gh milestone --version)"
267268
$milestones = $(gh milestone list --json number,title) | ConvertFrom-Json
268-
$milestoneNumber = ($milestones | Where-Object { $_.title -eq "5.1.0" }).number
269+
$milestoneNumber = ($milestones | Where-Object { $_.title -eq "${{ inputs.milestone }}" }).number
269270
gh milestone edit $milestoneNumber --state closed
270271
env:
271272
GITHUB_TOKEN: ${{ secrets.SA_PAT }}
@@ -277,7 +278,7 @@ jobs:
277278
environment: production
278279

279280
permissions:
280-
actions: write
281+
actions: write
281282

282283
steps:
283284
# Checkout is needed so that we can update the get_versions.yml file
@@ -312,6 +313,8 @@ jobs:
312313
Update-Version -Prefix "mdix-mahapps-version"
313314
314315
- name: Open Pull Request
316+
env:
317+
GITHUB_TOKEN: ${{ secrets.SA_PAT }}
315318
run: |
316319
git config --local user.email "github-actions[bot]@users.noreply.github.com"
317320
git config --local user.name "github-actions[bot]"

src/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.NumericUpDown.xaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@
184184

185185
<Style x:Key="MaterialDesignFilledUpDownBase"
186186
TargetType="{x:Type wpf:UpDownBase}"
187-
BasedOn="{StaticResource MaterialDesignFloatingHintNumericUpDown}">
187+
BasedOn="{StaticResource MaterialDesignFloatingHintUpDownBase}">
188188
<Style.Resources>
189189
<Style x:Key="NestedTextBoxStyle"
190190
TargetType="TextBox"
@@ -208,7 +208,7 @@
208208

209209
<Style x:Key="MaterialDesignOutlinedUpDownBase"
210210
TargetType="{x:Type wpf:UpDownBase}"
211-
BasedOn="{StaticResource MaterialDesignFloatingHintNumericUpDown}">
211+
BasedOn="{StaticResource MaterialDesignFloatingHintUpDownBase}">
212212
<Style.Resources>
213213
<Style x:Key="NestedTextBoxStyle"
214214
TargetType="TextBox"

src/MaterialDesignThemes.Wpf/UpDownBase.cs

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.ComponentModel;
1+
using System.ComponentModel;
22
using System.Globalization;
33

44
namespace MaterialDesignThemes.Wpf;
@@ -191,9 +191,7 @@ public override void OnApplyTemplate()
191191
if (_textBoxField != null)
192192
_textBoxField.TextChanged -= OnTextBoxFocusLost;
193193

194-
_increaseButton = GetTemplateChild(IncreaseButtonPartName) as RepeatButton;
195-
_decreaseButton = GetTemplateChild(DecreaseButtonPartName) as RepeatButton;
196-
_textBoxField = GetTemplateChild(TextBoxPartName) as TextBox;
194+
base.OnApplyTemplate();
197195

198196
if (_increaseButton != null)
199197
_increaseButton.Click += IncreaseButtonOnClick;
@@ -207,7 +205,6 @@ public override void OnApplyTemplate()
207205
_textBoxField.Text = Value?.ToString();
208206
}
209207

210-
base.OnApplyTemplate();
211208
}
212209

213210
private void OnTextBoxFocusLost(object sender, EventArgs e)
@@ -279,6 +276,55 @@ public class UpDownBase : Control
279276
protected RepeatButton? _decreaseButton;
280277
protected RepeatButton? _increaseButton;
281278

279+
static UpDownBase()
280+
{
281+
EventManager.RegisterClassHandler(typeof(UpDownBase), GotFocusEvent, new RoutedEventHandler(OnGotFocus));
282+
}
283+
284+
// Based on work in MahApps
285+
// https://github.com/MahApps/MahApps.Metro/blob/f7ba30586e9670f07c2f7b6553d129a9e32fc673/src/MahApps.Metro/Controls/NumericUpDown.cs#L966
286+
private static void OnGotFocus(object sender, RoutedEventArgs e)
287+
{
288+
// When NumericUpDown gets logical focus, select the text inside us.
289+
// If we're an editable NumericUpDown, forward focus to the TextBox element
290+
if (!e.Handled)
291+
{
292+
var numericUpDown = (UpDownBase)sender;
293+
if (numericUpDown.Focusable && e.OriginalSource == numericUpDown)
294+
{
295+
// MoveFocus takes a TraversalRequest as its argument.
296+
var focusDirection = Keyboard.Modifiers.HasFlag(ModifierKeys.Shift)
297+
? FocusNavigationDirection.Previous
298+
: FocusNavigationDirection.Next;
299+
300+
var request = new TraversalRequest(focusDirection);
301+
// Gets the element with keyboard focus.
302+
// And change the keyboard focus.
303+
if (Keyboard.FocusedElement is UIElement elementWithFocus)
304+
{
305+
elementWithFocus.MoveFocus(request);
306+
}
307+
else
308+
{
309+
numericUpDown.Focus();
310+
}
311+
312+
e.Handled = true;
313+
}
314+
}
315+
}
316+
317+
public override void OnApplyTemplate()
318+
{
319+
_increaseButton = GetTemplateChild(IncreaseButtonPartName) as RepeatButton;
320+
_decreaseButton = GetTemplateChild(DecreaseButtonPartName) as RepeatButton;
321+
_textBoxField = GetTemplateChild(TextBoxPartName) as TextBox;
322+
323+
base.OnApplyTemplate();
324+
}
325+
326+
public void SelectAll() => _textBoxField?.SelectAll();
327+
282328
public object? IncreaseContent
283329
{
284330
get => GetValue(IncreaseContentProperty);

tests/MaterialDesignThemes.UITests/WPF/UpDownControls/DecimalUpDownTests.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace MaterialDesignThemes.UITests.WPF.UpDownControls;
1+
using System.ComponentModel;
2+
3+
namespace MaterialDesignThemes.UITests.WPF.UpDownControls;
24

35
public class DecimalUpDownTests(ITestOutputHelper output) : TestBase(output)
46
{
@@ -115,4 +117,34 @@ public async Task MaxAndMinAssignments_CoerceValueToBeInRange()
115117
Assert.Equal(3, await numericUpDown.GetMinimum());
116118
Assert.Equal(3, await numericUpDown.GetMaximum());
117119
}
120+
121+
[Fact]
122+
[Description("Issue 3654")]
123+
public async Task InternalTextBoxIsFocused_WhenGettingKeyboardFocus()
124+
{
125+
await using var recorder = new TestRecorder(App);
126+
127+
// Arrange
128+
var stackPanel = await LoadXaml<StackPanel>("""
129+
<StackPanel>
130+
<TextBox />
131+
<materialDesign:DecimalUpDown />
132+
</StackPanel>
133+
""");
134+
135+
var textBox = await stackPanel.GetElement<TextBox>("/TextBox");
136+
var part_textBox = await stackPanel.GetElement<TextBox>("PART_TextBox");
137+
138+
// Act
139+
await textBox.MoveKeyboardFocus();
140+
await Task.Delay(50);
141+
await textBox.SendInput(new KeyboardInput(Key.Tab));
142+
await Task.Delay(50);
143+
144+
// Assert
145+
Assert.False(await textBox.GetIsFocused());
146+
Assert.True(await part_textBox.GetIsFocused());
147+
148+
recorder.Success();
149+
}
118150
}

tests/MaterialDesignThemes.UITests/WPF/UpDownControls/NumericUpDownTests.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace MaterialDesignThemes.UITests.WPF.UpDownControls;
1+
using System.ComponentModel;
2+
3+
namespace MaterialDesignThemes.UITests.WPF.UpDownControls;
24

35

46
public class NumericUpDownTests(ITestOutputHelper output) : TestBase(output)
@@ -116,4 +118,34 @@ public async Task MaxAndMinAssignments_CoerceValueToBeInRange()
116118
Assert.Equal(3, await numericUpDown.GetMinimum());
117119
Assert.Equal(3, await numericUpDown.GetMaximum());
118120
}
121+
122+
[Fact]
123+
[Description("Issue 3654")]
124+
public async Task InternalTextBoxIsFocused_WhenGettingKeyboardFocus()
125+
{
126+
await using var recorder = new TestRecorder(App);
127+
128+
// Arrange
129+
var stackPanel = await LoadXaml<StackPanel>("""
130+
<StackPanel>
131+
<TextBox />
132+
<materialDesign:NumericUpDown />
133+
</StackPanel>
134+
""");
135+
136+
var textBox = await stackPanel.GetElement<TextBox>("/TextBox");
137+
var part_textBox = await stackPanel.GetElement<TextBox>("PART_TextBox");
138+
139+
// Act
140+
await textBox.MoveKeyboardFocus();
141+
await Task.Delay(50);
142+
await textBox.SendInput(new KeyboardInput(Key.Tab));
143+
await Task.Delay(50);
144+
145+
// Assert
146+
Assert.False(await textBox.GetIsFocused());
147+
Assert.True(await part_textBox.GetIsFocused());
148+
149+
recorder.Success();
150+
}
119151
}

0 commit comments

Comments
 (0)