Skip to content

Commit 77f08f7

Browse files
authored
Merge pull request #221 from Infarh/dev
v0.0.48.2 - Обновление пакетов и мелкие исправления
2 parents e1551f8 + 6985025 commit 77f08f7

16 files changed

Lines changed: 455 additions & 48 deletions

MathCore.WPF.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
<s:Boolean x:Key="/Default/UserDictionary/Words/=Brel/@EntryIndexedValue">True</s:Boolean>
2121
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bself/@EntryIndexedValue">True</s:Boolean>
2222
<s:Boolean x:Key="/Default/UserDictionary/Words/=Headered/@EntryIndexedValue">True</s:Boolean>
23+
<s:Boolean x:Key="/Default/UserDictionary/Words/=hwnd/@EntryIndexedValue">True</s:Boolean>
2324
<s:Boolean x:Key="/Default/UserDictionary/Words/=Inits/@EntryIndexedValue">True</s:Boolean>
2425
<s:Boolean x:Key="/Default/UserDictionary/Words/=Interp/@EntryIndexedValue">True</s:Boolean>
2526
<s:Boolean x:Key="/Default/UserDictionary/Words/=MVVM/@EntryIndexedValue">True</s:Boolean>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.Windows.Data;
2+
3+
namespace MathCore.WPF.Commands;
4+
5+
/// <summary>Команда для подтверждения изменений в BindingGroup, если они были изменены</summary>
6+
public class BindingGroupCommit : Command
7+
{
8+
public override bool CanExecute(object? parameter) => parameter is BindingGroup { IsDirty: true };
9+
10+
public override void Execute(object? parameter) => (parameter as BindingGroup).CommitEdit();
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.Windows.Data;
2+
3+
namespace MathCore.WPF.Commands;
4+
5+
/// <summary>Команда для отмены изменений в BindingGroup, если они были изменены</summary>
6+
public class BindingGroupRollback : Command
7+
{
8+
public override bool CanExecute(object? parameter) => parameter is BindingGroup { IsDirty: true };
9+
10+
public override void Execute(object? parameter) => (parameter as BindingGroup).CancelEdit();
11+
}

MathCore.WPF/Extensions/WindowExtensions.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,26 @@ public static class WindowExtensions
1111
{
1212
public static IntPtr GetWindowHandle(this Window window) => new WindowInteropHelper(window).Handle;
1313

14-
public static void ForWindowFromChild(this object ChildDependencyObject, Action<Window> action)
14+
public static void ForWindowFromChild<T>(this T ChildDependencyObject, Action<Window> action)
15+
where T : DependencyObject
1516
{
1617
if (action is null) throw new ArgumentNullException(nameof(action));
17-
var element = ChildDependencyObject as DependencyObject;
18+
DependencyObject? element = ChildDependencyObject;
1819
while (element != null)
1920
{
2021
element = VisualTreeHelper.GetParent(element);
21-
if(element is not Window window) continue;
22-
action(window);
22+
if (element is not Window window) continue;
23+
action(window);
2324
break;
2425
}
2526
}
2627

27-
public static void ForWindowFromTemplate(this object TemplateFrameworkElement, Action<Window> action)
28+
public static void ForWindowFromTemplate<T>(this T TemplateFrameworkElement, Action<Window> action)
29+
where T : DependencyObject
2830
{
2931
if (action is null) throw new ArgumentNullException(nameof(action));
30-
if (((FrameworkElement)TemplateFrameworkElement)?.TemplatedParent is Window window) action(window);
32+
if (TemplateFrameworkElement is FrameworkElement { TemplatedParent: Window window })
33+
action(window);
3134
}
3235

3336
public static void AddHook(this Window window, HwndSourceHook WndProc)
@@ -39,7 +42,7 @@ public static void AddHook(this Window window, HwndSourceHook WndProc)
3942
source.AddHook(WndProc);
4043
}
4144
else
42-
window.SourceInitialized += (_,_) => window.AddHook(WndProc);
45+
window.SourceInitialized += (_, _) => window.AddHook(WndProc);
4346
}
4447

4548
public static void RemoveHook(this Window window, HwndSourceHook WndProc)

