[#37] Controls: Implement IntegerUpDown
All checks were successful
Test / Run tests (push) Successful in 2m28s
All checks were successful
Test / Run tests (push) Successful in 2m28s
This commit is contained in:
106
Elwig/Controls/IntegerUpDown.cs
Normal file
106
Elwig/Controls/IntegerUpDown.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Controls.Primitives;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace Elwig.Controls {
|
||||||
|
public class IntegerUpDown : TextBox {
|
||||||
|
|
||||||
|
public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register("Miminum", typeof(int?), typeof(IntegerUpDown), new FrameworkPropertyMetadata(null));
|
||||||
|
public int? Minimum {
|
||||||
|
get => (int?)GetValue(MinimumProperty);
|
||||||
|
set => SetValue(MinimumProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(int?), typeof(IntegerUpDown), new FrameworkPropertyMetadata(null));
|
||||||
|
public int? Maximum {
|
||||||
|
get => (int?)GetValue(MaximumProperty);
|
||||||
|
set => SetValue(MaximumProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int? Value {
|
||||||
|
get => int.TryParse(Text, out var res) ? res : null;
|
||||||
|
set => Text = $"{value}";
|
||||||
|
}
|
||||||
|
|
||||||
|
static IntegerUpDown() {
|
||||||
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(IntegerUpDown), new FrameworkPropertyMetadata(typeof(IntegerUpDown)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegerUpDown() {
|
||||||
|
TextChanged += IntegerUpDown_TextChanged;
|
||||||
|
LostFocus += IntegerUpDown_LostFocus;
|
||||||
|
KeyUp += IntegerUpDown_KeyUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnApplyTemplate() {
|
||||||
|
var incButton = GetTemplateChild("IncrementButton") as RepeatButton;
|
||||||
|
var decButton = GetTemplateChild("DecrementButton") as RepeatButton;
|
||||||
|
incButton!.Click += IncrementButton_Click;
|
||||||
|
decButton!.Click += DecrementButton_Click;
|
||||||
|
base.OnApplyTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IntegerUpDown_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||||
|
var idx = CaretIndex;
|
||||||
|
Text = new string(Text.Where(char.IsAsciiDigit).Take(4).ToArray());
|
||||||
|
CaretIndex = idx;
|
||||||
|
evt.Handled = !(Value >= Minimum && Value <= Maximum);
|
||||||
|
if (idx >= 4) {
|
||||||
|
if (Value < Minimum) {
|
||||||
|
Value = Minimum;
|
||||||
|
} else if (Value > Maximum) {
|
||||||
|
Value = Maximum;
|
||||||
|
}
|
||||||
|
CaretIndex = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IntegerUpDown_LostFocus(object sender, RoutedEventArgs evt) {
|
||||||
|
if (Value < Minimum) {
|
||||||
|
Value = Minimum;
|
||||||
|
} else if (Value > Maximum) {
|
||||||
|
Value = Maximum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IncrementButton_Click(object sender, RoutedEventArgs evt) {
|
||||||
|
Value = Math.Min((Value ?? 0) + 1, Maximum ?? int.MaxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DecrementButton_Click(object sender, RoutedEventArgs evt) {
|
||||||
|
Value = Math.Max((Value ?? 0) - 1, Minimum ?? int.MinValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IntegerUpDown_KeyUp(object sender, KeyEventArgs evt) {
|
||||||
|
switch (evt.Key) {
|
||||||
|
case Key.Up:
|
||||||
|
case Key.Add:
|
||||||
|
case Key.OemPlus:
|
||||||
|
Value = Math.Min((Value ?? 0) + 1, Maximum ?? int.MaxValue);
|
||||||
|
evt.Handled = true;
|
||||||
|
CaretIndex = 4;
|
||||||
|
break;
|
||||||
|
case Key.Down:
|
||||||
|
case Key.Subtract:
|
||||||
|
case Key.OemMinus:
|
||||||
|
Value = Math.Max((Value ?? 0) - 1, Minimum ?? int.MinValue);
|
||||||
|
evt.Handled = true;
|
||||||
|
CaretIndex = 4;
|
||||||
|
break;
|
||||||
|
case Key.PageUp:
|
||||||
|
Value = Math.Min((Value ?? 0) + 10, Maximum ?? int.MaxValue);
|
||||||
|
evt.Handled = true;
|
||||||
|
CaretIndex = 4;
|
||||||
|
break;
|
||||||
|
case Key.PageDown:
|
||||||
|
Value = Math.Max((Value ?? 0) - 10, Minimum ?? int.MinValue);
|
||||||
|
evt.Handled = true;
|
||||||
|
CaretIndex = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
Elwig/Controls/IntegerUpDown.xaml
Normal file
52
Elwig/Controls/IntegerUpDown.xaml
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:ctrl="clr-namespace:Elwig.Controls">
|
||||||
|
<Style TargetType="ctrl:IntegerUpDown" BasedOn="{StaticResource {x:Type TextBox}}">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="ctrl:IntegerUpDown">
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="18"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Border x:Name="Border" BorderThickness="1,1,0,1"
|
||||||
|
BorderBrush="{Binding Path=BorderBrush, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
|
||||||
|
SnapsToDevicePixels="True" Grid.RowSpan="2">
|
||||||
|
<ScrollViewer x:Name="PART_ContentHost" VerticalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<RepeatButton x:Name="IncrementButton" Padding="0" Height="Auto" Width="Auto" BorderThickness="1,1,1,0"
|
||||||
|
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" Grid.Column="1">
|
||||||
|
<Path x:Name="IconIncrement" Data="M 0,4 L 4,0 L 8,4 Z" Fill="#FF444444"
|
||||||
|
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
</RepeatButton>
|
||||||
|
<RepeatButton x:Name="DecrementButton" Padding="0" Height="Auto" Width="Auto" BorderThickness="1,0,1,1"
|
||||||
|
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1" Grid.Column="1">
|
||||||
|
<Path x:Name="IconDecrement" Data="M 0,0 L 4,4 L 8,0 Z" Fill="#FF444444"
|
||||||
|
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
</RepeatButton>
|
||||||
|
</Grid>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsEnabled" Value="False">
|
||||||
|
<Setter TargetName="Border" Property="BorderBrush" Value="LightGray"/>
|
||||||
|
<Setter TargetName="IconIncrement" Property="Fill" Value="#FF888888"/>
|
||||||
|
<Setter TargetName="IconDecrement" Property="Fill" Value="#FF888888"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Setter Property="TextAlignment" Value="Right"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="IsEnabled" Value="False">
|
||||||
|
<Setter Property="Foreground" Value="Gray"/>
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</ResourceDictionary>
|
@ -1,5 +1,6 @@
|
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
<ResourceDictionary Source="/Elwig;component/Controls/UnitTextBox.xaml"/>
|
<ResourceDictionary Source="/Elwig;component/Controls/UnitTextBox.xaml"/>
|
||||||
|
<ResourceDictionary Source="/Elwig;component/Controls/IntegerUpDown.xaml"/>
|
||||||
</ResourceDictionary.MergedDictionaries>
|
</ResourceDictionary.MergedDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
@ -175,9 +175,9 @@
|
|||||||
</TextBlock>
|
</TextBlock>
|
||||||
</TextBox.ToolTip>
|
</TextBox.ToolTip>
|
||||||
</TextBox>
|
</TextBox>
|
||||||
<xctk:IntegerUpDown x:Name="SeasonInput" Grid.ColumnSpan="3" Height="25" Width="56" FontSize="14" Minimum="1000" Maximum="9999"
|
<ctrl:IntegerUpDown x:Name="SeasonInput" Grid.ColumnSpan="3" Height="25" Width="56" FontSize="14" Minimum="1900" Maximum="9999"
|
||||||
Margin="0,10,100,0" VerticalAlignment="Top" HorizontalAlignment="Right"
|
Margin="0,10,100,0" VerticalAlignment="Top" HorizontalAlignment="Right" Text="2020"
|
||||||
ValueChanged="SeasonInput_ValueChanged"/>
|
TextChanged="SeasonInput_TextChanged"/>
|
||||||
<CheckBox x:Name="TodayOnlyInput" Content="Nur heute"
|
<CheckBox x:Name="TodayOnlyInput" Content="Nur heute"
|
||||||
HorizontalAlignment="Right" Margin="0,7,18,0" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="2"
|
HorizontalAlignment="Right" Margin="0,7,18,0" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="2"
|
||||||
Checked="TodayOnlyInput_Changed" Unchecked="TodayOnlyInput_Changed"/>
|
Checked="TodayOnlyInput_Changed" Unchecked="TodayOnlyInput_Changed"/>
|
||||||
|
@ -1344,8 +1344,8 @@ namespace Elwig.Windows {
|
|||||||
await RefreshDeliveryListQuery(true);
|
await RefreshDeliveryListQuery(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SeasonInput_ValueChanged(object sender, RoutedEventArgs evt) {
|
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||||
if (SeasonInput.Value == null) return;
|
if (SeasonInput.Value == null || TodayOnlyInput == null || AllSeasonsInput == null) return;
|
||||||
TodayOnlyInput.IsChecked = false;
|
TodayOnlyInput.IsChecked = false;
|
||||||
AllSeasonsInput.IsChecked = false;
|
AllSeasonsInput.IsChecked = false;
|
||||||
await RefreshDeliveryListQuery();
|
await RefreshDeliveryListQuery();
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:Elwig.Windows"
|
xmlns:local="clr-namespace:Elwig.Windows"
|
||||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
||||||
Title="Elwig" Height="390" Width="520" ResizeMode="CanMinimize"
|
Title="Elwig" Height="390" Width="520" ResizeMode="CanMinimize"
|
||||||
Loaded="Window_Loaded" Closing="Window_Closing">
|
Loaded="Window_Loaded" Closing="Window_Closing">
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
@ -71,9 +71,9 @@
|
|||||||
<Grid>
|
<Grid>
|
||||||
<Border BorderBrush="LightGray" BorderThickness="1"/>
|
<Border BorderBrush="LightGray" BorderThickness="1"/>
|
||||||
<Label Content="Saison:" Margin="0,10,100,0" VerticalAlignment="Top" HorizontalAlignment="Center" Padding="2,4,2,4" Height="25"/>
|
<Label Content="Saison:" Margin="0,10,100,0" VerticalAlignment="Top" HorizontalAlignment="Center" Padding="2,4,2,4" Height="25"/>
|
||||||
<xctk:IntegerUpDown Name="SeasonInput" Height="25" Width="56" FontSize="14" Minimum="1000" Maximum="9999"
|
<ctrl:IntegerUpDown x:Name="SeasonInput" Height="25" Width="56" FontSize="14" Minimum="1900" Maximum="9999"
|
||||||
Margin="0,10,0,0" VerticalAlignment="Top" HorizontalAlignment="Center"
|
Margin="0,10,0,0" VerticalAlignment="Top" HorizontalAlignment="Center"
|
||||||
ValueChanged="SeasonInput_ValueChanged"/>
|
TextChanged="SeasonInput_TextChanged"/>
|
||||||
|
|
||||||
<Button x:Name="DeliveryConfirmationButton" Content="Anlieferungsbestätigung"
|
<Button x:Name="DeliveryConfirmationButton" Content="Anlieferungsbestätigung"
|
||||||
Click="DeliveryConfirmationButton_Click"
|
Click="DeliveryConfirmationButton_Click"
|
||||||
|
@ -14,6 +14,7 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
namespace Elwig.Windows {
|
namespace Elwig.Windows {
|
||||||
@ -147,7 +148,7 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override Task OnRenewContext(AppDbContext ctx) {
|
protected override Task OnRenewContext(AppDbContext ctx) {
|
||||||
SeasonInput_ValueChanged(null, null);
|
SeasonInput_TextChanged(null, null);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +160,7 @@ namespace Elwig.Windows {
|
|||||||
Height = 390;
|
Height = 390;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SeasonInput_ValueChanged(object? sender, RoutedEventArgs? evt) {
|
private async void SeasonInput_TextChanged(object? sender, TextChangedEventArgs? evt) {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var s0 = await ctx.Seasons.FindAsync(SeasonInput.Value);
|
var s0 = await ctx.Seasons.FindAsync(SeasonInput.Value);
|
||||||
var valid = (s0 != null);
|
var valid = (s0 != null);
|
||||||
|
Reference in New Issue
Block a user