file-scoped namespaces and update of modernwpfui

This commit is contained in:
Holger Börchers 2022-10-22 13:26:01 +02:00
parent 02e3af3dcb
commit 644e2628e3
10 changed files with 638 additions and 647 deletions

View File

@ -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>

View File

@ -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)
};
}
} }
} }

View File

@ -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();
} }

View File

@ -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;
}
} }

View File

@ -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;
} }

View File

@ -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
};
}
} }
} }

View File

@ -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}";
}
} }
} }

View File

@ -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;
}
} }

View File

@ -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;
} }

View File

@ -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;
}