MathCore.WPF/MathCore.WPF.csproj

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424
<ImplicitUsings>enable</ImplicitUsings>
2525
<LangVersion>preview</LangVersion>
2626
<!--<RunAnalyzersDuringLiveAnalysis>true</RunAnalyzersDuringLiveAnalysis>-->
27+
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
28+
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
2729
</PropertyGroup>
2830

2931
<PropertyGroup>
30-
<Version>0.0.48.1</Version>
32+
<Version>0.0.48.2</Version>
3133
<PackageReleaseNotes>
3234
Добавлены стили для кнопок и полей ввода текста в стилистике Bootstrap 5
3335
</PackageReleaseNotes>
@@ -49,24 +51,24 @@
4951
</PropertyGroup>
5052

5153
<ItemGroup>
52-
<PackageReference Include="MathCore" Version="0.0.93.1" />
54+
<PackageReference Include="MathCore" Version="0.0.93.2" />
5355
</ItemGroup>
5456

5557
<ItemGroup Condition="'$(TargetFramework)'=='net4.6.1-windows'">
5658
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
57-
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.0" />
59+
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
5860
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="[1.1.39]" />
5961
</ItemGroup>
6062

6163
<ItemGroup Condition="'$(TargetFramework)'=='net4.7-windows'">
6264
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
63-
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.0" />
65+
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
6466
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" />
6567
</ItemGroup>
6668

6769
<ItemGroup Condition="'$(TargetFramework)'=='net4.8-windows'">
6870
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
69-
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.0" />
71+
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
7072
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" />
7173
</ItemGroup>
7274

@@ -75,7 +77,7 @@
7577
</ItemGroup>
7678

7779
<ItemGroup Condition="'$(TargetFramework)'=='net5.0-windows'">
78-
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.0" />
80+
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
7981
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="[1.1.39]" />
8082
</ItemGroup>
8183

MathCore.WPF/TextBoxEx.cs

Lines changed: 89 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,40 +20,42 @@ public static class TextBoxEx
2020
typeof(TextBoxEx),
2121
new(default(bool), OnUpdateBindingOnEnterChanged));
2222

23+
/// <summary>Обработчик изменения свойства UpdateBindingSourceOnEnter</summary>
2324
private static void OnUpdateBindingOnEnterChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
2425
{
25-
if(sender is not TextBox text_box || e.NewValue is not bool value) return;
26+
if (sender is not TextBox text_box || e.NewValue is not bool value) return;
2627

2728
if (value)
2829
text_box.KeyDown += OnTextBoxKeyDown;
2930
else
3031
text_box.KeyDown -= OnTextBoxKeyDown;
3132
}
3233

34+
/// <summary>Обработчик события нажатия клавиши в TextBox</summary>
3335
private static void OnTextBoxKeyDown(object Sender, KeyEventArgs E)
3436
{
35-
if(E.Key != Key.Enter) return;
37+
if (E.Key != Key.Enter) return;
3638

3739
var text_box = (TextBox)Sender;
3840

39-
if (text_box.AcceptsReturn && !E.KeyboardDevice.IsKeyDown(Key.LeftCtrl))
41+
if (text_box.AcceptsReturn && !E.KeyboardDevice.IsKeyDown(Key.LeftCtrl))
4042
return;
4143

42-
if (BindingOperations.GetBindingExpression(text_box, TextBox.TextProperty) is not { } binding)
44+
if (BindingOperations.GetBindingExpression(text_box, TextBox.TextProperty) is not { } binding)
4345
return;
4446

45-
if(binding.ParentBinding.UpdateSourceTrigger != UpdateSourceTrigger.Explicit && !E.KeyboardDevice.IsKeyDown(Key.LeftCtrl))
47+
if (binding.ParentBinding.UpdateSourceTrigger != UpdateSourceTrigger.Explicit && !E.KeyboardDevice.IsKeyDown(Key.LeftCtrl))
4648
return;
4749

4850
binding.UpdateSource();
4951
E.Handled = true;
5052
}
5153

