mirror of
https://github.com/holgerb83/ModernWpfPlayground.git
synced 2025-04-19 23:03:49 +02:00
file-scoped namespaces and update of modernwpfui
This commit is contained in:
parent
02e3af3dcb
commit
644e2628e3
@ -14,9 +14,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FastMember" Version="1.5.0" />
|
<PackageReference Include="FastMember" Version="1.5.0" />
|
||||||
<PackageReference Include="Hardcodet.NotifyIcon.Wpf" Version="1.1.0" />
|
<PackageReference Include="Hardcodet.NotifyIcon.Wpf" Version="1.1.0" />
|
||||||
<PackageReference Include="ModernWpfUis" Version="1.2.0" />
|
<PackageReference Include="ModernWpfUI" Version="0.9.7-preview.2" />
|
||||||
<PackageReference Include="MvvmGen" Version="1.1.2" />
|
<PackageReference Include="MvvmGen" Version="1.1.5" />
|
||||||
<PackageReference Include="YamlDotNet" Version="11.2.1" />
|
<PackageReference Include="YamlDotNet" Version="12.0.2" />
|
||||||
<PackageReference Include="MahApps.Metro.IconPacks.FontAwesome" Version="4.11.0" />
|
<PackageReference Include="MahApps.Metro.IconPacks.FontAwesome" Version="4.11.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -1,30 +1,29 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
|
||||||
namespace ModernWpfPlayground.Types
|
namespace ModernWpfPlayground.Types;
|
||||||
{
|
|
||||||
public enum AccentColors
|
|
||||||
{
|
|
||||||
Green,
|
|
||||||
Yellow,
|
|
||||||
Blue,
|
|
||||||
Purple,
|
|
||||||
Red
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class AccentColorExtension
|
public enum AccentColors
|
||||||
|
{
|
||||||
|
Green,
|
||||||
|
Yellow,
|
||||||
|
Blue,
|
||||||
|
Purple,
|
||||||
|
Red
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AccentColorExtension
|
||||||
|
{
|
||||||
|
public static Color ToWindowsColor(this AccentColors accentColor)
|
||||||
{
|
{
|
||||||
public static Color ToWindowsColor(this AccentColors accentColor)
|
return accentColor switch
|
||||||
{
|
{
|
||||||
return accentColor switch
|
AccentColors.Green => Color.FromRgb(0, 86, 76),
|
||||||
{
|
AccentColors.Yellow => Color.FromRgb(164, 144, 0),
|
||||||
AccentColors.Green => Color.FromRgb(0, 86, 76),
|
AccentColors.Blue => Color.FromRgb(0, 120, 215),
|
||||||
AccentColors.Yellow => Color.FromRgb(164, 144, 0),
|
AccentColors.Purple => Color.FromRgb(104, 33, 122),
|
||||||
AccentColors.Blue => Color.FromRgb(0, 120, 215),
|
AccentColors.Red => Color.FromRgb(183, 71, 42),
|
||||||
AccentColors.Purple => Color.FromRgb(104, 33, 122),
|
_ => throw new ArgumentOutOfRangeException(nameof(accentColor), accentColor, null)
|
||||||
AccentColors.Red => Color.FromRgb(183, 71, 42),
|
};
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(accentColor), accentColor, null)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,44 +6,43 @@ using System.Linq;
|
|||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using System.Windows.Markup;
|
using System.Windows.Markup;
|
||||||
|
|
||||||
namespace Controls
|
namespace Controls;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts enums to a List with KeyValuePairs.
|
||||||
|
/// </summary>
|
||||||
|
public class EnumToItemSourceConverter : MarkupExtension, IValueConverter
|
||||||
{
|
{
|
||||||
/// <summary>
|
private static EnumToItemSourceConverter? _converter;
|
||||||
/// Converts enums to a List with KeyValuePairs.
|
|
||||||
/// </summary>
|
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
public class EnumToItemSourceConverter : MarkupExtension, IValueConverter
|
|
||||||
{
|
{
|
||||||
private static EnumToItemSourceConverter? _converter;
|
if (value is not Enum) return Binding.DoNothing;
|
||||||
|
return (from object enumValue in Enum.GetValues(value.GetType())
|
||||||
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
select new KeyValuePair<string, object>(GetDescription(enumValue), enumValue)).ToList();
|
||||||
{
|
|
||||||
if (value is not Enum) return Binding.DoNothing;
|
|
||||||
return (from object enumValue in Enum.GetValues(value.GetType())
|
|
||||||
select new KeyValuePair<string, object>(GetDescription(enumValue), enumValue)).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the content of a description attribute of an enum.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private static string GetDescription(object value)
|
|
||||||
{
|
|
||||||
if (value is not Enum enumValue) return string.Empty;
|
|
||||||
var descriptionAttribute = enumValue.GetType()
|
|
||||||
.GetField(enumValue.ToString())?
|
|
||||||
.GetCustomAttributes(false)
|
|
||||||
.OfType<DescriptionAttribute>()
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
return descriptionAttribute?.Description ?? value.ToString() ?? string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
|
||||||
{
|
|
||||||
return Binding.DoNothing;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override object ProvideValue(IServiceProvider serviceProvider) => _converter ??= new EnumToItemSourceConverter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the content of a description attribute of an enum.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static string GetDescription(object value)
|
||||||
|
{
|
||||||
|
if (value is not Enum enumValue) return string.Empty;
|
||||||
|
var descriptionAttribute = enumValue.GetType()
|
||||||
|
.GetField(enumValue.ToString())?
|
||||||
|
.GetCustomAttributes(false)
|
||||||
|
.OfType<DescriptionAttribute>()
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
return descriptionAttribute?.Description ?? value.ToString() ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
return Binding.DoNothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ProvideValue(IServiceProvider serviceProvider) => _converter ??= new EnumToItemSourceConverter();
|
||||||
}
|
}
|
@ -2,42 +2,41 @@
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Markup;
|
using System.Windows.Markup;
|
||||||
|
|
||||||
namespace Controls
|
namespace Controls;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for <see cref="MagicSymbolControl"/>
|
||||||
|
/// </summary>
|
||||||
|
[ContentProperty(nameof(Symbol))]
|
||||||
|
public class MagicSymbolControl : ContentControl
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaction logic for <see cref="MagicSymbolControl"/>
|
/// Dependency property for <see cref="Symbol"/> property
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ContentProperty(nameof(Symbol))]
|
public static readonly DependencyProperty SymbolProperty = DependencyProperty.Register(nameof(Symbol), typeof(object), typeof(MagicSymbolControl), new PropertyMetadata(default, PropertyChangedCallback));
|
||||||
public class MagicSymbolControl : ContentControl
|
|
||||||
|
private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
/// <summary>
|
if (d is MagicSymbolControl magic)
|
||||||
/// Dependency property for <see cref="Symbol"/> property
|
|
||||||
/// </summary>
|
|
||||||
public static readonly DependencyProperty SymbolProperty = DependencyProperty.Register(nameof(Symbol), typeof(object), typeof(MagicSymbolControl), new PropertyMetadata(default, PropertyChangedCallback));
|
|
||||||
|
|
||||||
private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
||||||
{
|
{
|
||||||
if (d is MagicSymbolControl magic)
|
magic.Content = MagicSymbolConverter.ConvertToFrameworkElement(e.NewValue);
|
||||||
{
|
|
||||||
magic.Content = MagicSymbolConverter.ConvertToFrameworkElement(e.NewValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Symbol to show
|
|
||||||
/// </summary>
|
|
||||||
public object Symbol
|
|
||||||
{
|
|
||||||
get => GetValue(SymbolProperty);
|
|
||||||
set => SetValue(SymbolProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new instance of <see cref="MagicSymbolControl"/>
|
|
||||||
/// </summary>
|
|
||||||
public MagicSymbolControl()
|
|
||||||
{
|
|
||||||
Focusable = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Symbol to show
|
||||||
|
/// </summary>
|
||||||
|
public object Symbol
|
||||||
|
{
|
||||||
|
get => GetValue(SymbolProperty);
|
||||||
|
set => SetValue(SymbolProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="MagicSymbolControl"/>
|
||||||
|
/// </summary>
|
||||||
|
public MagicSymbolControl()
|
||||||
|
{
|
||||||
|
Focusable = false;
|
||||||
|
}
|
||||||
}
|
}
|
@ -8,145 +8,144 @@ using System.Windows.Data;
|
|||||||
using System.Windows.Documents;
|
using System.Windows.Documents;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
|
||||||
namespace Controls
|
namespace Controls;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Magically converts a text to
|
||||||
|
/// </summary>
|
||||||
|
[ValueConversion(typeof(string), typeof(FrameworkElement))]
|
||||||
|
public class MagicSymbolConverter : IValueConverter
|
||||||
{
|
{
|
||||||
/// <summary>
|
private const string NoParseKeyword = "noParse:";
|
||||||
/// Magically converts a text to
|
private const string PathKeyword = "path:";
|
||||||
/// </summary>
|
private const string DynResKeyword = "dynRes:";
|
||||||
[ValueConversion(typeof(string), typeof(FrameworkElement))]
|
|
||||||
public class MagicSymbolConverter : IValueConverter
|
/// <inheritdoc />
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
{
|
{
|
||||||
private const string NoParseKeyword = "noParse:";
|
return ConvertToFrameworkElement(value);
|
||||||
private const string PathKeyword = "path:";
|
|
||||||
private const string DynResKeyword = "dynRes:";
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
|
||||||
{
|
|
||||||
return ConvertToFrameworkElement(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Convert string to Framework element.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static object ConvertToFrameworkElement(object value)
|
|
||||||
{
|
|
||||||
var data = value as string;
|
|
||||||
if (string.IsNullOrWhiteSpace(data)) return value; //maybe not a string. eventually something else.
|
|
||||||
|
|
||||||
if (data.StartsWith(NoParseKeyword, StringComparison.Ordinal)) return data[NoParseKeyword.Length..];
|
|
||||||
|
|
||||||
if (data.StartsWith(PathKeyword, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
var path = data[PathKeyword.Length..];
|
|
||||||
var icon = ObjectImageConverter.GetIcon(Geometry.Parse(path), Brushes.Black);
|
|
||||||
return new Image
|
|
||||||
{
|
|
||||||
Source = icon,
|
|
||||||
HorizontalAlignment = HorizontalAlignment.Right,
|
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
|
||||||
Height = 16
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.StartsWith(DynResKeyword, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
var resourceKey = data[DynResKeyword.Length..];
|
|
||||||
//get icon from resource dictionary
|
|
||||||
return new Image
|
|
||||||
{
|
|
||||||
Source = Application.Current.FindResource(resourceKey) as ImageSource,
|
|
||||||
HorizontalAlignment = HorizontalAlignment.Right,
|
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
|
||||||
Height = 16
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var textComponents = ParseText(data);
|
|
||||||
return CreateTextBlock(textComponents);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TextBlock CreateTextBlock(IEnumerable<TextComponent> textComponents)
|
|
||||||
{
|
|
||||||
//create text block
|
|
||||||
var block = new TextBlock();
|
|
||||||
foreach (var tc in textComponents)
|
|
||||||
{
|
|
||||||
var run = new Run(tc.Text) {FontFamily = new FontFamily("Palatino Linotype"), FontSize = 16};
|
|
||||||
switch (tc.Style)
|
|
||||||
{
|
|
||||||
case BaselineAlignment.Subscript:
|
|
||||||
run.BaselineAlignment = BaselineAlignment.Subscript;
|
|
||||||
run.FontSize = 12;
|
|
||||||
break;
|
|
||||||
case BaselineAlignment.Superscript:
|
|
||||||
run.BaselineAlignment = BaselineAlignment.Superscript;
|
|
||||||
run.FontSize = 12;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
block.Inlines.Add(run);
|
|
||||||
}
|
|
||||||
|
|
||||||
block.HorizontalAlignment = HorizontalAlignment.Right;
|
|
||||||
block.VerticalAlignment = VerticalAlignment.Center;
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<TextComponent> ParseText(string data)
|
|
||||||
{
|
|
||||||
//parse text
|
|
||||||
var textComponents = new List<TextComponent>();
|
|
||||||
var alignment = BaselineAlignment.Baseline;
|
|
||||||
var snippet = new StringBuilder();
|
|
||||||
foreach (var c in data)
|
|
||||||
{
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '~':
|
|
||||||
if (snippet.Length > 0)
|
|
||||||
{
|
|
||||||
var comp = new TextComponent(snippet.ToString(), alignment);
|
|
||||||
textComponents.Add(comp);
|
|
||||||
snippet.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
alignment = alignment == BaselineAlignment.Subscript
|
|
||||||
? BaselineAlignment.Baseline
|
|
||||||
: BaselineAlignment.Subscript;
|
|
||||||
break;
|
|
||||||
case '^':
|
|
||||||
if (snippet.Length > 0)
|
|
||||||
{
|
|
||||||
var comp = new TextComponent(snippet.ToString(), alignment);
|
|
||||||
textComponents.Add(comp);
|
|
||||||
snippet.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
alignment = alignment == BaselineAlignment.Superscript
|
|
||||||
? BaselineAlignment.Baseline
|
|
||||||
: BaselineAlignment.Superscript;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
snippet.Append(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snippet.Length > 0)
|
|
||||||
{
|
|
||||||
var comp = new TextComponent(snippet.ToString(), alignment);
|
|
||||||
textComponents.Add(comp);
|
|
||||||
snippet.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return textComponents;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
|
||||||
=> Binding.DoNothing;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert string to Framework element.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static object ConvertToFrameworkElement(object value)
|
||||||
|
{
|
||||||
|
var data = value as string;
|
||||||
|
if (string.IsNullOrWhiteSpace(data)) return value; //maybe not a string. eventually something else.
|
||||||
|
|
||||||
|
if (data.StartsWith(NoParseKeyword, StringComparison.Ordinal)) return data[NoParseKeyword.Length..];
|
||||||
|
|
||||||
|
if (data.StartsWith(PathKeyword, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
var path = data[PathKeyword.Length..];
|
||||||
|
var icon = ObjectImageConverter.GetIcon(Geometry.Parse(path), Brushes.Black);
|
||||||
|
return new Image
|
||||||
|
{
|
||||||
|
Source = icon,
|
||||||
|
HorizontalAlignment = HorizontalAlignment.Right,
|
||||||
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
Height = 16
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.StartsWith(DynResKeyword, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
var resourceKey = data[DynResKeyword.Length..];
|
||||||
|
//get icon from resource dictionary
|
||||||
|
return new Image
|
||||||
|
{
|
||||||
|
Source = Application.Current.FindResource(resourceKey) as ImageSource,
|
||||||
|
HorizontalAlignment = HorizontalAlignment.Right,
|
||||||
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
Height = 16
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var textComponents = ParseText(data);
|
||||||
|
return CreateTextBlock(textComponents);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TextBlock CreateTextBlock(IEnumerable<TextComponent> textComponents)
|
||||||
|
{
|
||||||
|
//create text block
|
||||||
|
var block = new TextBlock();
|
||||||
|
foreach (var tc in textComponents)
|
||||||
|
{
|
||||||
|
var run = new Run(tc.Text) {FontFamily = new FontFamily("Palatino Linotype"), FontSize = 16};
|
||||||
|
switch (tc.Style)
|
||||||
|
{
|
||||||
|
case BaselineAlignment.Subscript:
|
||||||
|
run.BaselineAlignment = BaselineAlignment.Subscript;
|
||||||
|
run.FontSize = 12;
|
||||||
|
break;
|
||||||
|
case BaselineAlignment.Superscript:
|
||||||
|
run.BaselineAlignment = BaselineAlignment.Superscript;
|
||||||
|
run.FontSize = 12;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
block.Inlines.Add(run);
|
||||||
|
}
|
||||||
|
|
||||||
|
block.HorizontalAlignment = HorizontalAlignment.Right;
|
||||||
|
block.VerticalAlignment = VerticalAlignment.Center;
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<TextComponent> ParseText(string data)
|
||||||
|
{
|
||||||
|
//parse text
|
||||||
|
var textComponents = new List<TextComponent>();
|
||||||
|
var alignment = BaselineAlignment.Baseline;
|
||||||
|
var snippet = new StringBuilder();
|
||||||
|
foreach (var c in data)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '~':
|
||||||
|
if (snippet.Length > 0)
|
||||||
|
{
|
||||||
|
var comp = new TextComponent(snippet.ToString(), alignment);
|
||||||
|
textComponents.Add(comp);
|
||||||
|
snippet.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
alignment = alignment == BaselineAlignment.Subscript
|
||||||
|
? BaselineAlignment.Baseline
|
||||||
|
: BaselineAlignment.Subscript;
|
||||||
|
break;
|
||||||
|
case '^':
|
||||||
|
if (snippet.Length > 0)
|
||||||
|
{
|
||||||
|
var comp = new TextComponent(snippet.ToString(), alignment);
|
||||||
|
textComponents.Add(comp);
|
||||||
|
snippet.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
alignment = alignment == BaselineAlignment.Superscript
|
||||||
|
? BaselineAlignment.Baseline
|
||||||
|
: BaselineAlignment.Superscript;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
snippet.Append(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snippet.Length > 0)
|
||||||
|
{
|
||||||
|
var comp = new TextComponent(snippet.ToString(), alignment);
|
||||||
|
textComponents.Add(comp);
|
||||||
|
snippet.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return textComponents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
=> Binding.DoNothing;
|
||||||
}
|
}
|
@ -2,38 +2,37 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
|
||||||
namespace Controls
|
namespace Controls;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Selects the right template on base of value-type.
|
||||||
|
/// </summary>
|
||||||
|
public class PropertyDataTemplateSelector : DataTemplateSelector
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Selects the right template on base of value-type.
|
/// Default data template. (currently Textbox)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PropertyDataTemplateSelector : DataTemplateSelector
|
public DataTemplate? DefaultDataTemplate { private get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Data template for boolean. (currently Checkbox)
|
||||||
|
/// </summary>
|
||||||
|
public DataTemplate? BooleanDataTemplate { private get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Data template for enums. (currently Combobox)
|
||||||
|
/// </summary>
|
||||||
|
public DataTemplate? EnumComboBoxDataTemplate { private get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override DataTemplate? SelectTemplate(object item, DependencyObject container)
|
||||||
{
|
{
|
||||||
/// <summary>
|
return item switch
|
||||||
/// Default data template. (currently Textbox)
|
|
||||||
/// </summary>
|
|
||||||
public DataTemplate? DefaultDataTemplate { private get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Data template for boolean. (currently Checkbox)
|
|
||||||
/// </summary>
|
|
||||||
public DataTemplate? BooleanDataTemplate { private get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Data template for enums. (currently Combobox)
|
|
||||||
/// </summary>
|
|
||||||
public DataTemplate? EnumComboBoxDataTemplate { private get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override DataTemplate? SelectTemplate(object item, DependencyObject container)
|
|
||||||
{
|
{
|
||||||
return item switch
|
bool _ => BooleanDataTemplate,
|
||||||
{
|
Enum _ => EnumComboBoxDataTemplate,
|
||||||
bool _ => BooleanDataTemplate,
|
UIElement _ => null,
|
||||||
Enum _ => EnumComboBoxDataTemplate,
|
_ => DefaultDataTemplate
|
||||||
UIElement _ => null,
|
};
|
||||||
_ => DefaultDataTemplate
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,179 +3,178 @@ using System.Windows.Controls;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Markup;
|
using System.Windows.Markup;
|
||||||
|
|
||||||
namespace Controls
|
namespace Controls;
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ContentControl" />
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for PropertyPresenter.xaml
|
||||||
|
/// </summary>
|
||||||
|
[ContentProperty(nameof(Value))]
|
||||||
|
public sealed partial class PropertyPresenter
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="ContentControl" />
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaction logic for PropertyPresenter.xaml
|
/// Button alignment property.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ContentProperty(nameof(Value))]
|
public static readonly DependencyProperty ButtonAlignmentProperty = DependencyProperty.Register(nameof(ButtonAlignment), typeof(Dock), typeof(PropertyPresenter), new PropertyMetadata(Dock.Right));
|
||||||
public sealed partial class PropertyPresenter
|
|
||||||
|
/// <summary>
|
||||||
|
/// Content of the command property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty CommandContentProperty = DependencyProperty.Register(nameof(CommandContent), typeof(object), typeof(PropertyPresenter), new PropertyMetadata("..."));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Command Parameter property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(nameof(CommandParameter), typeof(object), typeof(PropertyPresenter), new PropertyMetadata(default(object)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Command property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(nameof(Command), typeof(ICommand), typeof(PropertyPresenter), new PropertyMetadata(default(ICommand)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// is checked property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register(nameof(IsChecked), typeof(bool?), typeof(PropertyPresenter), new FrameworkPropertyMetadata(default(bool?), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is readonly property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register(nameof(IsReadOnly), typeof(bool), typeof(PropertyPresenter), new PropertyMetadata(default(bool)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Label property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty LabelProperty = DependencyProperty.Register(nameof(Label), typeof(string), typeof(PropertyPresenter), new PropertyMetadata(default(string)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// label width property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty LabelWidthProperty = DependencyProperty.Register(nameof(LabelWidth), typeof(double), typeof(PropertyPresenter), new PropertyMetadata(150.0));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Symbol Property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty SymbolProperty = DependencyProperty.Register(nameof(Symbol), typeof(object), typeof(PropertyPresenter), new PropertyMetadata(default(object)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Value Property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(object), typeof(PropertyPresenter), new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Watermark Property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register(nameof(Watermark), typeof(string), typeof(PropertyPresenter), new FrameworkPropertyMetadata(default(string)));
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PropertyPresenter()
|
||||||
{
|
{
|
||||||
/// <summary>
|
InitializeComponent();
|
||||||
/// Button alignment property.
|
}
|
||||||
/// </summary>
|
|
||||||
public static readonly DependencyProperty ButtonAlignmentProperty = DependencyProperty.Register(nameof(ButtonAlignment), typeof(Dock), typeof(PropertyPresenter), new PropertyMetadata(Dock.Right));
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Content of the command property.
|
/// Button alignment.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty CommandContentProperty = DependencyProperty.Register(nameof(CommandContent), typeof(object), typeof(PropertyPresenter), new PropertyMetadata("..."));
|
public Dock ButtonAlignment
|
||||||
|
{
|
||||||
|
get => (Dock)GetValue(ButtonAlignmentProperty);
|
||||||
|
set => SetValue(ButtonAlignmentProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Command Parameter property
|
/// Command.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(nameof(CommandParameter), typeof(object), typeof(PropertyPresenter), new PropertyMetadata(default(object)));
|
public ICommand? Command
|
||||||
|
{
|
||||||
|
get => (ICommand)GetValue(CommandProperty);
|
||||||
|
set => SetValue(CommandProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Command property
|
/// Command content.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(nameof(Command), typeof(ICommand), typeof(PropertyPresenter), new PropertyMetadata(default(ICommand)));
|
public object? CommandContent
|
||||||
|
{
|
||||||
|
get => GetValue(CommandContentProperty);
|
||||||
|
set => SetValue(CommandContentProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// is checked property.
|
/// Command parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register(nameof(IsChecked), typeof(bool?), typeof(PropertyPresenter), new FrameworkPropertyMetadata(default(bool?), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
|
public object? CommandParameter
|
||||||
|
{
|
||||||
|
get => GetValue(CommandParameterProperty);
|
||||||
|
set => SetValue(CommandParameterProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is readonly property
|
/// IsChecked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register(nameof(IsReadOnly), typeof(bool), typeof(PropertyPresenter), new PropertyMetadata(default(bool)));
|
public bool? IsChecked
|
||||||
|
{
|
||||||
|
get => (bool?)GetValue(IsCheckedProperty);
|
||||||
|
set => SetValue(IsCheckedProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Label property
|
/// IsReadOnly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty LabelProperty = DependencyProperty.Register(nameof(Label), typeof(string), typeof(PropertyPresenter), new PropertyMetadata(default(string)));
|
public bool IsReadOnly
|
||||||
|
{
|
||||||
|
get => (bool)GetValue(IsReadOnlyProperty);
|
||||||
|
set => SetValue(IsReadOnlyProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// label width property.
|
/// Label.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty LabelWidthProperty = DependencyProperty.Register(nameof(LabelWidth), typeof(double), typeof(PropertyPresenter), new PropertyMetadata(150.0));
|
public string? Label
|
||||||
|
{
|
||||||
|
get => (string)GetValue(LabelProperty);
|
||||||
|
set => SetValue(LabelProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Symbol Property
|
/// Label width.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty SymbolProperty = DependencyProperty.Register(nameof(Symbol), typeof(object), typeof(PropertyPresenter), new PropertyMetadata(default(object)));
|
public double LabelWidth
|
||||||
|
{
|
||||||
|
get => (double)GetValue(LabelWidthProperty);
|
||||||
|
set => SetValue(LabelWidthProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Value Property
|
/// Symbol.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(object), typeof(PropertyPresenter), new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
|
public object? Symbol
|
||||||
|
{
|
||||||
|
get => GetValue(SymbolProperty);
|
||||||
|
set => SetValue(SymbolProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Watermark Property
|
/// Value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register(nameof(Watermark), typeof(string), typeof(PropertyPresenter), new FrameworkPropertyMetadata(default(string)));
|
public object? Value
|
||||||
|
{
|
||||||
|
get => GetValue(ValueProperty);
|
||||||
|
set => SetValue(ValueProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <summary>
|
||||||
public PropertyPresenter()
|
/// Watermark.
|
||||||
{
|
/// </summary>
|
||||||
InitializeComponent();
|
public string Watermark
|
||||||
}
|
{
|
||||||
|
get => (string)GetValue(WatermarkProperty);
|
||||||
|
set => SetValue(WatermarkProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Button alignment.
|
public override string ToString()
|
||||||
/// </summary>
|
{
|
||||||
public Dock ButtonAlignment
|
return $"{base.ToString()} {Value}";
|
||||||
{
|
|
||||||
get => (Dock)GetValue(ButtonAlignmentProperty);
|
|
||||||
set => SetValue(ButtonAlignmentProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command.
|
|
||||||
/// </summary>
|
|
||||||
public ICommand? Command
|
|
||||||
{
|
|
||||||
get => (ICommand)GetValue(CommandProperty);
|
|
||||||
set => SetValue(CommandProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command content.
|
|
||||||
/// </summary>
|
|
||||||
public object? CommandContent
|
|
||||||
{
|
|
||||||
get => GetValue(CommandContentProperty);
|
|
||||||
set => SetValue(CommandContentProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command parameter.
|
|
||||||
/// </summary>
|
|
||||||
public object? CommandParameter
|
|
||||||
{
|
|
||||||
get => GetValue(CommandParameterProperty);
|
|
||||||
set => SetValue(CommandParameterProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// IsChecked.
|
|
||||||
/// </summary>
|
|
||||||
public bool? IsChecked
|
|
||||||
{
|
|
||||||
get => (bool?)GetValue(IsCheckedProperty);
|
|
||||||
set => SetValue(IsCheckedProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// IsReadOnly
|
|
||||||
/// </summary>
|
|
||||||
public bool IsReadOnly
|
|
||||||
{
|
|
||||||
get => (bool)GetValue(IsReadOnlyProperty);
|
|
||||||
set => SetValue(IsReadOnlyProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Label.
|
|
||||||
/// </summary>
|
|
||||||
public string? Label
|
|
||||||
{
|
|
||||||
get => (string)GetValue(LabelProperty);
|
|
||||||
set => SetValue(LabelProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Label width.
|
|
||||||
/// </summary>
|
|
||||||
public double LabelWidth
|
|
||||||
{
|
|
||||||
get => (double)GetValue(LabelWidthProperty);
|
|
||||||
set => SetValue(LabelWidthProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Symbol.
|
|
||||||
/// </summary>
|
|
||||||
public object? Symbol
|
|
||||||
{
|
|
||||||
get => GetValue(SymbolProperty);
|
|
||||||
set => SetValue(SymbolProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Value.
|
|
||||||
/// </summary>
|
|
||||||
public object? Value
|
|
||||||
{
|
|
||||||
get => GetValue(ValueProperty);
|
|
||||||
set => SetValue(ValueProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Watermark.
|
|
||||||
/// </summary>
|
|
||||||
public string Watermark
|
|
||||||
{
|
|
||||||
get => (string)GetValue(WatermarkProperty);
|
|
||||||
set => SetValue(WatermarkProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{base.ToString()} {Value}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,164 +2,163 @@
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
namespace Controls
|
namespace Controls;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a TextBox that can update the binding on enter.
|
||||||
|
/// </summary>
|
||||||
|
public class TextBoxEx : TextBox
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Identifies the <see cref="MoveFocusOnEnter"/> dependency property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty MoveFocusOnEnterProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
nameof(MoveFocusOnEnter), typeof(bool), typeof(TextBoxEx), new UIPropertyMetadata(true));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifies the <see cref="UpdateBindingOnEnter"/> dependency property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty UpdateBindingOnEnterProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
nameof(UpdateBindingOnEnter), typeof(bool), typeof(TextBoxEx), new UIPropertyMetadata(true));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifies the <see cref="ScrollToHomeOnFocus"/> dependency property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty ScrollToHomeOnFocusProperty =
|
||||||
|
DependencyProperty.Register(nameof(ScrollToHomeOnFocus), typeof(bool), typeof(TextBoxEx), new PropertyMetadata(true));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifies the <see cref="SelectAllOnFocus"/> dependency property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty SelectAllOnFocusProperty =
|
||||||
|
DependencyProperty.Register(nameof(SelectAllOnFocus), typeof(bool), typeof(TextBoxEx), new PropertyMetadata(true));
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a TextBox that can update the binding on enter.
|
/// Initializes a new instance of the <see cref="T:Controls.TextBoxEx" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TextBoxEx : TextBox
|
public TextBoxEx()
|
||||||
{
|
{
|
||||||
/// <summary>
|
GotKeyboardFocus += HandleGotKeyboardFocus;
|
||||||
/// Identifies the <see cref="MoveFocusOnEnter"/> dependency property.
|
}
|
||||||
/// </summary>
|
|
||||||
public static readonly DependencyProperty MoveFocusOnEnterProperty =
|
|
||||||
DependencyProperty.Register(
|
|
||||||
"MoveFocusOnEnter", typeof(bool), typeof(TextBoxEx), new UIPropertyMetadata(true));
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Identifies the <see cref="UpdateBindingOnEnter"/> dependency property.
|
/// Gets or sets a value indicating whether to select all on focus.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty UpdateBindingOnEnterProperty =
|
/// <value>
|
||||||
DependencyProperty.Register(
|
/// <c>true</c> if all should be selected; otherwise, <c>false</c>.
|
||||||
"UpdateBindingOnEnter", typeof(bool), typeof(TextBoxEx), new UIPropertyMetadata(true));
|
/// </value>
|
||||||
|
public bool SelectAllOnFocus
|
||||||
|
{
|
||||||
|
get => (bool)GetValue(SelectAllOnFocusProperty);
|
||||||
|
set => SetValue(SelectAllOnFocusProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Identifies the <see cref="ScrollToHomeOnFocus"/> dependency property.
|
/// Gets or sets a value indicating whether to scroll to home on focus.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty ScrollToHomeOnFocusProperty =
|
/// <value>
|
||||||
DependencyProperty.Register("ScrollToHomeOnFocus", typeof(bool), typeof(TextBoxEx), new PropertyMetadata(true));
|
/// <c>true</c> if scroll is enabled; otherwise, <c>false</c>.
|
||||||
|
/// </value>
|
||||||
|
public bool ScrollToHomeOnFocus
|
||||||
|
{
|
||||||
|
get => (bool)GetValue(ScrollToHomeOnFocusProperty);
|
||||||
|
set => SetValue(ScrollToHomeOnFocusProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Identifies the <see cref="SelectAllOnFocus"/> dependency property.
|
/// Gets or sets a value indicating whether MoveFocusOnEnter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty SelectAllOnFocusProperty =
|
public bool MoveFocusOnEnter
|
||||||
DependencyProperty.Register("SelectAllOnFocus", typeof(bool), typeof(TextBoxEx), new PropertyMetadata(true));
|
{
|
||||||
|
get => (bool)GetValue(MoveFocusOnEnterProperty);
|
||||||
|
|
||||||
/// <inheritdoc />
|
set => SetValue(MoveFocusOnEnterProperty, value);
|
||||||
/// <summary>
|
}
|
||||||
/// Initializes a new instance of the <see cref="T:Controls.TextBoxEx" /> class.
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public TextBoxEx()
|
/// Gets or sets a value indicating whether UpdateBindingOnEnter.
|
||||||
|
/// </summary>
|
||||||
|
public bool UpdateBindingOnEnter
|
||||||
|
{
|
||||||
|
get => (bool)GetValue(UpdateBindingOnEnterProperty);
|
||||||
|
|
||||||
|
set => SetValue(UpdateBindingOnEnterProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnPreviewKeyDown(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnPreviewKeyDown(e);
|
||||||
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
GotKeyboardFocus += HandleGotKeyboardFocus;
|
case Key.Enter:
|
||||||
}
|
if (!AcceptsReturn)
|
||||||
|
{
|
||||||
/// <summary>
|
if (UpdateBindingOnEnter)
|
||||||
/// Gets or sets a value indicating whether to select all on focus.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>
|
|
||||||
/// <c>true</c> if all should be selected; otherwise, <c>false</c>.
|
|
||||||
/// </value>
|
|
||||||
public bool SelectAllOnFocus
|
|
||||||
{
|
|
||||||
get => (bool)GetValue(SelectAllOnFocusProperty);
|
|
||||||
set => SetValue(SelectAllOnFocusProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether to scroll to home on focus.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>
|
|
||||||
/// <c>true</c> if scroll is enabled; otherwise, <c>false</c>.
|
|
||||||
/// </value>
|
|
||||||
public bool ScrollToHomeOnFocus
|
|
||||||
{
|
|
||||||
get => (bool)GetValue(ScrollToHomeOnFocusProperty);
|
|
||||||
set => SetValue(ScrollToHomeOnFocusProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether MoveFocusOnEnter.
|
|
||||||
/// </summary>
|
|
||||||
public bool MoveFocusOnEnter
|
|
||||||
{
|
|
||||||
get => (bool)GetValue(MoveFocusOnEnterProperty);
|
|
||||||
|
|
||||||
set => SetValue(MoveFocusOnEnterProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether UpdateBindingOnEnter.
|
|
||||||
/// </summary>
|
|
||||||
public bool UpdateBindingOnEnter
|
|
||||||
{
|
|
||||||
get => (bool)GetValue(UpdateBindingOnEnterProperty);
|
|
||||||
|
|
||||||
set => SetValue(UpdateBindingOnEnterProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void OnPreviewKeyDown(KeyEventArgs e)
|
|
||||||
{
|
|
||||||
base.OnPreviewKeyDown(e);
|
|
||||||
switch (e.Key)
|
|
||||||
{
|
|
||||||
case Key.Enter:
|
|
||||||
if (!AcceptsReturn)
|
|
||||||
{
|
{
|
||||||
if (UpdateBindingOnEnter)
|
// get the binding to the Text property
|
||||||
{
|
var bindingExpression = GetBindingExpression(TextProperty);
|
||||||
// get the binding to the Text property
|
// update the source (do not update the target)
|
||||||
var bindingExpression = GetBindingExpression(TextProperty);
|
bindingExpression?.UpdateSource();
|
||||||
// update the source (do not update the target)
|
}
|
||||||
bindingExpression?.UpdateSource();
|
|
||||||
}
|
if (MoveFocusOnEnter)
|
||||||
|
{
|
||||||
if (MoveFocusOnEnter)
|
// Move focus to next element
|
||||||
{
|
// http://madprops.org/blog/enter-to-tab-in-wpf/
|
||||||
// Move focus to next element
|
if (e.OriginalSource is UIElement uiElement)
|
||||||
// http://madprops.org/blog/enter-to-tab-in-wpf/
|
{
|
||||||
if (e.OriginalSource is UIElement uiElement)
|
var shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
|
||||||
{
|
uiElement.MoveFocus(new TraversalRequest(shift ? FocusNavigationDirection.Previous : FocusNavigationDirection.Next));
|
||||||
var shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
|
}
|
||||||
uiElement.MoveFocus(new TraversalRequest(shift ? FocusNavigationDirection.Previous : FocusNavigationDirection.Next));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
case Key.Escape:
|
|
||||||
Undo();
|
|
||||||
SelectAll();
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
break;
|
||||||
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
|
case Key.Escape:
|
||||||
{
|
Undo();
|
||||||
base.OnPreviewMouseLeftButtonDown(e);
|
|
||||||
|
|
||||||
if (!IsKeyboardFocusWithin)
|
|
||||||
{
|
|
||||||
SelectAll();
|
SelectAll();
|
||||||
Focus();
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Handles the got keyboard focus event.
|
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
|
||||||
/// </summary>
|
{
|
||||||
/// <param name="sender">The sender.</param>
|
base.OnPreviewMouseLeftButtonDown(e);
|
||||||
/// <param name="e">The <see cref="KeyboardFocusChangedEventArgs" /> instance containing the event data.</param>
|
|
||||||
private void HandleGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
|
if (!IsKeyboardFocusWithin)
|
||||||
{
|
{
|
||||||
if (SelectAllOnFocus)
|
SelectAll();
|
||||||
{
|
Focus();
|
||||||
SelectAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ScrollToHomeOnFocus)
|
|
||||||
{
|
|
||||||
ScrollToHome();
|
|
||||||
}
|
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the got keyboard focus event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sender.</param>
|
||||||
|
/// <param name="e">The <see cref="KeyboardFocusChangedEventArgs" /> instance containing the event data.</param>
|
||||||
|
private void HandleGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (SelectAllOnFocus)
|
||||||
|
{
|
||||||
|
SelectAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ScrollToHomeOnFocus)
|
||||||
|
{
|
||||||
|
ScrollToHome();
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,31 +1,30 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
namespace Controls
|
namespace Controls;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A component of the symbol
|
||||||
|
/// </summary>
|
||||||
|
public readonly struct TextComponent
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A component of the symbol
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly struct TextComponent
|
/// <param name="text"></param>
|
||||||
|
/// <param name="style"></param>
|
||||||
|
public TextComponent(string text, BaselineAlignment style = BaselineAlignment.Baseline)
|
||||||
{
|
{
|
||||||
/// <summary>
|
Text = text;
|
||||||
/// Constructor
|
Style = style;
|
||||||
/// </summary>
|
|
||||||
/// <param name="text"></param>
|
|
||||||
/// <param name="style"></param>
|
|
||||||
public TextComponent(string text, BaselineAlignment style = BaselineAlignment.Baseline)
|
|
||||||
{
|
|
||||||
Text = text;
|
|
||||||
Style = style;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Text of the symbol component
|
|
||||||
/// </summary>
|
|
||||||
public readonly string Text;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Style of the symbol component
|
|
||||||
/// </summary>
|
|
||||||
public readonly BaselineAlignment Style;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Text of the symbol component
|
||||||
|
/// </summary>
|
||||||
|
public readonly string Text;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Style of the symbol component
|
||||||
|
/// </summary>
|
||||||
|
public readonly BaselineAlignment Style;
|
||||||
}
|
}
|
@ -11,90 +11,89 @@ using Brushes = System.Windows.Media.Brushes;
|
|||||||
using FontFamily = System.Windows.Media.FontFamily;
|
using FontFamily = System.Windows.Media.FontFamily;
|
||||||
using Point = System.Windows.Point;
|
using Point = System.Windows.Point;
|
||||||
|
|
||||||
namespace Controls
|
namespace Controls;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Makes an Bitmap from every Imageformat.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ObjectImageConverter : IValueConverter
|
||||||
{
|
{
|
||||||
/// <summary>
|
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
/// Makes an Bitmap from every Imageformat.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class ObjectImageConverter : IValueConverter
|
|
||||||
{
|
{
|
||||||
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
const string dynResPrefix = "dynRes:";
|
||||||
|
if (value is Bitmap bitmap)
|
||||||
{
|
{
|
||||||
const string dynResPrefix = "dynRes:";
|
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(16, 16));
|
||||||
if (value is Bitmap bitmap)
|
|
||||||
{
|
|
||||||
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(16, 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value is not string strValue) return Binding.DoNothing;
|
|
||||||
if (strValue.StartsWith(dynResPrefix, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
var resource = Application.Current.TryFindResource(strValue.Replace(dynResPrefix, string.Empty , StringComparison.InvariantCulture));
|
|
||||||
return resource is ImageSource source ? source : Binding.DoNothing;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strValue.StartsWith("text:", StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
var parts = strValue.Split(':');
|
|
||||||
return parts.Length == 3 ? DrawText(WebUtility.HtmlDecode(parts[2]), parts[1], Brushes.Black) : Binding.DoNothing;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetIcon(Geometry.Parse(strValue), null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
|
if (value is not string strValue) return Binding.DoNothing;
|
||||||
Binding.DoNothing;
|
if (strValue.StartsWith(dynResPrefix, StringComparison.Ordinal))
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get icon a ImageSource from geometry.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="geometry">geometry</param>
|
|
||||||
/// <param name="brush">color of the icon</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static ImageSource GetIcon(Geometry geometry, Brush? brush)
|
|
||||||
{
|
{
|
||||||
if (brush == null)
|
var resource = Application.Current.TryFindResource(strValue.Replace(dynResPrefix, string.Empty , StringComparison.InvariantCulture));
|
||||||
brush = Brushes.Black;
|
return resource is ImageSource source ? source : Binding.DoNothing;
|
||||||
var drawing = new GeometryDrawing(brush, null, geometry);
|
|
||||||
return new DrawingImage(drawing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
if (strValue.StartsWith("text:", StringComparison.Ordinal))
|
||||||
/// Draw text as ImageSource from string.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">the text</param>
|
|
||||||
/// <param name="strFontFamily">font of the string</param>
|
|
||||||
/// <param name="brush">color of the string</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static ImageSource DrawText(string text, string strFontFamily, Brush brush)
|
|
||||||
{
|
{
|
||||||
var fontFamily = new FontFamily(strFontFamily);
|
var parts = strValue.Split(':');
|
||||||
var formattedText = new FormattedText(text,
|
return parts.Length == 3 ? DrawText(WebUtility.HtmlDecode(parts[2]), parts[1], Brushes.Black) : Binding.DoNothing;
|
||||||
CultureInfo.GetCultureInfo("en-us"),
|
|
||||||
FlowDirection.LeftToRight,
|
|
||||||
new Typeface(
|
|
||||||
fontFamily,
|
|
||||||
FontStyles.Normal,
|
|
||||||
FontWeights.Normal,
|
|
||||||
FontStretches.Normal),
|
|
||||||
64, brush, 1.5);
|
|
||||||
|
|
||||||
var geometry = formattedText.BuildGeometry(new Point(0, 0));
|
|
||||||
return GetIcon(geometry, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return GetIcon(Geometry.Parse(strValue), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
|
||||||
|
Binding.DoNothing;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get icon a ImageSource from geometry.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="geometry">geometry</param>
|
||||||
|
/// <param name="brush">color of the icon</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static ImageSource GetIcon(Geometry geometry, Brush? brush)
|
||||||
|
{
|
||||||
|
if (brush == null)
|
||||||
|
brush = Brushes.Black;
|
||||||
|
var drawing = new GeometryDrawing(brush, null, geometry);
|
||||||
|
return new DrawingImage(drawing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invert boolean converter
|
/// Draw text as ImageSource from string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ValueConversion(typeof(bool), typeof(bool))]
|
/// <param name="text">the text</param>
|
||||||
public class InverseBooleanConverter : IValueConverter
|
/// <param name="strFontFamily">font of the string</param>
|
||||||
|
/// <param name="brush">color of the string</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static ImageSource DrawText(string text, string strFontFamily, Brush brush)
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
var fontFamily = new FontFamily(strFontFamily);
|
||||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
|
var formattedText = new FormattedText(text,
|
||||||
value is bool b ? !b : throw new InvalidOperationException("The target must be a boolean");
|
CultureInfo.GetCultureInfo("en-us"),
|
||||||
|
FlowDirection.LeftToRight,
|
||||||
|
new Typeface(
|
||||||
|
fontFamily,
|
||||||
|
FontStyles.Normal,
|
||||||
|
FontWeights.Normal,
|
||||||
|
FontStretches.Normal),
|
||||||
|
64, brush, 1.5);
|
||||||
|
|
||||||
/// <inheritdoc />
|
var geometry = formattedText.BuildGeometry(new Point(0, 0));
|
||||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => Binding.DoNothing;
|
return GetIcon(geometry, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invert boolean converter
|
||||||
|
/// </summary>
|
||||||
|
[ValueConversion(typeof(bool), typeof(bool))]
|
||||||
|
public class InverseBooleanConverter : IValueConverter
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
|
||||||
|
value is bool b ? !b : throw new InvalidOperationException("The target must be a boolean");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => Binding.DoNothing;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user