Browse Source

TextConverter property for finer control over NumericUpDown text display (#8839)

* Added TextConverter property to NumericUpDown

* Added a hex NumericUpDown sample to ControlCatalog

* Requested changes to conversion calls

* Fixed NumericUpDown::OnTextConverterChanged logic
pull/8846/head
hacklex 4 years ago
committed by GitHub
parent
commit
0b01a51c9e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 34
      samples/ControlCatalog/Converter/HexConverter.cs
  2. 12
      samples/ControlCatalog/Pages/NumericUpDownPage.xaml
  3. 61
      src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs

34
samples/ControlCatalog/Converter/HexConverter.cs

@ -0,0 +1,34 @@
using System;
using System.Globalization;
using Avalonia;
using Avalonia.Data.Converters;
namespace ControlCatalog.Converter;
public class HexConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var str = value?.ToString();
if (str == null)
return AvaloniaProperty.UnsetValue;
if (int.TryParse(str, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int x))
return (decimal)x;
return AvaloniaProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
if (value is decimal d)
return ((int)d).ToString("X8");
return AvaloniaProperty.UnsetValue;
}
catch
{
return AvaloniaProperty.UnsetValue;
}
}
}

12
samples/ControlCatalog/Pages/NumericUpDownPage.xaml

@ -1,6 +1,7 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=netstandard"
xmlns:converter="clr-namespace:ControlCatalog.Converter"
x:Class="ControlCatalog.Pages.NumericUpDownPage">
<StackPanel Orientation="Vertical" Spacing="4"
MaxWidth="800">
@ -97,6 +98,17 @@
</DataValidationErrors.Error>
</NumericUpDown>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="10">
<Label Target="HexUpDown" FontSize="14" FontWeight="Bold" VerticalAlignment="Center">NumericUpDown in HEX mode:</Label>
<NumericUpDown x:Name="HexUpDown" Value="0"
VerticalAlignment="Center">
<NumericUpDown.TextConverter>
<converter:HexConverter></converter:HexConverter>
</NumericUpDown.TextConverter>
</NumericUpDown>
</StackPanel>
</WrapPanel>
</StackPanel>

61
src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs

@ -5,6 +5,7 @@ using System.Linq;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
@ -96,6 +97,13 @@ namespace Avalonia.Controls
AvaloniaProperty.RegisterDirect<NumericUpDown, string?>(nameof(Text), o => o.Text, (o, v) => o.Text = v,
defaultBindingMode: BindingMode.TwoWay, enableDataValidation: true);
/// <summary>
/// Defines the <see cref="TextConverter"/> property.
/// </summary>
public static readonly DirectProperty<NumericUpDown, IValueConverter?> TextConverterProperty =
AvaloniaProperty.RegisterDirect<NumericUpDown, IValueConverter?>(nameof(TextConverter),
updown => updown.TextConverter, (o, v) => o.TextConverter = v, null, BindingMode.OneWay, false);
/// <summary>
/// Defines the <see cref="Value"/> property.
/// </summary>
@ -125,6 +133,7 @@ namespace Avalonia.Controls
private decimal? _value;
private string? _text;
private IValueConverter? _textConverter;
private bool _internalValueSet;
private bool _clipValueToMinMax;
private bool _isSyncingTextAndValueProperties;
@ -235,6 +244,8 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the parsing style (AllowLeadingWhite, Float, AllowHexSpecifier, ...). By default, Any.
/// Note that Hex style does not work with decimal.
/// For hexadecimal display, use <see cref="TextConverter"/>.
/// </summary>
public NumberStyles ParsingNumberStyle
{
@ -251,6 +262,17 @@ namespace Avalonia.Controls
set { SetAndRaise(TextProperty, ref _text, value); }
}
/// <summary>
/// Gets or sets the custom bidirectional Text-Value converter.
/// Non-null converter overrides <see cref="ParsingNumberStyle"/>, providing finer control over
/// string representation of the underlying value.
/// </summary>
public IValueConverter? TextConverter
{
get { return _textConverter; }
set { SetAndRaise(TextConverterProperty, ref _textConverter, value); }
}
/// <summary>
/// Gets or sets the value.
/// </summary>
@ -319,6 +341,7 @@ namespace Avalonia.Controls
MaximumProperty.Changed.Subscribe(OnMaximumChanged);
MinimumProperty.Changed.Subscribe(OnMinimumChanged);
TextProperty.Changed.Subscribe(OnTextChanged);
TextConverterProperty.Changed.Subscribe(OnTextConverterChanged);
ValueProperty.Changed.Subscribe(OnValueChanged);
}
@ -485,6 +508,19 @@ namespace Avalonia.Controls
SyncTextAndValueProperties(true, Text);
}
}
/// <summary>
/// Called when the <see cref="Text"/> property value changed.
/// </summary>
/// <param name="oldValue">The old value.</param>
/// <param name="newValue">The new value.</param>
protected virtual void OnTextConverterChanged(IValueConverter? oldValue, IValueConverter? newValue)
{
if (IsInitialized)
{
SyncTextAndValueProperties(false, null);
}
}
/// <summary>
/// Called when the <see cref="Value"/> property value changed.
@ -612,6 +648,10 @@ namespace Avalonia.Controls
/// <returns></returns>
private string? ConvertValueToText()
{
if (TextConverter != null)
{
return TextConverter.ConvertBack(Value, typeof(string), null, CultureInfo.CurrentCulture)?.ToString();
}
//Manage FormatString of type "{}{0:N2} °" (in xaml) or "{0:N2} °" in code-behind.
if (FormatString.Contains("{0"))
{
@ -788,6 +828,21 @@ namespace Avalonia.Controls
}
}
/// <summary>
/// Called when the <see cref="TextConverter"/> property value changed.
/// </summary>
/// <param name="e">The event args.</param>
private static void OnTextConverterChanged(AvaloniaPropertyChangedEventArgs e)
{
if (e.Sender is NumericUpDown upDown)
{
var oldValue = (IValueConverter?)e.OldValue;
var newValue = (IValueConverter?)e.NewValue;
upDown.OnTextConverterChanged(oldValue, newValue);
}
}
/// <summary>
/// Called when the <see cref="Value"/> property value changed.
/// </summary>
@ -1012,6 +1067,12 @@ namespace Avalonia.Controls
return null;
}
if (TextConverter != null)
{
var valueFromText = TextConverter.Convert(text, typeof(decimal?), null, CultureInfo.CurrentCulture);
return (decimal?)valueFromText;
}
if (IsPercent(FormatString))
{
result = ParsePercent(text, NumberFormat);

Loading…
Cancel
Save