52-
/// <summary>Обновить привязку при нажатии Enter</summary>
54+
/// <summary>Установить значение свойства UpdateBindingSourceOnEnter</summary>
5355
[AttachedPropertyBrowsableForType(typeof(TextBox))]
5456
public static void SetUpdateBindingSourceOnEnter(DependencyObject d, bool value) => d.SetValue(UpdateBindingSourceOnEnterProperty, value);
5557

56-
/// <summary>Обновить привязку при нажатии Enter</summary>
58+
/// <summary>Получить значение свойства UpdateBindingSourceOnEnter</summary>
5759
public static bool GetUpdateBindingSourceOnEnter(DependencyObject d) => (bool)d.GetValue(UpdateBindingSourceOnEnterProperty);
5860

5961
#endregion
@@ -66,21 +68,23 @@ private static void OnTextBoxKeyDown(object Sender, KeyEventArgs E)
6668
"ValidateInputScope",
6769
typeof(bool),
6870
typeof(TextBoxEx),
69-
new(default(bool), OnValidateInputScopeChanged));
71+
new(false, OnValidateInputScopeChanged));
7072

73+
/// <summary>Обработчик изменения свойства ValidateInputScope</summary>
7174
private static void OnValidateInputScopeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
7275
{
73-
if(obj is not TextBox text_box || e.NewValue is not bool value) return;
76+
if (obj is not TextBox text_box || e.NewValue is not bool value) return;
7477

7578
if (value)
7679
text_box.PreviewTextInput += ValidateScopes_OnPreviewTextInput;
7780
else
7881
text_box.PreviewTextInput -= ValidateScopes_OnPreviewTextInput;
7982
}
8083

