314 lines
10 KiB
C#
314 lines
10 KiB
C#
using AuroraUIComponent.UserControls.Dialog;
|
|
using System;
|
|
using System.Globalization;
|
|
using System.Text;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
|
|
namespace AuroraUIComponent.UserControls
|
|
{
|
|
public abstract class CustomControlBase<TSubClass> : Control
|
|
{
|
|
static CustomControlBase()
|
|
{
|
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(TSubClass),
|
|
new FrameworkPropertyMetadata(typeof(TSubClass)));
|
|
LoadResourceDictionary();
|
|
}
|
|
|
|
private static void LoadResourceDictionary()
|
|
{
|
|
Uri resourceLocater =
|
|
new Uri($"/AuroraUIComponent;component/UserControls/Input/{typeof(TSubClass).Name}Resources.xaml",
|
|
UriKind.Relative);
|
|
ResourceDictionary resourceDictionary = new ResourceDictionary { Source = resourceLocater };
|
|
|
|
Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
|
|
}
|
|
|
|
public override void OnApplyTemplate()
|
|
{
|
|
base.OnApplyTemplate();
|
|
|
|
InitializeControlReferences();
|
|
|
|
InitializeControls();
|
|
}
|
|
|
|
protected abstract void InitializeControlReferences();
|
|
protected abstract void InitializeControls();
|
|
|
|
protected TType GetChild<TType>(string xamlElementName)
|
|
{
|
|
return (TType)Convert.ChangeType(GetTemplateChild(xamlElementName), typeof(TType));
|
|
}
|
|
}
|
|
|
|
public class UCNumericTextBox : UCKeyValueNumber<UCNumericTextBox>
|
|
{
|
|
private static readonly Thickness UnitPadding = new Thickness(2, 0, 15, 0);
|
|
private string _rangeStr;
|
|
|
|
public static readonly DependencyProperty MaximumProperty =
|
|
DependencyProperty.Register(
|
|
nameof(Maximum),
|
|
typeof(decimal),
|
|
typeof(UCNumericTextBox),
|
|
new PropertyMetadata(
|
|
decimal.MaxValue, OnMaximumChanged, CoerceMaximumCallback)
|
|
);
|
|
|
|
public decimal Maximum {
|
|
get { return (decimal)GetValue(MaximumProperty); }
|
|
set {
|
|
SetValue(MaximumProperty, value);
|
|
}
|
|
}
|
|
|
|
private static void OnMaximumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
var control = (UCNumericTextBox)d;
|
|
var maxValue = (decimal)e.NewValue;
|
|
|
|
// If maxValue steps over Minimum, shift it
|
|
if (maxValue < control.Minimum) {
|
|
control.Minimum = maxValue;
|
|
}
|
|
|
|
// desired 값이 경계 내에 존재하도록 강제하는 로직..
|
|
if (maxValue <= control.Value) {
|
|
control.Value = maxValue;
|
|
}
|
|
}
|
|
|
|
private static object CoerceMaximumCallback(DependencyObject d, object baseValue)
|
|
{
|
|
var control = (UCNumericTextBox)d;
|
|
var maxValue = (decimal)baseValue;
|
|
control.SetMaximum = true;
|
|
|
|
return maxValue;
|
|
}
|
|
|
|
public static readonly DependencyProperty MinimumProperty =
|
|
DependencyProperty.Register(
|
|
nameof(Minimum),
|
|
typeof(decimal),
|
|
typeof(UCNumericTextBox),
|
|
new PropertyMetadata(
|
|
Decimal.MinValue, OnMinimumChanged, CoerceMinimumCallback)
|
|
);
|
|
|
|
public decimal Minimum {
|
|
get { return (decimal)GetValue(MinimumProperty); }
|
|
set {
|
|
SetValue(MinimumProperty, value);
|
|
}
|
|
}
|
|
|
|
private static void OnMinimumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
var control = (UCNumericTextBox)d;
|
|
var minValue = (decimal)e.NewValue;
|
|
|
|
// If minValue steps over Maximum, shift it
|
|
if (minValue > control.Maximum) {
|
|
control.Maximum = minValue;
|
|
}
|
|
|
|
if (minValue >= control.Value) {
|
|
control.Value = minValue;
|
|
}
|
|
}
|
|
|
|
private static object CoerceMinimumCallback(DependencyObject d, object baseValue)
|
|
{
|
|
var control = (UCNumericTextBox)d;
|
|
var minValue = (decimal)baseValue;
|
|
control.SetMinimum = true;
|
|
|
|
return minValue;
|
|
}
|
|
|
|
// min, max 둘 중 하나 이상 설정됐을 때만 Tooltip 보임
|
|
private bool _setMinimum;
|
|
public bool SetMinimum {
|
|
get => _setMinimum; set {
|
|
_setMinimum = value;
|
|
}
|
|
}
|
|
|
|
private bool _setMaximum;
|
|
public bool SetMaximum {
|
|
get => _setMaximum; set {
|
|
_setMaximum = value;
|
|
}
|
|
}
|
|
|
|
private void UpdateTooltipRange()
|
|
{
|
|
if (SetMinimum || SetMaximum) {
|
|
StringBuilder range = new StringBuilder();
|
|
if (SetMinimum) range.Append("Min: ").Append(Minimum);
|
|
if (SetMinimum && SetMaximum) range.Append(", ");
|
|
if (SetMaximum) range.Append("Max: ").Append(Maximum);
|
|
_rangeStr = range.ToString();
|
|
}
|
|
}
|
|
|
|
private Grid _gridParent;
|
|
private TextBlock _textKey;
|
|
private TextBox _textValue;
|
|
private Button _buttonMouse;
|
|
private ToolTip _tooltipRange;
|
|
private Border _borderKey;
|
|
private TextBlock _textUnit;
|
|
private Border _valueBorder;
|
|
|
|
public UCNumericTextBox()
|
|
{
|
|
Loaded += OnControlLoaded;
|
|
DataContextChanged += OnDataContextChanged;
|
|
}
|
|
|
|
private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
UpdateLayout();
|
|
}
|
|
|
|
protected void OnControlLoaded(object sender, RoutedEventArgs e)
|
|
{
|
|
UpdateLayout();
|
|
}
|
|
|
|
protected override void InitializeControlReferences()
|
|
{
|
|
// class 내에서 참조할 Control들의 레퍼런스를 업데이트 (미리 변수 선언 필요)
|
|
_gridParent = GetChild<Grid>("GridParent");
|
|
_textKey = GetChild<TextBlock>("TextKey");
|
|
_textValue = GetChild<TextBox>("TextValue");
|
|
_buttonMouse = GetChild<Button>("ButtonMouse");
|
|
_tooltipRange = GetChild<ToolTip>("TooltipRange");
|
|
_borderKey = GetChild<Border>("BorderKey");
|
|
_textUnit = GetChild<TextBlock>("TextUnit");
|
|
_valueBorder = GetChild<Border>("ValueBorder");
|
|
}
|
|
|
|
protected override void InitializeControls()
|
|
{
|
|
ShowKeypad = false; // AA customization
|
|
|
|
_textValue.LostFocus += TextBoxOnLostFocus;
|
|
_textValue.IsReadOnly = IsReadOnly;
|
|
_textValue.FontSize = ValueTextSize;
|
|
_textValue.Padding = string.IsNullOrEmpty(Unit) ? UCCommonDef.UCKeyValueCommon.DEFAULT_TEXTBOX_PADDING : UnitPadding;
|
|
|
|
if (string.IsNullOrEmpty(KeyText)) {
|
|
// KeyText 가 없으므로, 해당 grid 의 width 를 0 으로 만든다
|
|
KeyTextWidth = "0px";
|
|
_borderKey.Visibility = Visibility.Collapsed;
|
|
}
|
|
|
|
if (ShowKeypad && !IsReadOnly) {
|
|
_buttonMouse.Visibility = Visibility.Visible;
|
|
_buttonMouse.Click += Button_Click;
|
|
_buttonMouse.Content = (Image)FindResource("Electronics_MouseDrawingImage");
|
|
} else {
|
|
_buttonMouse.Visibility = Visibility.Collapsed;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(Unit)) _textUnit.Visibility = Visibility.Collapsed;
|
|
|
|
_valueBorder.PreviewMouseLeftButtonDown += Text_PreviewMouseLeftButtonDown;
|
|
|
|
if (SetMinimum || SetMaximum) {
|
|
UpdateTooltipRange();
|
|
_tooltipRange.Visibility = Visibility.Visible;
|
|
_tooltipRange.Content = _rangeStr;
|
|
}
|
|
}
|
|
|
|
private void TextBoxOnLostFocus(object sender, RoutedEventArgs e)
|
|
{
|
|
decimal value = ParseString2Decimal(_textValue.Text);
|
|
CoerceValue2Bounds(ref value);
|
|
|
|
Value = value;
|
|
}
|
|
|
|
protected override void ChangeThousandSeparator(decimal value)
|
|
{
|
|
//change formatting based on this flag
|
|
if (ThousandSeparator) {
|
|
if (_textValue != null) {
|
|
_textValue.Text = value.ToString("N", Culture);
|
|
}
|
|
} else {
|
|
if (_textValue != null) {
|
|
_textValue.Text = value.ToString($"F", Culture);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void KeyTextChanged(string newValue)
|
|
{
|
|
if (!string.IsNullOrEmpty(newValue) && _gridParent != null) {
|
|
// KeyText가 있으면, 해당 grid 의 width 를 1* 으로 만든다
|
|
_gridParent.ColumnDefinitions[0].Width = new GridLength(1, GridUnitType.Star);
|
|
}
|
|
}
|
|
|
|
protected override void KeyTextFGColorChanged(Brush brush)
|
|
{
|
|
_textKey.Foreground = brush;
|
|
}
|
|
|
|
private void Button_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
ShowWinCalculator(_textValue);
|
|
}
|
|
|
|
private void Text_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
if (IsReadOnly) return;
|
|
e.Handled = true;
|
|
ShowWinCalculator(_textValue);
|
|
}
|
|
|
|
protected void ShowWinCalculator(TextBox text)
|
|
{
|
|
WinCalculator window = new WinCalculator {
|
|
Foreground = Brushes.White,
|
|
DecimalPlaces = DecimalPlaces,
|
|
IsAllowMinus = true,
|
|
Unit = Unit,
|
|
Value = Value.ToString(CultureInfo.InvariantCulture),
|
|
Owner = Window.GetWindow(this),
|
|
ResultCallback = CalcWindowResult,
|
|
TextRange = _rangeStr
|
|
};
|
|
window.SetWindowControl(Window.GetWindow(this), text);
|
|
window.ShowDialog();
|
|
}
|
|
|
|
private void CalcWindowResult(string strValue)
|
|
{
|
|
decimal value = ParseString2Decimal(strValue);
|
|
CoerceValue2Bounds(ref value);
|
|
|
|
Value = value;
|
|
}
|
|
|
|
private void CoerceValue2Bounds(ref decimal value)
|
|
{
|
|
if (value < Minimum) {
|
|
value = Minimum;
|
|
} else if (value > Maximum) {
|
|
value = Maximum;
|
|
}
|
|
}
|
|
}
|
|
}
|