未验证 提交 7c75f5c6 编写于 作者: P pomianowski

Refactor Relay Command

上级 6ea46bbd
MIT License
Copyright (c) 2021-2022 Leszek Pomianowski and WPF UI Contributors. https://dev.lepo.co/
Copyright (c) 2021-2023 Leszek Pomianowski and WPF UI Contributors. https://dev.lepo.co/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
SOFTWARE.
# Copyright 2022 Leszek Pomianowski and WPF UI Contributors
# Copyright 2022-2023 Leszek Pomianowski and WPF UI Contributors
[CmdletBinding(PositionalBinding = $false)]
Param(
......
......@@ -3,9 +3,7 @@
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using System;
using System.Windows;
using Wpf.Ui.Contracts;
using Wpf.Ui.Gallery.Helpers;
namespace Wpf.Ui.Gallery.Controls;
......@@ -42,19 +40,17 @@ public object ItemsSource
/// </summary>
public GalleryNavigationPresenter()
{
SetValue(TemplateButtonCommandProperty, new Common.RelayCommand(o => OnTemplateButtonClick(this, o)));
SetValue(TemplateButtonCommandProperty, new Common.RelayCommand<string>(o => OnTemplateButtonClick(o ?? String.Empty)));
}
private void OnTemplateButtonClick(object sender, object parameter)
private void OnTemplateButtonClick(string parameter)
{
string parameterString = parameter as string ?? String.Empty;
var navigationService = App.GetService<INavigationService>();
if (navigationService == null)
return;
var pageType = NameToPageTypeConverter.Convert(parameterString);
var pageType = NameToPageTypeConverter.Convert(parameter);
if (pageType != null)
navigationService.Navigate(pageType);
......
......@@ -216,6 +216,13 @@
Icon="Empty"
NavigateUri="https://wpfui.lepo.co/"
ToolTip="https://wpfui.lepo.co/" />
<ui:Hyperlink
Margin="8,0,0,0"
Padding="4"
Content="Microsoft Store"
Icon="Empty"
NavigateUri="https://apps.microsoft.com/store/detail/wpf-ui/9N9LKV8R9VGM"
ToolTip="https://apps.microsoft.com/store/detail/wpf-ui/9N9LKV8R9VGM" />
<ui:Hyperlink
Margin="8,0,0,0"
Padding="4"
......
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Windows.Input;
namespace Wpf.Ui.Common;
/// <summary>
/// A command whose sole purpose is to relay its functionality to other objects by invoking delegates. The
/// default return value for the <see cref="CanExecute"/> method is <see langword="true"/>.
/// An interface expanding <see cref="ICommand"/> with the ability to raise
/// the <see cref="ICommand.CanExecuteChanged"/> event externally.
/// </summary>
public interface IRelayCommand : ICommand
{
/// <summary>
/// Gets encapsulated canExecute function.
/// Notifies that the <see cref="ICommand.CanExecute"/> property has changed.
/// </summary>
/// <param name="parameter"></param>
public new bool CanExecute(object parameter);
/// <summary>
/// Triggers action with provided parameter.
/// </summary>
/// <param name="parameter">Argument to be passed.</param>
public new void Execute(object parameter);
void NotifyCanExecuteChanged();
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Windows.Input;
namespace Wpf.Ui.Common;
/// <summary>
/// A generic interface representing a more specific version of <see cref="IRelayCommand"/>.
/// </summary>
/// <typeparam name="T">The type used as argument for the interface methods.</typeparam>
public interface IRelayCommand<in T> : IRelayCommand
{
/// <summary>
/// Provides a strongly-typed variant of <see cref="ICommand.CanExecute(object)"/>.
/// </summary>
/// <param name="parameter">The input parameter.</param>
/// <returns>Whether or not the current command can be executed.</returns>
/// <remarks>Use this overload to avoid boxing, if <typeparamref name="T"/> is a value type.</remarks>
bool CanExecute(T? parameter);
/// <summary>
/// Provides a strongly-typed variant of <see cref="ICommand.Execute(object)"/>.
/// </summary>
/// <param name="parameter">The input parameter.</param>
/// <remarks>Use this overload to avoid boxing, if <typeparamref name="T"/> is a value type.</remarks>
void Execute(T? parameter);
}
// Documentation of this Source Code is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
// ICommand implementation example provided by Microsoft.
// https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.input.icommand?view=winrt-22000
using System;
using System.Windows.Input;
namespace Wpf.Ui.Common;
/// <summary>
/// A command whose sole purpose is to relay its functionality to other objects by invoking delegates. The
/// default return value for the <see cref="CanExecute"/> method is <see langword="true"/>.
/// <para>
/// <see href="https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.input.icommand?view=winrt-22000"/>
/// </para>
/// </summary>
public sealed class RelayCommand : IRelayCommand
{
readonly Action<object> _execute;
readonly Func<bool> _canExecute;
/// <summary>
/// Event occuring when encapsulated canExecute method is changed.
/// </summary>
public event EventHandler? CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
/// <summary>
/// Creates new instance of <see cref="RelayCommand"/>.
/// </summary>
/// <param name="execute">Action to be executed.</param>
public RelayCommand(Action execute) : this(execute, null!)
{
// Delegated to RelayCommand(Action execute, Func<bool> canExecute)
}
/// <summary>
/// Creates new instance of <see cref="RelayCommand"/>.
/// </summary>
/// <param name="execute">Action with <see cref="object"/> parameter to be executed.</param>
public RelayCommand(Action<object> execute) : this(execute, null!)
{
// Delegated to RelayCommand(Action<object> execute, Func<bool> canExecute)
}
/// <summary>
/// Creates new instance of <see cref="RelayCommand"/>.
/// </summary>
/// <param name="execute">Action to be executed.</param>
/// <param name="canExecute">Encapsulated method determining whether to execute action.</param>
/// <exception cref="ArgumentNullException">Exception occurring when no <see cref="Action"/> is defined.</exception>
public RelayCommand(Action execute, Func<bool> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = p => execute();
_canExecute = canExecute;
}
/// <summary>
/// Creates new instance of <see cref="RelayCommand"/>.
/// </summary>
/// <param name="execute">Action with <see cref="object"/> parameter to be executed.</param>
/// <param name="canExecute">Encapsulated method determining whether to execute action.</param>
/// <exception cref="ArgumentNullException">Exception occurring when no <see cref="Action"/> is defined.</exception>
public RelayCommand(Action<object> execute, Func<bool> canExecute)
{
_execute = execute ?? throw new ArgumentNullException("execute");
_canExecute = canExecute;
}
/// <inheritdoc cref="IRelayCommand.CanExecute" />
public bool CanExecute(object? parameter)
{
return _canExecute?.Invoke() ?? true;
}
/// <inheritdoc cref="IRelayCommand.Execute" />
public void Execute(object? parameter)
{
_execute(parameter!);
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// This file is inspired from the MvvmLight library (lbugnion/MvvmLight)
using System;
using System.Runtime.CompilerServices;
namespace Wpf.Ui.Common;
/// <summary>
/// A generic command whose sole purpose is to relay its functionality to other
/// objects by invoking delegates. The default return value for the CanExecute
/// method is <see langword="true"/>. This class allows you to accept command parameters
/// in the <see cref="Execute(T)"/> and <see cref="CanExecute(T)"/> callback methods.
/// </summary>
/// <typeparam name="T">The type of parameter being passed as input to the callbacks.</typeparam>
public class RelayCommand<T> : IRelayCommand<T>
{
/// <summary>
/// The <see cref="Action"/> to invoke when <see cref="Execute(T)"/> is used.
/// </summary>
private readonly Action<T?> execute;
/// <summary>
/// The optional action to invoke when <see cref="CanExecute(T)"/> is used.
/// </summary>
private readonly Predicate<T?>? canExecute;
/// <inheritdoc/>
public event EventHandler? CanExecuteChanged;
/// <summary>
/// Initializes a new instance of the <see cref="RelayCommand{T}"/> class that can always execute.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <remarks>
/// Due to the fact that the <see cref="System.Windows.Input.ICommand"/> interface exposes methods that accept a
/// nullable <see cref="object"/> parameter, it is recommended that if <typeparamref name="T"/> is a reference type,
/// you should always declare it as nullable, and to always perform checks within <paramref name="execute"/>.
/// </remarks>
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="execute"/> is <see langword="null"/>.</exception>
public RelayCommand(Action<T?> execute)
{
if (execute is null)
throw new ArgumentNullException(nameof(execute));
this.execute = execute;
}
/// <summary>
/// Initializes a new instance of the <see cref="RelayCommand{T}"/> class.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
/// <remarks>See notes in <see cref="RelayCommand{T}(Action{T})"/>.</remarks>
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="execute"/> or <paramref name="canExecute"/> are <see langword="null"/>.</exception>
public RelayCommand(Action<T?> execute, Predicate<T?> canExecute)
{
if (execute is null)
throw new ArgumentNullException(nameof(execute));
if (canExecute is null)
throw new ArgumentNullException(nameof(canExecute));
this.execute = execute;
this.canExecute = canExecute;
}
/// <inheritdoc/>
public void NotifyCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool CanExecute(T? parameter)
{
return this.canExecute?.Invoke(parameter) != false;
}
/// <inheritdoc/>
public bool CanExecute(object? parameter)
{
// Special case a null value for a value type argument type.
// This ensures that no exceptions are thrown during initialization.
if (parameter is null && default(T) is not null)
{
return false;
}
if (!TryGetCommandArgument(parameter, out T? result))
{
ThrowArgumentExceptionForInvalidCommandArgument(parameter);
}
return CanExecute(result);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Execute(T? parameter)
{
this.execute(parameter);
}
/// <inheritdoc/>
public void Execute(object? parameter)
{
if (!TryGetCommandArgument(parameter, out T? result))
{
ThrowArgumentExceptionForInvalidCommandArgument(parameter);
}
Execute(result);
}
/// <summary>
/// Tries to get a command argument of compatible type <typeparamref name="T"/> from an input <see cref="object"/>.
/// </summary>
/// <param name="parameter">The input parameter.</param>
/// <param name="result">The resulting <typeparamref name="T"/> value, if any.</param>
/// <returns>Whether or not a compatible command argument could be retrieved.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool TryGetCommandArgument(object? parameter, out T? result)
{
// If the argument is null and the default value of T is also null, then the
// argument is valid. T might be a reference type or a nullable value type.
if (parameter is null && default(T) is null)
{
result = default;
return true;
}
// Check if the argument is a T value, so either an instance of a type or a derived
// type of T is a reference type, an interface implementation if T is an interface,
// or a boxed value type in case T was a value type.
if (parameter is T argument)
{
result = argument;
return true;
}
result = default;
return false;
}
/// <summary>
/// Throws an <see cref="ArgumentException"/> if an invalid command argument is used.
/// </summary>
/// <param name="parameter">The input parameter.</param>
/// <exception cref="ArgumentException">Thrown with an error message to give info on the invalid parameter.</exception>
internal static void ThrowArgumentExceptionForInvalidCommandArgument(object? parameter)
{
[MethodImpl(MethodImplOptions.NoInlining)]
static Exception GetException(object? parameter)
{
if (parameter is null)
{
return new ArgumentException($"Parameter \"{nameof(parameter)}\" (object) must not be null, as the command type requires an argument of type {typeof(T)}.", nameof(parameter));
}
return new ArgumentException($"Parameter \"{nameof(parameter)}\" (object) cannot be of type {parameter.GetType()}, as the command type requires an argument of type {typeof(T)}.", nameof(parameter));
}
throw GetException(parameter);
}
}
......@@ -22,35 +22,12 @@ public class Badge : System.Windows.Controls.ContentControl, IAppearanceControl
/// Property for <see cref="Appearance"/>.
/// </summary>
public static readonly DependencyProperty AppearanceProperty = DependencyProperty.Register(nameof(Appearance),
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
typeof(Common.ControlAppearance), typeof(Badge),
new PropertyMetadata(Common.ControlAppearance.Primary));
After:
typeof(ControlAppearance), typeof(Badge),
new PropertyMetadata(ControlAppearance.Primary));
*/
typeof(Controls.ControlAppearance), typeof(Badge),
new PropertyMetadata(Controls.ControlAppearance.Primary));
/// <inheritdoc />
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
public Common.ControlAppearance Appearance
After:
public ControlAppearance Appearance
*/
public Controls.ControlAppearance Appearance
{
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
get => (Common.ControlAppearance)GetValue(AppearanceProperty);
After:
get => (ControlAppearance)GetValue(AppearanceProperty);
*/
get => (Controls.ControlAppearance)GetValue(AppearanceProperty);
set => SetValue(AppearanceProperty, value);
}
......
......@@ -39,15 +39,6 @@ public class Button : System.Windows.Controls.Button, IIconControl, IAppearanceC
/// Property for <see cref="Appearance"/>.
/// </summary>
public static readonly DependencyProperty AppearanceProperty = DependencyProperty.Register(nameof(Appearance),
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
typeof(Common.ControlAppearance), typeof(Button),
new PropertyMetadata(Common.ControlAppearance.Primary));
After:
typeof(ControlAppearance), typeof(Button),
new PropertyMetadata(ControlAppearance.Primary));
*/
typeof(Controls.ControlAppearance), typeof(Button),
new PropertyMetadata(Controls.ControlAppearance.Primary));
......@@ -114,22 +105,8 @@ public Brush IconForeground
/// <inheritdoc />
[Bindable(true), Category("Appearance")]
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
public Common.ControlAppearance Appearance
After:
public ControlAppearance Appearance
*/
public Controls.ControlAppearance Appearance
{
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
get => (Common.ControlAppearance)GetValue(AppearanceProperty);
After:
get => (ControlAppearance)GetValue(AppearanceProperty);
*/
get => (Controls.ControlAppearance)GetValue(AppearanceProperty);
set => SetValue(AppearanceProperty, value);
}
......
......@@ -54,7 +54,7 @@ public object SyntaxContent
/// </summary>
public CodeBlock()
{
SetValue(ButtonCommandProperty, new Common.RelayCommand(o => Button_Click(this, o)));
SetValue(ButtonCommandProperty, new Common.RelayCommand<string>(o => OnTemplateButtonClick(o ?? String.Empty)));
Appearance.Theme.Changed += ThemeOnChanged;
}
......@@ -80,7 +80,7 @@ protected virtual void UpdateSyntax()
SyntaxContent = Syntax.Highlighter.Format(_sourceCode);
}
private void Button_Click(object sender, object parameter)
private void OnTemplateButtonClick(string parameter)
{
#if DEBUG
System.Diagnostics.Debug.WriteLine($"INFO | CodeBlock source: \n{_sourceCode}", "Wpf.Ui.CodeBlock");
......
......@@ -107,15 +107,6 @@ public class Dialog : System.Windows.Controls.ContentControl, IDialogControl
/// </summary>
public static readonly DependencyProperty ButtonLeftAppearanceProperty = DependencyProperty.Register(
nameof(ButtonLeftAppearance),
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
typeof(Common.ControlAppearance), typeof(Dialog),
new PropertyMetadata(Common.ControlAppearance.Primary));
After:
typeof(ControlAppearance), typeof(Dialog),
new PropertyMetadata(ControlAppearance.Primary));
*/
typeof(Controls.ControlAppearance), typeof(Dialog),
new PropertyMetadata(Controls.ControlAppearance.Primary));
......@@ -139,15 +130,6 @@ public class Dialog : System.Windows.Controls.ContentControl, IDialogControl
/// </summary>
public static readonly DependencyProperty ButtonRightAppearanceProperty = DependencyProperty.Register(
nameof(ButtonRightAppearance),
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
typeof(Common.ControlAppearance), typeof(Dialog),
new PropertyMetadata(Common.ControlAppearance.Secondary));
After:
typeof(ControlAppearance), typeof(Dialog),
new PropertyMetadata(ControlAppearance.Secondary));
*/
typeof(Controls.ControlAppearance), typeof(Dialog),
new PropertyMetadata(Controls.ControlAppearance.Secondary));
......@@ -220,22 +202,8 @@ public string ButtonLeftName
/// <summary>
/// Gets or sets the <see cref="ControlAppearance"/> of the button on the left, if available.
/// </summary>
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
public Common.ControlAppearance ButtonLeftAppearance
After:
public ControlAppearance ButtonLeftAppearance
*/
public Controls.ControlAppearance ButtonLeftAppearance
{
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
get => (Common.ControlAppearance)GetValue(ButtonLeftAppearanceProperty);
After:
get => (ControlAppearance)GetValue(ButtonLeftAppearanceProperty);
*/
get => (Controls.ControlAppearance)GetValue(ButtonLeftAppearanceProperty);
set => SetValue(ButtonLeftAppearanceProperty, value);
}
......@@ -266,22 +234,8 @@ public string ButtonRightName
/// <summary>
/// Gets or sets the <see cref="ControlAppearance"/> of the button on the right, if available.
/// </summary>
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
public Common.ControlAppearance ButtonRightAppearance
After:
public ControlAppearance ButtonRightAppearance
*/
public Controls.ControlAppearance ButtonRightAppearance
{
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
get => (Common.ControlAppearance)GetValue(ButtonRightAppearanceProperty);
After:
get => (ControlAppearance)GetValue(ButtonRightAppearanceProperty);
*/
get => (Controls.ControlAppearance)GetValue(ButtonRightAppearanceProperty);
set => SetValue(ButtonRightAppearanceProperty, value);
}
......@@ -339,7 +293,7 @@ public System.Windows.Visibility ButtonRightVisibility
/// </summary>
public Dialog()
{
SetValue(TemplateButtonCommandProperty, new Common.RelayCommand(o => OnTemplateButtonClick(this, o)));
SetValue(TemplateButtonCommandProperty, new Common.RelayCommand<string>(o => OnTemplateButtonClick(o ?? String.Empty)));
}
/// <inheritdoc />
......@@ -471,19 +425,14 @@ protected virtual void OnClosed()
/// <summary>
/// Triggered by clicking a button in the control template.
/// </summary>
/// <param name="sender">Sender of the click event.</param>
/// <param name="parameter">Additional parameters.</param>
protected virtual void OnTemplateButtonClick(object sender, object? parameter)
protected virtual void OnTemplateButtonClick(string parameter)
{
if (parameter is not String parameterString)
return;
#if DEBUG
System.Diagnostics.Debug.WriteLine($"INFO: {typeof(Dialog)} button clicked with param: {parameterString}",
System.Diagnostics.Debug.WriteLine($"INFO: {typeof(Dialog)} button clicked with param: {parameter}",
"Wpf.Ui.Dialog");
#endif
switch (parameterString)
switch (parameter)
{
case "left":
RaiseEvent(new RoutedEventArgs(ButtonLeftClickEvent, this));
......
......@@ -5,18 +5,6 @@
using System.Threading.Tasks;
using System.Windows;
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
using Wpf.Ui.Common;
After:
using Wpf;
using Wpf.Ui;
using Wpf.Ui.Common;
using Wpf.Ui.Controls;
using Wpf.Ui.Controls;
using Wpf.Ui.Controls.Interfaces;
*/
using Wpf.Ui.Common;
namespace Wpf.Ui.Controls;
......
......@@ -4,18 +4,6 @@
// All Rights Reserved.
using System.Threading.Tasks;
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
using Wpf.Ui.Common;
After:
using Wpf;
using Wpf.Ui;
using Wpf.Ui.Common;
using Wpf.Ui.Controls;
using Wpf.Ui.Controls;
using Wpf.Ui.Controls.Interfaces;
*/
using Wpf.Ui.Common;
namespace Wpf.Ui.Controls;
......
......@@ -5,6 +5,7 @@
using System;
using System.Windows;
using Wpf.Ui.Common;
namespace Wpf.Ui.Controls;
......@@ -56,7 +57,7 @@ public class InfoBar : System.Windows.Controls.ContentControl
/// Property for <see cref="TemplateButtonCommand"/>.
/// </summary>
public static readonly DependencyProperty TemplateButtonCommandProperty =
DependencyProperty.Register(nameof(TemplateButtonCommand), typeof(Common.IRelayCommand), typeof(InfoBar),
DependencyProperty.Register(nameof(TemplateButtonCommand), typeof(IRelayCommand), typeof(InfoBar),
new PropertyMetadata(null));
/// <summary>
......@@ -109,15 +110,15 @@ public InfoBarSeverity Severity
}
/// <summary>
/// Gets the <see cref="Common.RelayCommand"/> triggered after clicking
/// Gets the <see cref="RelayCommand{T}"/> triggered after clicking
/// the close button.
/// </summary>
public Common.IRelayCommand TemplateButtonCommand => (Common.IRelayCommand)GetValue(TemplateButtonCommandProperty);
public IRelayCommand TemplateButtonCommand => (IRelayCommand)GetValue(TemplateButtonCommandProperty);
/// <inheritdoc />
public InfoBar()
{
SetValue(TemplateButtonCommandProperty,
new Common.RelayCommand(o => IsOpen = false));
new RelayCommand<bool>(o => IsOpen = false));
}
}
......@@ -7,6 +7,7 @@
using System.ComponentModel;
using System.Drawing;
using System.Windows;
using Wpf.Ui.Common;
using Wpf.Ui.Interop;
namespace Wpf.Ui.Controls;
......@@ -52,15 +53,6 @@ public class MessageBox : System.Windows.Window
/// Property for <see cref="ButtonLeftAppearance"/>.
/// </summary>
public static readonly DependencyProperty ButtonLeftAppearanceProperty = DependencyProperty.Register(nameof(ButtonLeftAppearance),
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
typeof(Common.ControlAppearance), typeof(MessageBox),
new PropertyMetadata(Common.ControlAppearance.Primary));
After:
typeof(ControlAppearance), typeof(MessageBox),
new PropertyMetadata(ControlAppearance.Primary));
*/
typeof(Controls.ControlAppearance), typeof(MessageBox),
new PropertyMetadata(Controls.ControlAppearance.Primary));
......@@ -80,15 +72,6 @@ public class MessageBox : System.Windows.Window
/// Property for <see cref="ButtonRightAppearance"/>.
/// </summary>
public static readonly DependencyProperty ButtonRightAppearanceProperty = DependencyProperty.Register(nameof(ButtonRightAppearance),
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
typeof(Common.ControlAppearance), typeof(MessageBox),
new PropertyMetadata(Common.ControlAppearance.Secondary));
After:
typeof(ControlAppearance), typeof(MessageBox),
new PropertyMetadata(ControlAppearance.Secondary));
*/
typeof(Controls.ControlAppearance), typeof(MessageBox),
new PropertyMetadata(Controls.ControlAppearance.Secondary));
......@@ -153,22 +136,8 @@ public string ButtonLeftName
/// <summary>
/// Gets or sets the <see cref="ControlAppearance"/> of the button on the left, if available.
/// </summary>
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
public Common.ControlAppearance ButtonLeftAppearance
After:
public ControlAppearance ButtonLeftAppearance
*/
public Controls.ControlAppearance ButtonLeftAppearance
{
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
get => (Common.ControlAppearance)GetValue(ButtonLeftAppearanceProperty);
After:
get => (ControlAppearance)GetValue(ButtonLeftAppearanceProperty);
*/
get => (Controls.ControlAppearance)GetValue(ButtonLeftAppearanceProperty);
set => SetValue(ButtonLeftAppearanceProperty, value);
}
......@@ -194,22 +163,8 @@ public string ButtonRightName
/// <summary>
/// Gets or sets the <see cref="ControlAppearance"/> of the button on the right, if available.
/// </summary>
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
public Common.ControlAppearance ButtonRightAppearance
After:
public ControlAppearance ButtonRightAppearance
*/
public Controls.ControlAppearance ButtonRightAppearance
{
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
get => (Common.ControlAppearance)GetValue(ButtonRightAppearanceProperty);
After:
get => (ControlAppearance)GetValue(ButtonRightAppearanceProperty);
*/
get => (Controls.ControlAppearance)GetValue(ButtonRightAppearanceProperty);
set => SetValue(ButtonRightAppearanceProperty, value);
}
......@@ -226,7 +181,7 @@ public Controls.ControlAppearance ButtonRightAppearance
/// <summary>
/// Command triggered after clicking the button on the Footer.
/// </summary>
public Common.IRelayCommand TemplateButtonCommand => (Common.IRelayCommand)GetValue(TemplateButtonCommandProperty);
public IRelayCommand TemplateButtonCommand => (IRelayCommand)GetValue(TemplateButtonCommandProperty);
/// <summary>
/// Creates new instance and sets default <see cref="FrameworkElement.Loaded"/> event.
......@@ -241,7 +196,7 @@ public MessageBox()
WindowStartupLocation = WindowStartupLocation.CenterOwner;
SetValue(TemplateButtonCommandProperty, new Common.RelayCommand(o => Button_OnClick(this, o)));
SetValue(TemplateButtonCommandProperty, new RelayCommand<string>(o => OnTemplateButtonClick(o ?? String.Empty)));
}
/// Shows a <see cref="System.Windows.MessageBox"/>.
......@@ -288,18 +243,13 @@ private void SetWindowStartupLocation()
WindowStartupLocation = WindowStartupLocation.CenterScreen;
}
private void Button_OnClick(object sender, object parameter)
private void OnTemplateButtonClick(string parameter)
{
if (parameter == null)
return;
string param = parameter as string ?? String.Empty;
#if DEBUG
System.Diagnostics.Debug.WriteLine($"INFO | {typeof(MessageBox)} button clicked with param: {param}", "Wpf.Ui.MessageBox");
System.Diagnostics.Debug.WriteLine($"INFO | {typeof(MessageBox)} button clicked with param: {parameter}", "Wpf.Ui.MessageBox");
#endif
switch (param)
switch (parameter)
{
case "left":
RaiseEvent(new RoutedEventArgs(ButtonLeftClickEvent, this));
......
......@@ -59,13 +59,6 @@ public static FrameworkElement CreateInstance(Type pageType, object? dataContext
{
var selectedCtor = FitBestConstructor(pageConstructors, dataContext);
if (selectedCtor == null)
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
throw new InvalidOperationException($"The {pageType} page does not have a parameterless constructor or the required services have not been configured for dependency injection. Use the static {nameof(ControlsServices)} class to initialize the GUI library with your service provider. If you are using {typeof(Mvvm.Contracts.IPageService)} do not navigate initially and don't use Cache or Precache.");
After:
throw new InvalidOperationException($"The {pageType} page does not have a parameterless constructor or the required services have not been configured for dependency injection. Use the static {nameof(ControlsServices)} class to initialize the GUI library with your service provider. If you are using {typeof(IPageService)} do not navigate initially and don't use Cache or Precache.");
*/
throw new InvalidOperationException($"The {pageType} page does not have a parameterless constructor or the required services have not been configured for dependency injection. Use the static {nameof(ControlsServices)} class to initialize the GUI library with your service provider. If you are using {typeof(Contracts.IPageService)} do not navigate initially and don't use Cache or Precache.");
instance = InvokeElementConstructor(selectedCtor, dataContext);
......@@ -84,14 +77,8 @@ public static FrameworkElement CreateInstance(Type pageType, object? dataContext
}
var emptyConstructor = FindParameterlessConstructor(pageType);
if (emptyConstructor == null)
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
throw new InvalidOperationException($"The {pageType} page does not have a parameterless constructor. If you are using {typeof(Mvvm.Contracts.IPageService)} do not navigate initially and don't use Cache or Precache.");
After:
throw new InvalidOperationException($"The {pageType} page does not have a parameterless constructor. If you are using {typeof(IPageService)} do not navigate initially and don't use Cache or Precache.");
*/
if (emptyConstructor == null)
throw new InvalidOperationException($"The {pageType} page does not have a parameterless constructor. If you are using {typeof(Contracts.IPageService)} do not navigate initially and don't use Cache or Precache.");
instance = emptyConstructor.Invoke(null) as FrameworkElement;
......
......@@ -24,13 +24,6 @@ public enum NavigationViewPaneDisplayMode
LeftMinimal,
/// <summary>
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
/// The pane is shown on the left side of the control. Large icons with titles underneath are the only display option. Does not support <see cref="Wpf.Ui.Controls.Interfaces.INavigationViewItem.MenuItems"/>.
After:
/// The pane is shown on the left side of the control. Large icons with titles underneath are the only display option. Does not support <see cref="INavigationViewItem.MenuItems"/>.
*/
/// The pane is shown on the left side of the control. Large icons with titles underneath are the only display option. Does not support <see cref="Navigation.INavigationViewItem.MenuItems"/>.
/// <para>Similar to the Windows Store (2022) app.</para>
/// </summary>
......
......@@ -237,17 +237,11 @@ protected virtual void OnValueChanged()
}
/// <inheritdoc/>
protected override void OnTemplateButtonClick(object sender, object parameter)
protected override void OnTemplateButtonClick(string parameter)
{
base.OnTemplateButtonClick(sender, parameter);
base.OnTemplateButtonClick(parameter);
if (sender is not NumberBox)
return;
if (parameter is not string parameterString)
return;
switch (parameterString)
switch (parameter)
{
case "increment":
IncrementValue();
......
......@@ -170,18 +170,15 @@ protected virtual void OnPasswordRevealModeChanged()
/// </summary>
/// <param name="sender">Sender of the click event.</param>
/// <param name="parameter">Additional parameters.</param>
protected override void OnTemplateButtonClick(object sender, object parameter)
protected override void OnTemplateButtonClick(string parameter)
{
base.OnTemplateButtonClick(sender, parameter);
if (parameter is not string parameterString)
return;
base.OnTemplateButtonClick(parameter);
#if DEBUG
System.Diagnostics.Debug.WriteLine($"INFO: {typeof(PasswordBox)} button clicked with param: {parameterString}", "Wpf.Ui.PasswordBox");
System.Diagnostics.Debug.WriteLine($"INFO: {typeof(PasswordBox)} button clicked with param: {parameter}", "Wpf.Ui.PasswordBox");
#endif
switch (parameterString)
switch (parameter)
{
case "reveal":
IsPasswordRevealed = !IsPasswordRevealed;
......
......@@ -81,15 +81,6 @@ public class Snackbar : System.Windows.Controls.ContentControl, ISnackbarControl
/// Property for <see cref="Appearance"/>.
/// </summary>
public static readonly DependencyProperty AppearanceProperty = DependencyProperty.Register(nameof(Appearance),
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
typeof(Common.ControlAppearance), typeof(Snackbar),
new PropertyMetadata(Common.ControlAppearance.Secondary));
After:
typeof(ControlAppearance), typeof(Snackbar),
new PropertyMetadata(ControlAppearance.Secondary));
*/
typeof(Controls.ControlAppearance), typeof(Snackbar),
new PropertyMetadata(Controls.ControlAppearance.Secondary));
......@@ -180,22 +171,8 @@ public Brush MessageForeground
/// <inheritdoc />
[Bindable(true), Category("Appearance")]
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
public Common.ControlAppearance Appearance
After:
public ControlAppearance Appearance
*/
public Controls.ControlAppearance Appearance
{
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
get => (Common.ControlAppearance)GetValue(AppearanceProperty);
After:
get => (ControlAppearance)GetValue(AppearanceProperty);
*/
get => (Controls.ControlAppearance)GetValue(AppearanceProperty);
set => SetValue(AppearanceProperty, value);
}
......@@ -243,7 +220,7 @@ public TranslateTransform SlideTransform
}
/// <summary>
/// Gets the <see cref="Common.RelayCommand"/> triggered after clicking close button.
/// Gets the <see cref="Common.RelayCommand{T}"/> triggered after clicking close button.
/// </summary>
public Common.IRelayCommand TemplateButtonCommand => (Common.IRelayCommand)GetValue(TemplateButtonCommandProperty);
......@@ -253,7 +230,7 @@ public Snackbar()
{
_eventIdentifier = new EventIdentifier();
SetValue(TemplateButtonCommandProperty, new Common.RelayCommand(o => OnTemplateButtonClick(this, o)));
SetValue(TemplateButtonCommandProperty, new Common.RelayCommand<string>(o => OnTemplateButtonClick(o ?? String.Empty)));
}
/// <inheritdoc />
......@@ -345,14 +322,9 @@ public async Task<bool> HideAsync()
/// <summary>
/// Triggered by clicking a button in the control template.
/// </summary>
/// <param name="sender">Sender of the click event.</param>
/// <param name="parameter">Additional parameters.</param>
protected virtual async void OnTemplateButtonClick(object sender, object parameter)
protected virtual async void OnTemplateButtonClick(string parameter)
{
if (parameter is not String parameterString)
return;
if (parameterString == "close")
if (parameter == "close")
await HideAsync();
}
......
......@@ -6,11 +6,10 @@
using System;
using System.Windows;
using System.Windows.Controls;
using Wpf.Ui.Common;
using Brush = System.Windows.Media.Brush;
using SystemColors = System.Windows.SystemColors;
// TODO: Fix clear button
namespace Wpf.Ui.Controls;
/// <summary>
......@@ -22,25 +21,16 @@ public class TextBox : System.Windows.Controls.TextBox, IIconControl
/// Property for <see cref="Icon"/>.
/// </summary>
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(nameof(Icon),
typeof(Common.SymbolRegular), typeof(TextBox),
new PropertyMetadata(Common.SymbolRegular.Empty));
typeof(SymbolRegular), typeof(TextBox),
new PropertyMetadata(SymbolRegular.Empty));
/// <summary>
/// Property for <see cref="IconPlacement"/>.
/// </summary>
public static readonly DependencyProperty IconPlacementProperty = DependencyProperty.Register(
nameof(IconPlacement),
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
typeof(Common.ElementPlacement), typeof(TextBox),
new PropertyMetadata(Common.ElementPlacement.Left));
After:
typeof(ElementPlacement), typeof(TextBox),
new PropertyMetadata(ElementPlacement.Left));
*/
typeof(Controls.ElementPlacement), typeof(TextBox),
new PropertyMetadata(Controls.ElementPlacement.Left));
/// <summary>
/// Property for <see cref="IconFilled"/>.
......@@ -90,35 +80,21 @@ public class TextBox : System.Windows.Controls.TextBox, IIconControl
/// </summary>
public static readonly DependencyProperty TemplateButtonCommandProperty =
DependencyProperty.Register(nameof(TemplateButtonCommand),
typeof(Common.IRelayCommand), typeof(TextBox), new PropertyMetadata(null));
typeof(IRelayCommand), typeof(TextBox), new PropertyMetadata(null));
/// <inheritdoc />
public Common.SymbolRegular Icon
public SymbolRegular Icon
{
get => (Common.SymbolRegular)GetValue(IconProperty);
get => (SymbolRegular)GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
/// <summary>
/// Defines which side the icon should be placed on.
/// </summary>
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
public Common.ElementPlacement IconPlacement
After:
public ElementPlacement IconPlacement
*/
public Controls.ElementPlacement IconPlacement
{
/* Unmerged change from project 'Wpf.Ui (net7.0-windows)'
Before:
get => (Common.ElementPlacement)GetValue(IconPlacementProperty);
After:
get => (ElementPlacement)GetValue(IconPlacementProperty);
*/
get => (Controls.ElementPlacement)GetValue(IconPlacementProperty);
set => SetValue(IconPlacementProperty, value);
}
......@@ -177,14 +153,14 @@ public bool ShowClearButton
/// <summary>
/// Command triggered after clicking the button.
/// </summary>
public Common.IRelayCommand TemplateButtonCommand => (Common.IRelayCommand)GetValue(TemplateButtonCommandProperty);
public IRelayCommand TemplateButtonCommand => (IRelayCommand)GetValue(TemplateButtonCommandProperty);
/// <summary>
/// Creates a new instance and assigns default events.
/// </summary>
public TextBox()
{
SetValue(TemplateButtonCommandProperty, new Common.RelayCommand(o => OnTemplateButtonClick(this, o)));
SetValue(TemplateButtonCommandProperty, new RelayCommand<string>(o => OnTemplateButtonClick(o ?? String.Empty)));
}
/// <inheritdoc />
......@@ -247,20 +223,13 @@ protected virtual void OnClearButtonClick()
/// <summary>
/// Triggered by clicking a button in the control template.
/// </summary>
/// <param name="sender">Sender of the click event.</param>
/// <param name="parameter">Additional parameters.</param>
protected virtual void OnTemplateButtonClick(object sender, object parameter)
protected virtual void OnTemplateButtonClick(string parameter)
{
if (parameter == null)
return;
var param = parameter as string ?? String.Empty;
#if DEBUG
System.Diagnostics.Debug.WriteLine($"INFO: {typeof(TextBox)} button clicked with param: {param}", "Wpf.Ui.TextBox");
System.Diagnostics.Debug.WriteLine($"INFO: {typeof(TextBox)} button clicked with param: {parameter}", "Wpf.Ui.TextBox");
#endif
switch (param)
switch (parameter)
{
case "clear":
OnClearButtonClick();
......
......@@ -3,9 +3,11 @@
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows;
using Wpf.Ui.Common;
using Wpf.Ui.Controls.States;
namespace Wpf.Ui.Controls;
......@@ -58,29 +60,22 @@ public ThumbRateState State
/// <summary>
/// Command triggered after clicking the button.
/// </summary>
public Common.IRelayCommand TemplateButtonCommand => (Common.IRelayCommand)GetValue(TemplateButtonCommandProperty);
public IRelayCommand TemplateButtonCommand => (IRelayCommand)GetValue(TemplateButtonCommandProperty);
/// <summary>
/// Creates new instance and attaches <see cref="TemplateButtonCommand"/>.
/// </summary>
public ThumbRate()
{
SetValue(TemplateButtonCommandProperty, new Common.RelayCommand(o => OnButtonClick(this, o)));
SetValue(TemplateButtonCommandProperty, new RelayCommand<string>(o => OnTemplateButtonClick(o ?? String.Empty)));
}
/// <summary>
/// Triggered by clicking a button in the control template.
/// </summary>
/// <param name="sender">Sender of the click event.</param>
/// <param name="parameter">Additional parameters.</param>
protected virtual void OnButtonClick(object sender, object parameter)
protected virtual void OnTemplateButtonClick(string parameter)
{
if (parameter is not string)
return;
var param = parameter as string;
switch (param)
switch (parameter)
{
case "up":
State = State == ThumbRateState.Liked ? ThumbRateState.None : ThumbRateState.Liked;
......
......@@ -379,7 +379,7 @@ public NotifyIcon Tray
/// </summary>
public TitleBar()
{
SetValue(TemplateButtonCommandProperty, new Common.RelayCommand(o => OnTemplateButtonClick(this, o)));
SetValue(TemplateButtonCommandProperty, new Common.RelayCommand<string>(o => OnTemplateButtonClick(o ?? String.Empty)));
Loaded += OnLoaded;
}
......@@ -612,11 +612,9 @@ private void OnMainGridMouseLeftButtonDown(object sender, MouseButtonEventArgs e
MaximizeWindow();
}
private void OnTemplateButtonClick(TitleBar sender, object parameter)
private void OnTemplateButtonClick(string parameter)
{
string command = parameter as string ?? String.Empty;
switch (command)
switch (parameter)
{
case "maximize":
RaiseEvent(new RoutedEventArgs(MaximizeClickedEvent, this));
......
......@@ -96,7 +96,8 @@
Background="Transparent"
BorderThickness="0"
Command="{Binding Path=TemplateButtonCommand, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
Icon="Dismiss24" />
Icon="Dismiss24"
IsEnabled="True" />
</Border>
</Grid>
</Border>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册