84+
/// <summary>Обработчик события предварительного ввода текста в TextBox</summary>
8185
private static void ValidateScopes_OnPreviewTextInput(object Sender, TextCompositionEventArgs E)
8286
{
83-
if(Sender is not TextBox { InputScope: { } input_scope, Text: var current_text } text_box) return;
87+
if (Sender is not TextBox { InputScope: { } input_scope, Text: var current_text } text_box) return;
8488

8589
var input_text = E.Text;
8690
var full_text = current_text + input_text;
@@ -95,20 +99,20 @@ private static void ValidateScopes_OnPreviewTextInput(object Sender, TextComposi
9599
case InputScopeNameValue.FullFilePath when Path.GetInvalidPathChars().Any(c => input_text.Contains(c)):
96100
case InputScopeNameValue.FileName when Path.GetInvalidFileNameChars().Any(c => input_text.Contains(c)):
97101
case InputScopeNameValue.DateDayName when full_text.ToLower() is not (
98-
"sunday" or "sun" or "su" or
102+
"sunday" or "sun" or "su" or
99103
"monday" or "mon" or "mo" or
100104
"tuesday" or "tue" or "tu" or
101105
"wednesday" or "wed" or "wd" or
102106
"thursday" or "thu" or "th" or
103107
"friday" or "fri" or "fr" or
104-
"saturday" or "sat" or "st" or
108+
"saturday" or "sat" or "st" or
105109
"понедельник" or "пон" or "пн" or
106110
"вторник" or "втр" or "вт" or
107111
"среда" or "срд" or "ср" or
108112
"четверг" or "чет" or "чт" or
109113
"пятница" or "пят" or "пт" or
110114
"суббота" or "суб" or "сб" or
111-
"воскресенье" or "вос" or "вс"
115+
"воскресенье" or "вос" or "вс"
112116
):
113117
case InputScopeNameValue.DateDay when !int.TryParse(full_text, out var day) && day is not (>= 1 and <= 31):
114118
case InputScopeNameValue.DateMonth when !int.TryParse(full_text, out var month) && month is not (>= 1 and <= 12):
@@ -120,15 +124,15 @@ private static void ValidateScopes_OnPreviewTextInput(object Sender, TextComposi
120124
return;
121125
}
122126

123-
if (full_text.Length > 0 && input_scope.RegularExpression is { Length: > 0 } regex_str && !Regex.IsMatch(full_text, regex_str))
127+
if (full_text.Length > 0 && input_scope.RegularExpression is { Length: > 0 } regex_str && !Regex.IsMatch(full_text, regex_str))
124128
E.Handled = true;
125129
}
126130

127-
/// <summary>Проверять корректность правил InputScope</summary>
131+
/// <summary>Установить значение свойства ValidateInputScope</summary>
128132
[AttachedPropertyBrowsableForType(typeof(TextBox))]
129133
public static void SetValidateInputScope(DependencyObject d, bool value) => d.SetValue(ValidateInputScopeProperty, value);
130134

131-
/// <summary>Проверять корректность правил InputScope</summary>
135+
/// <summary>Получить значение свойства ValidateInputScope</summary>
132136
public static bool GetValidateInputScope(DependencyObject d) => (bool)d.GetValue(ValidateInputScopeProperty);
133137

134138
#endregion
@@ -143,19 +147,25 @@ private static void ValidateScopes_OnPreviewTextInput(object Sender, TextComposi
143147
typeof(TextBoxEx),
144148
new(decimal.Zero, OnMouseWheelIncrementChanged));
145149

150+
/// <summary>Обработчик изменения свойства MouseWheelIncrement</summary>
146151
private static void OnMouseWheelIncrementChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
147152
{
148-
if (e is { OldValue: decimal.Zero, NewValue: not decimal.Zero })
149-
((TextBox)s).MouseWheel += OnMouseWheel;
150-
else if (e is { OldValue: not decimal.Zero, NewValue: decimal.Zero })
151-
((TextBox)s).MouseWheel -= OnMouseWheel;
153+
switch (e)
154+
{
155+
case { OldValue: decimal.Zero, NewValue: not decimal.Zero }:
156+
((TextBox)s).MouseWheel += OnMouseWheel;
157+
break;
158+
case { OldValue: not decimal.Zero, NewValue: decimal.Zero }:
159+
((TextBox)s).MouseWheel -= OnMouseWheel;
160+
break;
161+
}
152162
}
153163

154-
/// <summary>Инкремент колёсика мышки</summary>
164+
/// <summary>Установить значение свойства MouseWheelIncrement</summary>
155165
[AttachedPropertyBrowsableForType(typeof(TextBox))]
156166
public static void SetMouseWheelIncrement(DependencyObject d, decimal value) => d.SetValue(MouseWheelIncrementProperty, value);
157167

158-
/// <summary>Инкремент колёсика мышки</summary>
168+
/// <summary>Получить значение свойства MouseWheelIncrement</summary>
159169
public static decimal GetMouseWheelIncrement(DependencyObject d) => (decimal)d.GetValue(MouseWheelIncrementProperty);
160170

161171
#endregion
@@ -170,15 +180,16 @@ private static void OnMouseWheelIncrementChanged(DependencyObject s, DependencyP
170180
typeof(TextBoxEx),
171181
new(0.1m));
172182

173-
/// <summary>Инкремент колёсика мышки</summary>
183+
/// <summary>Установить значение свойства MouseWheelIncrementCtrlRatio</summary>
174184
[AttachedPropertyBrowsableForType(typeof(TextBox))]
175185
public static void SetMouseWheelIncrementCtrlRatio(DependencyObject d, decimal value) => d.SetValue(MouseWheelIncrementCtrlRatioProperty, value);
176186

177-
/// <summary>Инкремент колёсика мышки</summary>
187+
/// <summary>Получить значение свойства MouseWheelIncrementCtrlRatio</summary>
178188
public static decimal GetMouseWheelIncrementCtrlRatio(DependencyObject d) => (decimal)d.GetValue(MouseWheelIncrementCtrlRatioProperty);
179189

180190
#endregion
181191

192+
/// <summary>Обработчик события прокрутки колёсика мыши в TextBox</summary>
182193
private static void OnMouseWheel(object Sender, MouseWheelEventArgs E)
183194
{
184195
if (Sender is not TextBox { Text: var text } text_block) return;
@@ -195,4 +206,58 @@ private static void OnMouseWheel(object Sender, MouseWheelEventArgs E)
195206
var new_value_text = new_value.ToString(CultureInfo.InvariantCulture);
196207
text_block.Text = new_value_text;
197208
}
209+
210+
#region Attached property AutoSelectAll : bool - Автовыбор всего содержимого TextBox
211+
212+
/// <summary>Авто выбор всего содержимого TextBox</summary>
213+
public static readonly DependencyProperty AutoSelectAllProperty =
214+
DependencyProperty.RegisterAttached(
215+
"AutoSelectAll",
216+
typeof(bool),
217+
typeof(TextBoxEx),
218+
new(false, OnAutoSelectAllChanged));
219+
220+
/// <summary>Обработчик изменения свойства AutoSelectAll</summary>
221+
private static void OnAutoSelectAllChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
222+
{
223+
if (d is not TextBox text_box) return;
224+
225+
if ((bool)e.NewValue)
226+
{
227+
text_box.PreviewMouseDown += OnTextBoxPreviewMouseDown;
228+
text_box.GotKeyboardFocus += OnTextBoxGotKeyboardFocus;
229+
}
230+
else
231+
{
232+
text_box.PreviewMouseDown -= OnTextBoxPreviewMouseDown;
233+
text_box.GotKeyboardFocus -= OnTextBoxGotKeyboardFocus;
234+
}
235+
}
236+
237+
/// <summary>Обработчик события предварительного нажатия мыши в TextBox</summary>
238+
private static void OnTextBoxPreviewMouseDown(object sender, MouseButtonEventArgs e)
239+
{
240+
if (sender is not TextBox text_box || text_box.IsKeyboardFocusWithin) return;
241+
242+
text_box.Focus();
243+
e.Handled = true;
244+
}
245+
246+
/// <summary>Обработчик события получения фокуса клавиатуры в TextBox</summary>
247+
private static void OnTextBoxGotKeyboardFocus(object sender, RoutedEventArgs e)
248+
{
249+
if (sender is not TextBox text_box) return;
250+
251+
text_box.SelectAll();
252+
e.Handled = true;
253+
}
254+
255+
/// <summary>Установить значение свойства AutoSelectAll</summary>
256+
[AttachedPropertyBrowsableForType(typeof(TextBox))]
257+
public static void SetAutoSelectAll(DependencyObject d, bool value) => d.SetValue(AutoSelectAllProperty, value);
258+
259+
/// <summary>Получить значение свойства AutoSelectAll</summary>
260+
public static bool GetAutoSelectAll(DependencyObject d) => (bool)d.GetValue(AutoSelectAllProperty);
261+
262+
#endregion
198263
}

