Merge pull request #170 from heartacker/acker/und_new_feature_3_20
bug fix and add new NumericUpDownDemo
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net7.0-android</TargetFramework>
|
<TargetFramework>net8.0-android</TargetFramework>
|
||||||
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
|
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ApplicationId>com.irihitech.Ursa</ApplicationId>
|
<ApplicationId>com.irihitech.Ursa</ApplicationId>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
|
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
|
||||||
<WasmMainJSPath>AppBundle\main.js</WasmMainJSPath>
|
<WasmMainJSPath>AppBundle\main.js</WasmMainJSPath>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0-ios</TargetFramework>
|
<TargetFramework>net8.0-ios</TargetFramework>
|
||||||
<SupportedOSPlatformVersion>13.0</SupportedOSPlatformVersion>
|
<SupportedOSPlatformVersion>13.0</SupportedOSPlatformVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -8,19 +8,170 @@
|
|||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<UserControl.Styles>
|
<UserControl.Styles>
|
||||||
<Style Selector=":is(u|NumericUpDown)">
|
<Style Selector=":is(u|NumericUpDown)">
|
||||||
<Setter Property="Width" Value="240"></Setter>
|
<Setter Property="Width" Value="240" />
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||||
</Style>
|
</Style>
|
||||||
</UserControl.Styles>
|
</UserControl.Styles>
|
||||||
<StackPanel HorizontalAlignment="Left">
|
|
||||||
<u:NumericIntUpDown Name="input" InnerLeftContent="Age" Step="1" Value="2" Watermark="Input Value" Classes="ClearButton" />
|
<Grid ColumnDefinitions="*,*">
|
||||||
<TextBlock Text="{Binding #input.Value}" ></TextBlock>
|
<Grid
|
||||||
<u:NumericDoubleUpDown Name="inputDouble" Step="0.5" Value="3.1" EmptyInputValue="1"></u:NumericDoubleUpDown>
|
Grid.Column="0"
|
||||||
<TextBlock Text="{Binding #inputDouble.Value}"></TextBlock>
|
HorizontalAlignment="Left"
|
||||||
<u:NumericByteUpDown Name="inputByte" Step="1" Value="3" EmptyInputValue="1"></u:NumericByteUpDown>
|
RowDefinitions="200,*">
|
||||||
<TextBlock Text="{Binding #inputByte.Value}"></TextBlock>
|
<StackPanel>
|
||||||
<TextBlock Text="Drag"></TextBlock>
|
<u:Divider Content="Change Right ->" />
|
||||||
<u:NumericIntUpDown Step="1" Value="2" Watermark="Input Value" AllowDrag="True" />
|
<u:NumericUIntUpDown
|
||||||
</StackPanel>
|
Name="numd"
|
||||||
|
HorizontalContentAlignment="{Binding HorizontalContentAlignment}"
|
||||||
|
AllowDrag="{Binding AllowDrag}"
|
||||||
|
AllowSpin="{Binding AllowSpin}"
|
||||||
|
FontFamily="{Binding FontFamily, Mode=OneWay}"
|
||||||
|
FormatString="{Binding FormatString}"
|
||||||
|
InnerLeftContent="{Binding InnerLeftContent}"
|
||||||
|
IsEnabled="{Binding IsEnable}"
|
||||||
|
IsReadOnly="{Binding IsReadOnly}"
|
||||||
|
Maximum="{Binding Maximum}"
|
||||||
|
Minimum="{Binding Minimum}"
|
||||||
|
ParsingNumberStyle="{Binding ParsingNumberStyle}"
|
||||||
|
ShowButtonSpinner="{Binding ShowButtonSpinner}"
|
||||||
|
Step="{Binding Step}"
|
||||||
|
Watermark="{Binding Watermark}"
|
||||||
|
Value="{Binding Value}" />
|
||||||
|
<u:Divider Content="Demo" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="1">
|
||||||
|
<u:Divider Content="{Binding #input.Value, StringFormat='Int = {0}'}" />
|
||||||
|
<u:NumericIntUpDown
|
||||||
|
Name="input"
|
||||||
|
Classes="ClearButton"
|
||||||
|
InnerLeftContent="Age"
|
||||||
|
Step="1"
|
||||||
|
Watermark="Input Value"
|
||||||
|
Value="2" />
|
||||||
|
<u:Divider Content="{Binding #inputDouble.Value, StringFormat='Double = {0}'}" />
|
||||||
|
<u:NumericDoubleUpDown
|
||||||
|
Name="inputDouble"
|
||||||
|
EmptyInputValue="1"
|
||||||
|
Step="0.5"
|
||||||
|
Value="3.1" />
|
||||||
|
<u:Divider Content="{Binding #inputByte.Value, StringFormat='Byte = {0}'}" />
|
||||||
|
<u:NumericByteUpDown
|
||||||
|
Name="inputByte"
|
||||||
|
EmptyInputValue="1"
|
||||||
|
Step="1"
|
||||||
|
Value="3" />
|
||||||
|
<u:Divider Content="{Binding #Drag_Int.Value, StringFormat='Drag Int = {0}'}" />
|
||||||
|
<u:NumericIntUpDown
|
||||||
|
Name="Drag_Int"
|
||||||
|
AllowDrag="True"
|
||||||
|
InnerLeftContent="Drag"
|
||||||
|
Step="1"
|
||||||
|
Watermark="Input Value"
|
||||||
|
Value="2" />
|
||||||
|
|
||||||
|
<!-- hex demo -->
|
||||||
|
|
||||||
|
<u:Divider Content="{Binding #uint_HexNumber.Value, StringFormat='Don‘t Use = {0}, hex={0:X}'}" />
|
||||||
|
<!-- =================this is error usage -->
|
||||||
|
<u:NumericUIntUpDown
|
||||||
|
Name="uint_HexNumber"
|
||||||
|
AllowDrag="False"
|
||||||
|
FormatString="{}{0:X8}"
|
||||||
|
InnerLeftContent="HexNumber"
|
||||||
|
ParsingNumberStyle="HexNumber"
|
||||||
|
Step="1"
|
||||||
|
Watermark="Input Value"
|
||||||
|
Value="2" />
|
||||||
|
|
||||||
|
<!-- =================we should use AllowHexSpecifier -->
|
||||||
|
<u:Divider Content="{Binding #uint_AllowHexSpecifier.Value, StringFormat='uint = {0}, hex={0:X}'}" />
|
||||||
|
<u:NumericUIntUpDown
|
||||||
|
Name="uint_AllowHexSpecifier"
|
||||||
|
HorizontalContentAlignment="Right"
|
||||||
|
AllowDrag="False"
|
||||||
|
FontFamily="Consolas"
|
||||||
|
FormatString="{}{0:X8}"
|
||||||
|
InnerLeftContent="AllowHexSpecifier"
|
||||||
|
ParsingNumberStyle="AllowHexSpecifier"
|
||||||
|
Step="1"
|
||||||
|
Watermark="AllowHexSpecifier"
|
||||||
|
Value="2" />
|
||||||
|
|
||||||
|
<u:Divider Content="{Binding #Consolas_uint.Value, StringFormat='Font=Consolas {0}, hex={0:X}'}" />
|
||||||
|
<u:NumericUIntUpDown
|
||||||
|
Name="Consolas_uint"
|
||||||
|
HorizontalContentAlignment="Right"
|
||||||
|
AllowDrag="False"
|
||||||
|
FontFamily="Consolas"
|
||||||
|
FormatString="X8"
|
||||||
|
InnerLeftContent="0x"
|
||||||
|
ParsingNumberStyle="AllowHexSpecifier"
|
||||||
|
Step="1"
|
||||||
|
Watermark="AllowHexSpecifier"
|
||||||
|
Value="2" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
<StackPanel Grid.Column="1" HorizontalAlignment="Left">
|
||||||
|
|
||||||
|
<Label Content="FontFamily" />
|
||||||
|
<TextBox Text="{Binding FontFamily}" />
|
||||||
|
|
||||||
|
<Label Content="AllowDrag" />
|
||||||
|
<CheckBox IsChecked="{Binding AllowDrag}" />
|
||||||
|
|
||||||
|
<Label Content="IsReadOnly" />
|
||||||
|
<CheckBox IsChecked="{Binding IsReadOnly}" />
|
||||||
|
|
||||||
|
<Label Content="HorizontalContentAlignment" />
|
||||||
|
<ComboBox ItemsSource="{Binding Array_HorizontalContentAlignment}" SelectedItem="{Binding HorizontalContentAlignment}" />
|
||||||
|
|
||||||
|
<Label Content="InnerLeftContent" />
|
||||||
|
<TextBox Text="{Binding InnerLeftContent}" />
|
||||||
|
|
||||||
|
|
||||||
|
<Label Content="Watermark" />
|
||||||
|
<TextBox Text="{Binding Watermark}" />
|
||||||
|
|
||||||
|
|
||||||
|
<Label Content="FormatString" />
|
||||||
|
<TextBox
|
||||||
|
MinWidth="100"
|
||||||
|
MaxLength="100"
|
||||||
|
Text="{Binding FormatString}" />
|
||||||
|
|
||||||
|
<Label Content="ParsingNumberStyle" />
|
||||||
|
<ComboBox ItemsSource="{Binding Array_ParsingNumberStyle}" SelectedItem="{Binding ParsingNumberStyle}" />
|
||||||
|
|
||||||
|
|
||||||
|
<Label Content="AllowSpin" />
|
||||||
|
<CheckBox IsChecked="{Binding AllowSpin}" />
|
||||||
|
|
||||||
|
<Label Content="ShowButtonSpinner" />
|
||||||
|
<CheckBox IsChecked="{Binding ShowButtonSpinner}" />
|
||||||
|
|
||||||
|
<u:NumericUIntUpDown
|
||||||
|
Name="nudV"
|
||||||
|
AllowSpin="True"
|
||||||
|
InnerLeftContent="Value"
|
||||||
|
IsEnabled="True"
|
||||||
|
IsReadOnly="False"
|
||||||
|
Value="{Binding Value, Mode=TwoWay}" />
|
||||||
|
|
||||||
|
<u:NumericUIntUpDown InnerLeftContent="Max" Value="{Binding Maximum}" />
|
||||||
|
|
||||||
|
<u:NumericUIntUpDown InnerLeftContent="Min" Value="{Binding Minimum}" />
|
||||||
|
|
||||||
|
<Label Content="Step" />
|
||||||
|
<Slider Minimum="1" Value="{Binding Step}" />
|
||||||
|
|
||||||
|
<Label Content="IsEnable" />
|
||||||
|
<CheckBox IsChecked="{Binding IsEnable}" />
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using Ursa.Controls;
|
||||||
using Ursa.Demo.ViewModels;
|
using Ursa.Demo.ViewModels;
|
||||||
|
|
||||||
namespace Ursa.Demo.Pages;
|
namespace Ursa.Demo.Pages;
|
||||||
@@ -11,5 +14,12 @@ public partial class NumericUpDownDemo : UserControl
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
DataContext = new NumericUpDownDemoViewModel();
|
DataContext = new NumericUpDownDemoViewModel();
|
||||||
|
numd.ValueChanged += Numd_ValueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Numd_ValueChanged(object? sender, ValueChangedEventArgs<uint> e)
|
||||||
|
{
|
||||||
|
Trace.WriteLine($"{(sender as NumericUIntUpDown).Name} {e.OldValue} {e.NewValue}");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)" />
|
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)" />
|
||||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)" />
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.0" />
|
||||||
<PackageReference Include="Semi.Avalonia" Version="11.0.7" />
|
<PackageReference Include="Semi.Avalonia" Version="11.0.7" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,50 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Layout;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using Ursa.Controls;
|
||||||
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
|
||||||
namespace Ursa.Demo.ViewModels;
|
namespace Ursa.Demo.ViewModels;
|
||||||
|
|
||||||
public class NumericUpDownDemoViewModel: ObservableObject
|
public partial class NumericUpDownDemoViewModel : ObservableObject
|
||||||
{
|
{
|
||||||
|
|
||||||
|
[ObservableProperty] private uint _Value;
|
||||||
|
[ObservableProperty] private string _FontFamily = "Consolas";
|
||||||
|
[ObservableProperty] private bool _AllowDrag = false;
|
||||||
|
[ObservableProperty] private bool _IsReadOnly = false;
|
||||||
|
|
||||||
|
[ObservableProperty] private Array _Array_HorizontalContentAlignment;
|
||||||
|
[ObservableProperty] private HorizontalAlignment _HorizontalContentAlignment = HorizontalAlignment.Center;
|
||||||
|
[ObservableProperty] private object? _InnerLeftContent = "obj:0x";
|
||||||
|
[ObservableProperty] private string _Watermark = "Water mark showed";
|
||||||
|
[ObservableProperty] private string _FormatString = "X8";
|
||||||
|
[ObservableProperty] private Array _Array_ParsingNumberStyle;
|
||||||
|
[ObservableProperty] private NumberStyles _ParsingNumberStyle = NumberStyles.AllowHexSpecifier;
|
||||||
|
[ObservableProperty] private bool _AllowSpin = true;
|
||||||
|
[ObservableProperty] private bool _ShowButtonSpinner = true;
|
||||||
|
|
||||||
|
[ObservableProperty] private UInt32 _Maximum = UInt32.MaxValue;
|
||||||
|
[ObservableProperty] private UInt32 _Minimum = UInt32.MinValue;
|
||||||
|
[ObservableProperty] private UInt32 _Step = 1;
|
||||||
|
|
||||||
|
[ObservableProperty] private bool _IsEnable = true;
|
||||||
|
|
||||||
|
|
||||||
|
public NumericUpDownDemoViewModel()
|
||||||
|
{
|
||||||
|
Array_HorizontalContentAlignment = Enum.GetValues(typeof(HorizontalAlignment));
|
||||||
|
Array_ParsingNumberStyle = Enum.GetValues(typeof(NumberStyles));
|
||||||
|
NumericUIntUpDown numericUIntUpDown;
|
||||||
|
TextBox textBox;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnValueChanging(uint oldValue, uint newValue)
|
||||||
|
{
|
||||||
|
Console.WriteLine(oldValue);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -35,24 +35,25 @@
|
|||||||
MinWidth="0"
|
MinWidth="0"
|
||||||
HorizontalContentAlignment="Stretch"
|
HorizontalContentAlignment="Stretch"
|
||||||
VerticalContentAlignment="Stretch"
|
VerticalContentAlignment="Stretch"
|
||||||
ShowButtonSpinner="{TemplateBinding ShowButtonSpinner}"
|
|
||||||
AllowSpin="{TemplateBinding AllowSpin}"
|
AllowSpin="{TemplateBinding AllowSpin}"
|
||||||
Background="{TemplateBinding Background}"
|
Background="{TemplateBinding Background}"
|
||||||
BorderBrush="{TemplateBinding BorderBrush}"
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
BorderThickness="{TemplateBinding BorderThickness}">
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
ShowButtonSpinner="{TemplateBinding ShowButtonSpinner}">
|
||||||
<Panel>
|
<Panel>
|
||||||
<TextBox
|
<TextBox
|
||||||
Name="PART_TextBox"
|
Name="PART_TextBox"
|
||||||
Height="{TemplateBinding Height}"
|
Height="{TemplateBinding Height}"
|
||||||
MinHeight="{DynamicResource NumericUpDownWrapperDefaultHeight}"
|
MinHeight="{DynamicResource NumericUpDownWrapperDefaultHeight}"
|
||||||
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||||
AcceptsReturn="False"
|
AcceptsReturn="False"
|
||||||
CornerRadius="{TemplateBinding CornerRadius}"
|
CornerRadius="{TemplateBinding CornerRadius}"
|
||||||
DataValidationErrors.Errors="{ReflectionBinding $parent[NumericUpDown].(DataValidationErrors.Errors)}"
|
DataValidationErrors.Errors="{ReflectionBinding $parent[NumericUpDown].(DataValidationErrors.Errors)}"
|
||||||
FontSize="{TemplateBinding FontSize}"
|
FontSize="{TemplateBinding FontSize}"
|
||||||
Foreground="{TemplateBinding Foreground}"
|
Foreground="{TemplateBinding Foreground}"
|
||||||
|
InnerLeftContent="{TemplateBinding InnerLeftContent}"
|
||||||
IsReadOnly="{TemplateBinding IsReadOnly}"
|
IsReadOnly="{TemplateBinding IsReadOnly}"
|
||||||
TextWrapping="NoWrap"
|
TextWrapping="NoWrap"
|
||||||
InnerLeftContent="{TemplateBinding InnerLeftContent}"
|
|
||||||
Theme="{DynamicResource NonErrorTextBox}"
|
Theme="{DynamicResource NonErrorTextBox}"
|
||||||
Watermark="{TemplateBinding Watermark}" />
|
Watermark="{TemplateBinding Watermark}" />
|
||||||
<Panel
|
<Panel
|
||||||
@@ -64,11 +65,11 @@
|
|||||||
IsVisible="{TemplateBinding AllowDrag}" />
|
IsVisible="{TemplateBinding AllowDrag}" />
|
||||||
<Button
|
<Button
|
||||||
Name="PART_ClearButton"
|
Name="PART_ClearButton"
|
||||||
Command="{Binding $parent[u:NumericUpDown].Clear}"
|
Margin="0,0,8,0"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Margin="0 0 8 0"
|
Command="{Binding $parent[u:NumericUpDown].Clear}"
|
||||||
IsVisible="False"
|
|
||||||
Focusable="False"
|
Focusable="False"
|
||||||
|
IsVisible="False"
|
||||||
Theme="{StaticResource InputClearButton}" />
|
Theme="{StaticResource InputClearButton}" />
|
||||||
</Panel>
|
</Panel>
|
||||||
</ButtonSpinner>
|
</ButtonSpinner>
|
||||||
|
|||||||
@@ -18,7 +18,10 @@ public class NumericIntUpDown : NumericUpDownBase<int>
|
|||||||
protected override bool ParseText(string? text, out int number) =>
|
protected override bool ParseText(string? text, out int number) =>
|
||||||
int.TryParse(text, ParsingNumberStyle, NumberFormat, out number);
|
int.TryParse(text, ParsingNumberStyle, NumberFormat, out number);
|
||||||
|
|
||||||
protected override string? ValueToString(int? value) => value?.ToString(FormatString, NumberFormat);
|
protected override string? ValueToString(int? value)
|
||||||
|
{
|
||||||
|
return value?.ToString(FormatString, NumberFormat);
|
||||||
|
}
|
||||||
|
|
||||||
protected override int Zero => 0;
|
protected override int Zero => 0;
|
||||||
|
|
||||||
@@ -27,6 +30,34 @@ public class NumericIntUpDown : NumericUpDownBase<int>
|
|||||||
protected override int? Minus(int? a, int? b) => a - b;
|
protected override int? Minus(int? a, int? b) => a - b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class NumericUIntUpDown : NumericUpDownBase<uint>
|
||||||
|
{
|
||||||
|
protected override Type StyleKeyOverride { get; } = typeof(NumericUpDown);
|
||||||
|
|
||||||
|
static NumericUIntUpDown()
|
||||||
|
{
|
||||||
|
MaximumProperty.OverrideDefaultValue<NumericUIntUpDown>(uint.MaxValue);
|
||||||
|
MinimumProperty.OverrideDefaultValue<NumericUIntUpDown>(uint.MinValue);
|
||||||
|
StepProperty.OverrideDefaultValue<NumericUIntUpDown>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool ParseText(string? text, out uint number)
|
||||||
|
{
|
||||||
|
return uint.TryParse(text, ParsingNumberStyle, NumberFormat, out number);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string? ValueToString(uint? value)
|
||||||
|
{
|
||||||
|
return value?.ToString(FormatString, NumberFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override uint Zero => 0;
|
||||||
|
|
||||||
|
protected override uint? Add(uint? a, uint? b) => a + b;
|
||||||
|
|
||||||
|
protected override uint? Minus(uint? a, uint? b) => a - b;
|
||||||
|
}
|
||||||
|
|
||||||
public class NumericDoubleUpDown : NumericUpDownBase<double>
|
public class NumericDoubleUpDown : NumericUpDownBase<double>
|
||||||
{
|
{
|
||||||
protected override Type StyleKeyOverride { get; } = typeof(NumericUpDown);
|
protected override Type StyleKeyOverride { get; } = typeof(NumericUpDown);
|
||||||
@@ -68,9 +99,9 @@ public class NumericByteUpDown : NumericUpDownBase<byte>
|
|||||||
|
|
||||||
protected override byte Zero => 0;
|
protected override byte Zero => 0;
|
||||||
|
|
||||||
protected override byte? Add(byte? a, byte? b) => (byte?) (a + b);
|
protected override byte? Add(byte? a, byte? b) => (byte?)(a + b);
|
||||||
|
|
||||||
protected override byte? Minus(byte? a, byte? b) => (byte?) (a - b);
|
protected override byte? Minus(byte? a, byte? b) => (byte?)(a - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericSByteUpDown : NumericUpDownBase<sbyte>
|
public class NumericSByteUpDown : NumericUpDownBase<sbyte>
|
||||||
@@ -91,9 +122,9 @@ public class NumericSByteUpDown : NumericUpDownBase<sbyte>
|
|||||||
|
|
||||||
protected override sbyte Zero => 0;
|
protected override sbyte Zero => 0;
|
||||||
|
|
||||||
protected override sbyte? Add(sbyte? a, sbyte? b) => (sbyte?) (a + b);
|
protected override sbyte? Add(sbyte? a, sbyte? b) => (sbyte?)(a + b);
|
||||||
|
|
||||||
protected override sbyte? Minus(sbyte? a, sbyte? b) => (sbyte?) (a - b);
|
protected override sbyte? Minus(sbyte? a, sbyte? b) => (sbyte?)(a - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericShortUpDown : NumericUpDownBase<short>
|
public class NumericShortUpDown : NumericUpDownBase<short>
|
||||||
@@ -114,9 +145,9 @@ public class NumericShortUpDown : NumericUpDownBase<short>
|
|||||||
|
|
||||||
protected override short Zero => 0;
|
protected override short Zero => 0;
|
||||||
|
|
||||||
protected override short? Add(short? a, short? b) => (short?) (a + b);
|
protected override short? Add(short? a, short? b) => (short?)(a + b);
|
||||||
|
|
||||||
protected override short? Minus(short? a, short? b) => (short?) (a - b);
|
protected override short? Minus(short? a, short? b) => (short?)(a - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericUShortUpDown : NumericUpDownBase<ushort>
|
public class NumericUShortUpDown : NumericUpDownBase<ushort>
|
||||||
@@ -137,9 +168,9 @@ public class NumericUShortUpDown : NumericUpDownBase<ushort>
|
|||||||
|
|
||||||
protected override ushort Zero => 0;
|
protected override ushort Zero => 0;
|
||||||
|
|
||||||
protected override ushort? Add(ushort? a, ushort? b) => (ushort?) (a + b);
|
protected override ushort? Add(ushort? a, ushort? b) => (ushort?)(a + b);
|
||||||
|
|
||||||
protected override ushort? Minus(ushort? a, ushort? b) => (ushort?) (a - b);
|
protected override ushort? Minus(ushort? a, ushort? b) => (ushort?)(a - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericLongUpDown : NumericUpDownBase<long>
|
public class NumericLongUpDown : NumericUpDownBase<long>
|
||||||
@@ -233,4 +264,3 @@ public class NumericDecimalUpDown : NumericUpDownBase<decimal>
|
|||||||
|
|
||||||
protected override decimal? Minus(decimal? a, decimal? b) => a - b;
|
protected override decimal? Minus(decimal? a, decimal? b) => a - b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Avalonia.Data;
|
|||||||
using Avalonia.Data.Converters;
|
using Avalonia.Data.Converters;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
|
using Avalonia.Layout;
|
||||||
using Irihi.Avalonia.Shared.Contracts;
|
using Irihi.Avalonia.Shared.Contracts;
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
@@ -29,6 +30,12 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
|
|||||||
private Point? _point;
|
private Point? _point;
|
||||||
protected internal bool _updateFromTextInput;
|
protected internal bool _updateFromTextInput;
|
||||||
|
|
||||||
|
|
||||||
|
protected internal bool _canIncrease = true;
|
||||||
|
|
||||||
|
protected internal bool _canDecrease = true;
|
||||||
|
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> AllowDragProperty = AvaloniaProperty.Register<NumericUpDown, bool>(
|
public static readonly StyledProperty<bool> AllowDragProperty = AvaloniaProperty.Register<NumericUpDown, bool>(
|
||||||
nameof(AllowDrag), defaultValue: false);
|
nameof(AllowDrag), defaultValue: false);
|
||||||
|
|
||||||
@@ -47,6 +54,14 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
|
|||||||
set => SetValue(IsReadOnlyProperty, value);
|
set => SetValue(IsReadOnlyProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<HorizontalAlignment> HorizontalContentAlignmentProperty =
|
||||||
|
ContentControl.HorizontalContentAlignmentProperty.AddOwner<NumericUpDown>();
|
||||||
|
public HorizontalAlignment HorizontalContentAlignment
|
||||||
|
{
|
||||||
|
get => GetValue(HorizontalContentAlignmentProperty);
|
||||||
|
set => SetValue(HorizontalContentAlignmentProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<object?> InnerLeftContentProperty = AvaloniaProperty.Register<NumericUpDown, object?>(
|
public static readonly StyledProperty<object?> InnerLeftContentProperty = AvaloniaProperty.Register<NumericUpDown, object?>(
|
||||||
nameof(InnerLeftContent));
|
nameof(InnerLeftContent));
|
||||||
|
|
||||||
@@ -125,7 +140,7 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
|
|||||||
{
|
{
|
||||||
NumberFormatProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.OnFormatChange(e));
|
NumberFormatProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.OnFormatChange(e));
|
||||||
FormatStringProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.OnFormatChange(e));
|
FormatStringProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.OnFormatChange(e));
|
||||||
IsReadOnlyProperty.Changed.AddClassHandler<NumericUpDown>((o,e)=>o.ChangeToSetSpinDirection(e));
|
IsReadOnlyProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.ChangeToSetSpinDirection(e));
|
||||||
TextConverterProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.OnFormatChange(e));
|
TextConverterProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.OnFormatChange(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +170,7 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
|
|||||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnApplyTemplate(e);
|
base.OnApplyTemplate(e);
|
||||||
if(_spinner is not null)
|
if (_spinner is not null)
|
||||||
{
|
{
|
||||||
_spinner.Spin -= OnSpin;
|
_spinner.Spin -= OnSpin;
|
||||||
}
|
}
|
||||||
@@ -174,7 +189,7 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
|
|||||||
}
|
}
|
||||||
if (_dragPanel is not null)
|
if (_dragPanel is not null)
|
||||||
{
|
{
|
||||||
_dragPanel.PointerPressed+= OnDragPanelPointerPressed;
|
_dragPanel.PointerPressed += OnDragPanelPointerPressed;
|
||||||
_dragPanel.PointerMoved += OnDragPanelPointerMoved;
|
_dragPanel.PointerMoved += OnDragPanelPointerMoved;
|
||||||
_dragPanel.PointerReleased += OnDragPanelPointerReleased;
|
_dragPanel.PointerReleased += OnDragPanelPointerReleased;
|
||||||
}
|
}
|
||||||
@@ -185,7 +200,7 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
|
|||||||
{
|
{
|
||||||
CommitInput(true);
|
CommitInput(true);
|
||||||
base.OnLostFocus(e);
|
base.OnLostFocus(e);
|
||||||
if(AllowDrag && _dragPanel is not null)
|
if (AllowDrag && _dragPanel is not null)
|
||||||
{
|
{
|
||||||
_dragPanel.IsVisible = true;
|
_dragPanel.IsVisible = true;
|
||||||
}
|
}
|
||||||
@@ -237,7 +252,7 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
|
|||||||
private void OnDragPanelPointerMoved(object sender, PointerEventArgs e)
|
private void OnDragPanelPointerMoved(object sender, PointerEventArgs e)
|
||||||
{
|
{
|
||||||
if (!AllowDrag || IsReadOnly) return;
|
if (!AllowDrag || IsReadOnly) return;
|
||||||
if(!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) return;
|
if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) return;
|
||||||
var point = e.GetPosition(this);
|
var point = e.GetPosition(this);
|
||||||
var delta = point - _point;
|
var delta = point - _point;
|
||||||
if (delta is null)
|
if (delta is null)
|
||||||
@@ -245,13 +260,15 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int d = GetDelta(delta.Value);
|
int d = GetDelta(delta.Value);
|
||||||
if(d > 0)
|
if (d > 0)
|
||||||
{
|
{
|
||||||
Increase();
|
if (_canIncrease)
|
||||||
|
Increase();
|
||||||
}
|
}
|
||||||
else if (d < 0)
|
else if (d < 0)
|
||||||
{
|
{
|
||||||
Decrease();
|
if (_canDecrease)
|
||||||
|
Decrease();
|
||||||
}
|
}
|
||||||
_point = point;
|
_point = point;
|
||||||
}
|
}
|
||||||
@@ -307,8 +324,35 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
|
|||||||
public abstract void Clear();
|
public abstract void Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComparable<T>
|
public abstract class NumericUpDownBase<T> : NumericUpDown where T : struct, IComparable<T>
|
||||||
{
|
{
|
||||||
|
protected static string TrimString(string? text, NumberStyles numberStyles)
|
||||||
|
{
|
||||||
|
text = text!.Trim();
|
||||||
|
if (text.Contains("_")) // support _ like 0x1024_1024(hex), 10_24 (normal)
|
||||||
|
{
|
||||||
|
text = text.Replace("_", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((numberStyles & NumberStyles.AllowHexSpecifier) != 0)
|
||||||
|
{
|
||||||
|
if (text.StartsWith("0X") || text.StartsWith("0x")) // support 0x hex while user input
|
||||||
|
{
|
||||||
|
text = text.Substring(2);
|
||||||
|
}
|
||||||
|
else if (text.StartsWith("h") || text.StartsWith("H")) // support hex while user input
|
||||||
|
{
|
||||||
|
text = text.Substring(1);
|
||||||
|
}
|
||||||
|
else if (text.StartsWith("h'") || text.StartsWith("H'")) // support hex while user input
|
||||||
|
{
|
||||||
|
text = text.Substring(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<T?> ValueProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T?>(
|
public static readonly StyledProperty<T?> ValueProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T?>(
|
||||||
nameof(Value), defaultBindingMode: BindingMode.TwoWay);
|
nameof(Value), defaultBindingMode: BindingMode.TwoWay);
|
||||||
|
|
||||||
@@ -319,7 +363,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<T> MaximumProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T>(
|
public static readonly StyledProperty<T> MaximumProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T>(
|
||||||
nameof(Maximum), defaultBindingMode:BindingMode.TwoWay, coerce: CoerceMaximum);
|
nameof(Maximum), defaultBindingMode: BindingMode.TwoWay, coerce: CoerceMaximum);
|
||||||
|
|
||||||
public T Maximum
|
public T Maximum
|
||||||
{
|
{
|
||||||
@@ -328,7 +372,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<T> MinimumProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T>(
|
public static readonly StyledProperty<T> MinimumProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T>(
|
||||||
nameof(Minimum), defaultBindingMode:BindingMode.TwoWay, coerce: CoerceMinimum);
|
nameof(Minimum), defaultBindingMode: BindingMode.TwoWay, coerce: CoerceMinimum);
|
||||||
|
|
||||||
public T Minimum
|
public T Minimum
|
||||||
{
|
{
|
||||||
@@ -416,7 +460,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
|
|||||||
StepProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.ChangeToSetSpinDirection(e));
|
StepProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.ChangeToSetSpinDirection(e));
|
||||||
MaximumProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.OnConstraintChanged(e));
|
MaximumProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.OnConstraintChanged(e));
|
||||||
MinimumProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.OnConstraintChanged(e));
|
MinimumProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.OnConstraintChanged(e));
|
||||||
ValueProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.OnValueChanged(e) );
|
ValueProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.OnValueChanged(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnConstraintChanged(AvaloniaPropertyChangedEventArgs avaloniaPropertyChangedEventArgs)
|
private void OnConstraintChanged(AvaloniaPropertyChangedEventArgs avaloniaPropertyChangedEventArgs)
|
||||||
@@ -474,6 +518,8 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
|
|||||||
protected override void SetValidSpinDirection()
|
protected override void SetValidSpinDirection()
|
||||||
{
|
{
|
||||||
var validDirection = ValidSpinDirections.None;
|
var validDirection = ValidSpinDirections.None;
|
||||||
|
_canIncrease = false;
|
||||||
|
_canDecrease = false;
|
||||||
if (!IsReadOnly)
|
if (!IsReadOnly)
|
||||||
{
|
{
|
||||||
if (Value is null)
|
if (Value is null)
|
||||||
@@ -483,11 +529,13 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
|
|||||||
if (Value.HasValue && Value.Value.CompareTo(Maximum) < 0)
|
if (Value.HasValue && Value.Value.CompareTo(Maximum) < 0)
|
||||||
{
|
{
|
||||||
validDirection |= ValidSpinDirections.Increase;
|
validDirection |= ValidSpinDirections.Increase;
|
||||||
|
_canIncrease = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Value.HasValue && Value.Value.CompareTo(Minimum) > 0)
|
if (Value.HasValue && Value.Value.CompareTo(Minimum) > 0)
|
||||||
{
|
{
|
||||||
validDirection |= ValidSpinDirections.Decrease;
|
validDirection |= ValidSpinDirections.Decrease;
|
||||||
|
_canDecrease = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_spinner != null)
|
if (_spinner != null)
|
||||||
@@ -516,7 +564,14 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
|
|||||||
}
|
}
|
||||||
if (!Equals(newValue, Value))
|
if (!Equals(newValue, Value))
|
||||||
{
|
{
|
||||||
SetCurrentValue(ValueProperty, newValue);
|
if (Equals(Clamp(newValue, Maximum, Minimum), newValue))
|
||||||
|
{
|
||||||
|
SetCurrentValue(ValueProperty, newValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parsedTextIsValid = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -530,7 +585,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
|
|||||||
if (forceTextUpdate)
|
if (forceTextUpdate)
|
||||||
{
|
{
|
||||||
var newText = ConvertValueToText(Value);
|
var newText = ConvertValueToText(Value);
|
||||||
if (_textBox!= null && !Equals(_textBox.Text, newText))
|
if (_textBox != null && !Equals(_textBox.Text, newText))
|
||||||
{
|
{
|
||||||
_textBox.Text = newText;
|
_textBox.Text = newText;
|
||||||
_textBox.CaretIndex = newText?.Length ?? 0;
|
_textBox.CaretIndex = newText?.Length ?? 0;
|
||||||
@@ -568,6 +623,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
text = TrimString(text, ParsingNumberStyle);
|
||||||
if (!ParseText(text, out var outputValue))
|
if (!ParseText(text, out var outputValue))
|
||||||
{
|
{
|
||||||
throw new InvalidDataException("Input string was not in a correct format.");
|
throw new InvalidDataException("Input string was not in a correct format.");
|
||||||
|
|||||||
Reference in New Issue
Block a user