Tests/MathCore.WPF.Tests/MathCore.WPF.Tests.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010

1111
<ItemGroup>
1212
<PackageReference Include="MathCore.TestsExtensions" Version="0.1.44" />
13-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
14-
<PackageReference Include="MSTest.TestAdapter" Version="3.7.3" />
15-
<PackageReference Include="MSTest.TestFramework" Version="3.7.3" />
13+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
14+
<PackageReference Include="MSTest.TestAdapter" Version="3.9.2" />
15+
<PackageReference Include="MSTest.TestFramework" Version="3.9.2" />
1616
<PackageReference Include="coverlet.collector" Version="6.0.4" PrivateAssets="all">
1717
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1818
</PackageReference>

Tests/MathCore.WPF.WindowTest/App.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
44
xmlns:l="clr-namespace:MathCore.WPF.WindowTest"
5-
StartupUri="TestWindow5.xaml">
5+
StartupUri="TestWindow7.xaml">
66
<Application.Resources>
77
<ResourceDictionary>
88
<ResourceDictionary.MergedDictionaries>

Tests/MathCore.WPF.WindowTest/App.xaml.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ protected override async void OnStartup(StartupEventArgs e)
4545
base.OnStartup(e);
4646
await host.StartAsync();
4747

48-
var main_thread_cancellation = __MainThreadWatcherCancellation.Token;
49-
_ = Task.Run(() => MainThreadLoadingWatcher(main_thread_cancellation), main_thread_cancellation);
48+
//var main_thread_cancellation = __MainThreadWatcherCancellation.Token;
49+
//_ = Task.Run(() => MainThreadLoadingWatcher(main_thread_cancellation), main_thread_cancellation);
5050
}
5151

5252
private static readonly CancellationTokenSource __MainThreadWatcherCancellation = new();

0 commit comments

Comments
 (0)