Merge branch 'main' of github.com:KJD2025/29WxOrder

This commit is contained in:
wule committed 2026-10-12 18:48:54 +08:00
commit 5fb42e4d34
15 files changed
+1055 -21

No files matched your search

+5 -2
View File
@@ -1,4 +1,5 @@
using System;
using Prism.Services.Dialogs;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Contexts;
@@ -14,7 +15,7 @@ namespace _29WxOrderWpf.Common
/// <summary>
/// DialogWindow.xaml 的交互逻辑
/// </summary>
public partial class DialogWindow : Window
public partial class DialogWindow : Window, IDialogWindow
{
private readonly Style dialogWindowStyle;
private bool isConstructorSuccessful = false;
@@ -101,6 +102,8 @@ namespace _29WxOrderWpf.Common
private const int GWL_STYLE = -16;
private const int WS_MINIMIZEBOX = 0x00020000;
public IDialogResult Result { get; set; }
[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
@@ -0,0 +1,41 @@
namespace Prism.Services.Dialogs
{
/// <summary>
/// The result of the dialog.
/// </summary>
public enum ButtonResult
{
/// <summary>
/// Abort.
/// </summary>
Abort = 3,
/// <summary>
/// Cancel.
/// </summary>
Cancel = 2,
/// <summary>
/// Ignore.
/// </summary>
Ignore = 5,
/// <summary>
/// No.
/// </summary>
No = 7,
/// <summary>
/// No result returned.
/// </summary>
None = 0,
/// <summary>
/// OK.
/// </summary>
OK = 1,
/// <summary>
/// Retry.
/// </summary>
Retry = 4,
/// <summary>
/// Yes.
/// </summary>
Yes = 6
}
}
+82
View File
@@ -0,0 +1,82 @@
#if HAS_UWP
using Windows.UI.Xaml;
#elif HAS_WINUI
using Microsoft.UI.Xaml;
#else
using System.Windows;
#endif
namespace Prism.Services.Dialogs
{
/// <summary>
/// This class contains <see cref="IDialogWindow"/> attached properties.
/// </summary>
public class Dialog
{
/// <summary>
/// Identifies the WindowStyle attached property.
/// </summary>
/// <remarks>
/// This attached property is used to specify the style of a <see cref="IDialogWindow"/>.
/// </remarks>
public static readonly DependencyProperty WindowStyleProperty =
DependencyProperty.RegisterAttached("WindowStyle", typeof(Style), typeof(Dialog), new PropertyMetadata(null));
/// <summary>
/// Gets the value for the <see cref="WindowStyleProperty"/> attached property.
/// </summary>
/// <param name="obj">The target element.</param>
/// <returns>The <see cref="WindowStyleProperty"/> attached to the <paramref name="obj"/> element.</returns>
public static Style GetWindowStyle(DependencyObject obj)
{
return (Style)obj.GetValue(WindowStyleProperty);
}
/// <summary>
/// Sets the <see cref="WindowStyleProperty"/> attached property.
/// </summary>
/// <param name="obj">The target element.</param>
/// <param name="value">The Style to attach.</param>
public static void SetWindowStyle(DependencyObject obj, Style value)
{
obj.SetValue(WindowStyleProperty, value);
}
#if !HAS_UWP && !HAS_WINUI
/// <summary>
/// Identifies the WindowStartupLocation attached property.
/// </summary>
/// <remarks>
/// This attached property is used to specify the startup location of a <see cref="IDialogWindow"/>.
/// </remarks>
public static readonly DependencyProperty WindowStartupLocationProperty =
DependencyProperty.RegisterAttached("WindowStartupLocation", typeof(WindowStartupLocation), typeof(Dialog), new UIPropertyMetadata(OnWindowStartupLocationChanged));
/// <summary>
/// Gets the value for the <see cref="WindowStartupLocationProperty"/> attached property.
/// </summary>
/// <param name="obj">The target element.</param>
/// <returns>The <see cref="WindowStartupLocationProperty"/> attached to the <paramref name="obj"/> element.</returns>
public static WindowStartupLocation GetWindowStartupLocation(DependencyObject obj)
{
return (WindowStartupLocation)obj.GetValue(WindowStartupLocationProperty);
}
/// <summary>
/// Sets the <see cref="WindowStartupLocationProperty"/> attached property.
/// </summary>
/// <param name="obj">The target element.</param>
/// <param name="value">The WindowStartupLocation to attach.</param>
public static void SetWindowStartupLocation(DependencyObject obj, WindowStartupLocation value)
{
obj.SetValue(WindowStartupLocationProperty, value);
}
private static void OnWindowStartupLocationChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (sender is Window window)
window.WindowStartupLocation = (WindowStartupLocation)e.NewValue;
}
#endif
}
}
@@ -0,0 +1,24 @@
using Prism.Common;
namespace Prism.Services.Dialogs
{
/// <summary>
/// Represents Dialog parameters.
/// </summary>
/// <remarks>
/// This class can be used to to pass object parameters during the showing and closing of Dialogs.
/// </remarks>
public class DialogParameters : ParametersBase, IDialogParameters
{
/// <summary>
/// Initializes a new instance of the <see cref="DialogParameters"/> class.
/// </summary>
public DialogParameters() : base() { }
/// <summary>
/// Constructs a list of parameters.
/// </summary>
/// <param name="query">Query string to be parsed.</param>
public DialogParameters(string query) : base(query) { }
}
}
@@ -0,0 +1,44 @@
namespace Prism.Services.Dialogs
{
/// <summary>
/// An <see cref="IDialogResult"/> that contains <see cref="IDialogParameters"/> from the dialog
/// and the <see cref="ButtonResult"/> of the dialog.
/// </summary>
public class DialogResult : IDialogResult
{
/// <summary>
/// The parameters from the dialog.
/// </summary>
public IDialogParameters Parameters { get; private set; } = new DialogParameters();
/// <summary>
/// The result of the dialog.
/// </summary>
public ButtonResult Result { get; private set; } = ButtonResult.None;
/// <summary>
/// Initializes a new instance of the <see cref="DialogResult"/> class.
/// </summary>
public DialogResult() { }
/// <summary>
/// Initializes a new instance of the <see cref="DialogResult"/> class.
/// </summary>
/// <param name="result">The result of the dialog.</param>
public DialogResult(ButtonResult result)
{
Result = result;
}
/// <summary>
/// Initializes a new instance of the <see cref="DialogResult"/> class.
/// </summary>
/// <param name="result">The result of the dialog.</param>
/// <param name="parameters">The parameters from the dialog.</param>
public DialogResult(ButtonResult result, IDialogParameters parameters)
{
Result = result;
Parameters = parameters;
}
}
}
@@ -0,0 +1,170 @@
using _29WxOrderWpf.Common;
using Prism.Common;
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows;
namespace Prism.Services.Dialogs
{
/// <summary>
/// 静态弹窗服务:不依赖容器,直接传入 View 实例弹出。
/// ViewModel 需实现 IDialogAware。
/// </summary>
public static class DialogService
{
// ========== 对外接口 ==========
/// <summary>非模态弹出</summary>
public static void Show(FrameworkElement view,
IDialogParameters parameters = null,
Action<IDialogResult> callback = null,
IDialogWindow window = null)
{
ShowInternal(view, parameters, callback, false, window);
}
/// <summary>模态弹出</summary>
public static void ShowDialog(FrameworkElement view,
IDialogParameters parameters = null,
Action<IDialogResult> callback = null,
IDialogWindow window = null)
{
ShowInternal(view, parameters, callback, true, window);
}
// ========== 内部实现 ==========
private static void ShowInternal(FrameworkElement view,
IDialogParameters parameters,
Action<IDialogResult> callback,
bool isModal,
IDialogWindow window)
{
if (view == null) throw new ArgumentNullException(nameof(view));
if (parameters == null) parameters = new DialogParameters();
// 1. 创建(或使用传入的)DialogWindow
var dialogWindow = window ?? new DialogWindow();
// 2. 绑定事件(关闭、回调等)
ConfigureDialogWindowEvents(dialogWindow, callback);
// 3. 配置内容(View + ViewModel)
ConfigureDialogWindowContent(view, dialogWindow, parameters);
// 4. 弹出
ShowDialogWindow(dialogWindow, isModal);
}
private static void ShowDialogWindow(IDialogWindow dialogWindow, bool isModal)
{
if (isModal)
dialogWindow.ShowDialog();
else
dialogWindow.Show();
}
/// <summary>
/// 把 View 挂到 DialogWindow 上,并触发 OnDialogOpened。
/// </summary>
private static void ConfigureDialogWindowContent(FrameworkElement dialogContent,
IDialogWindow window,
IDialogParameters parameters)
{
// 不再自动绑 ViewModel,DataContext 由 View 自己负责
if (!(dialogContent.DataContext is IDialogAware viewModel))
throw new NullReferenceException("A dialog's ViewModel must implement the IDialogAware interface");
ConfigureDialogWindowProperties(window, dialogContent, viewModel);
// 直接触发 OnDialogOpened(替代 MvvmHelpers.ViewAndViewModelAction)
viewModel.OnDialogOpened(parameters);
}
/// <summary>
/// 绑定 DialogWindow 的生命周期事件。
/// </summary>
private static void ConfigureDialogWindowEvents(IDialogWindow dialogWindow, Action<IDialogResult> callback)
{
Action<IDialogResult> requestCloseHandler = null;
requestCloseHandler = (o) =>
{
dialogWindow.Result = o;
dialogWindow.Close();
};
RoutedEventHandler loadedHandler = null;
loadedHandler = (o, e) =>
{
dialogWindow.Loaded -= loadedHandler;
GetDialogViewModel(dialogWindow).RequestClose += requestCloseHandler;
};
dialogWindow.Loaded += loadedHandler;
CancelEventHandler closingHandler = null;
closingHandler = (o, e) =>
{
if (!GetDialogViewModel(dialogWindow).CanCloseDialog())
e.Cancel = true;
};
dialogWindow.Closing += closingHandler;
EventHandler closedHandler = null;
closedHandler = (o, e) =>
{
dialogWindow.Closed -= closedHandler;
dialogWindow.Closing -= closingHandler;
GetDialogViewModel(dialogWindow).RequestClose -= requestCloseHandler;
GetDialogViewModel(dialogWindow).OnDialogClosed();
if (dialogWindow.Result == null)
dialogWindow.Result = new DialogResult();
callback?.Invoke(dialogWindow.Result);
dialogWindow.DataContext = null;
dialogWindow.Content = null;
};
dialogWindow.Closed += closedHandler;
}
/// <summary>
/// 设置 DialogWindow 的 Style / Content / DataContext / Owner。
/// </summary>
private static void ConfigureDialogWindowProperties(IDialogWindow window,
FrameworkElement dialogContent,
IDialogAware viewModel)
{
var windowStyle = Dialog.GetWindowStyle(dialogContent);
if (windowStyle != null)
window.Style = windowStyle;
window.Content = dialogContent;
window.DataContext = viewModel; // 宿主窗口和对话框共享同一个 DataContext
if (window.Owner == null)
window.Owner = Application.Current?.Windows
.OfType<Window>()
.FirstOrDefault(x => x.IsActive);
}
/// <summary>
/// 从 window.Content 或 window.DataContext 里拿 IDialogAware。
/// 替代 Prism 的 dialogWindow.GetDialogViewModel() 扩展方法。
/// </summary>
private static IDialogAware GetDialogViewModel(IDialogWindow window)
{
if (window.Content is FrameworkElement fe)
{
if (fe is IDialogAware aware) return aware;
if (fe.DataContext is IDialogAware vm) return vm;
}
if (window.DataContext is IDialogAware wvm) return wvm;
throw new NullReferenceException("A dialog's ViewModel must implement the IDialogAware interface");
}
}
}
@@ -0,0 +1,37 @@
using System;
namespace Prism.Services.Dialogs
{
/// <summary>
/// Interface that provides dialog functions and events to ViewModels.
/// </summary>
public interface IDialogAware
{
/// <summary>
/// Determines if the dialog can be closed.
/// </summary>
/// <returns>If <c>true</c> the dialog can be closed. If <c>false</c> the dialog will not close.</returns>
bool CanCloseDialog();
/// <summary>
/// Called when the dialog is closed.
/// </summary>
void OnDialogClosed();
/// <summary>
/// Called when the dialog is opened.
/// </summary>
/// <param name="parameters">The parameters passed to the dialog.</param>
void OnDialogOpened(IDialogParameters parameters);
/// <summary>
/// The title of the dialog that will show in the window title bar.
/// </summary>
string Title { get; }
/// <summary>
/// Instructs the <see cref="IDialogWindow"/> to close the dialog.
/// </summary>
event Action<IDialogResult> RequestClose;
}
}
@@ -0,0 +1,63 @@
using System.Collections.Generic;
namespace Prism.Services.Dialogs
{
/// <summary>
/// Represents Dialog parameters.
/// </summary>
/// <remarks>
/// A class that implements this interface can be used to pass
/// object parameters during the showing and closing of Dialogs.
/// </remarks>
public interface IDialogParameters
{
/// <summary>
/// Adds the key and value to the collection.
/// </summary>
/// <param name="key">The key to reference this parameter value in the collection.</param>
/// <param name="value">The parameter value to store.</param>
void Add(string key, object value);
/// <summary>
/// Checks the collection for the presence of a key.
/// </summary>
/// <param name="key">The key to check.</param>
/// <returns><c>true</c> if key exists; <c>false</c> otherwise.</returns>
bool ContainsKey(string key);
/// <summary>
/// The number of parameters in the collection.
/// </summary>
int Count { get; }
/// <summary>
/// The keys in the collection.
/// </summary>
IEnumerable<string> Keys { get; }
/// <summary>
/// Gets the parameter value referenced by a key.
/// </summary>
/// <typeparam name="T">The type of object to be returned.</typeparam>
/// <param name="key">The key of the parameter value to be returned.</param>
/// <returns>The matching parameter of type <typeparamref name="T"/>.</returns>
T GetValue<T>(string key);
/// <summary>
/// Gets all parameter values referenced by a key.
/// </summary>
/// <typeparam name="T">The type of object to be returned.</typeparam>
/// <param name="key">The key of the parameter values to be returned.</param>
///<returns>All matching parameter values of type <typeparamref name="T"/>.</returns>
IEnumerable<T> GetValues<T>(string key);
/// <summary>
/// Gets the parameter value if the referenced key exists.
/// </summary>
/// <typeparam name="T">The type of object to be returned.</typeparam>
/// <param name="key">The key of the parameter value to be returned.</param>
/// <param name="value">The matching parameter of type <typeparamref name="T"/> if the key exists.</param>
/// <returns><c>true</c> if the parameter exists; <c>false</c> otherwise.</returns>
bool TryGetValue<T>(string key, out T value);
}
}
@@ -0,0 +1,19 @@
namespace Prism.Services.Dialogs
{
/// <summary>
/// Contains <see cref="IDialogParameters"/> from the dialog
/// and the <see cref="ButtonResult"/> of the dialog.
/// </summary>
public interface IDialogResult
{
/// <summary>
/// The parameters from the dialog.
/// </summary>
IDialogParameters Parameters { get; }
/// <summary>
/// The result of the dialog.
/// </summary>
ButtonResult Result { get; }
}
}
@@ -0,0 +1,71 @@
using System;
using System.ComponentModel;
using System.Windows;
namespace Prism.Services.Dialogs
{
/// <summary>
/// Interface for a dialog hosting window.
/// </summary>
public interface IDialogWindow
{
/// <summary>
/// Dialog content.
/// </summary>
object Content { get; set; }
/// <summary>
/// Close the window.
/// </summary>
void Close();
/// <summary>
/// The window's owner.
/// </summary>
Window Owner { get; set; }
/// <summary>
/// Show a non-modal dialog.
/// </summary>
void Show();
/// <summary>
/// Show a modal dialog.
/// </summary>
/// <returns></returns>
bool? ShowDialog();
/// <summary>
/// The data context of the window.
/// </summary>
/// <remarks>
/// The data context must implement <see cref="IDialogAware"/>.
/// </remarks>
object DataContext { get; set; }
/// <summary>
/// Called when the window is loaded.
/// </summary>
event RoutedEventHandler Loaded;
/// <summary>
/// Called when the window is closed.
/// </summary>
event EventHandler Closed;
/// <summary>
/// Called when the window is closing.
/// </summary>
event CancelEventHandler Closing;
/// <summary>
/// The result of the dialog.
/// </summary>
IDialogResult Result { get; set; }
/// <summary>
/// The window style.
/// </summary>
Style Style { get; set; }
}
}
@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Prism.Common
{
/// <summary>
/// Defines a contract for specifying values associated with a unique key.
/// </summary>
public interface IParameters : IEnumerable<KeyValuePair<string, object>>
{
/// <summary>
/// Adds the specified key and value to the parameter collection.
/// </summary>
/// <param name="key">The key of the parameter to add.</param>
/// <param name="value">The value of the parameter to add.</param>
void Add(string key, object value);
/// <summary>
/// Determines whether the <see cref="IParameters"/> contains the specified <paramref name="key"/>.
/// </summary>
/// <param name="key">The key to search the parameters for existence.</param>
/// <returns>true if the <see cref="IParameters"/> contains a parameter with the specified key; otherwise, false.</returns>
bool ContainsKey(string key);
/// <summary>
/// Gets the number of parameters contained in the <see cref="IParameters"/>.
/// </summary>
int Count { get; }
/// <summary>
/// Gets a collection containing the keys in the <see cref="IParameters"/>.
/// </summary>
IEnumerable<string> Keys { get; }
/// <summary>
/// Gets the parameter associated with the specified <paramref name="key"/>.
/// </summary>
/// <typeparam name="T">The type of the parameter to get.</typeparam>
/// <param name="key">The key of the parameter to find.</param>
/// <returns>A matching value of <typeparamref name="T"/> if it exists.</returns>
T GetValue<T>(string key);
/// <summary>
/// Gets the parameter associated with the specified <paramref name="key"/>.
/// </summary>
/// <typeparam name="T">The type of the parameter to get.</typeparam>
/// <param name="key">The key of the parameter to find.</param>
/// <returns>An <see cref="IEnumerable{T}"/> of all the values referenced by key.</returns>
IEnumerable<T> GetValues<T>(string key);
/// <summary>
/// Gets the parameter associated with the specified <paramref name="key"/>.
/// </summary>
/// <typeparam name="T">The type of the parameter to get.</typeparam>
/// <param name="key">The key of the parameter to get.</param>
/// <param name="value">
/// When this method returns, contains the parameter associated with the specified key,
/// if the key is found; otherwise, the default value for the type of the value parameter.
/// </param>
/// <returns>true if the <see cref="IParameters"/> contains a parameter with the specified key; otherwise, false.</returns>
bool TryGetValue<T>(string key, out T value);
/// <summary>
/// Gets the parameter associated with the specified key (legacy).
/// </summary>
/// <param name="key">The key of the parameter to get.</param>
/// <returns>A matching value if it exists.</returns>
object this[string key] { get; }
}
}
@@ -0,0 +1,198 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace Prism.Common
{
/// <summary>
/// This is a generic parameters base class used for Dialog Parameters and Navigation Parameters.
/// </summary>
public abstract class ParametersBase : IParameters, IEnumerable<KeyValuePair<string, object>>
{
private readonly List<KeyValuePair<string, object>> _entries = new List<KeyValuePair<string, object>>();
/// <summary>
/// Default constructor.
/// </summary>
protected ParametersBase()
{
}
/// <summary>
/// Constructs a list of parameters.
/// </summary>
/// <param name="query">Query string to be parsed.</param>
protected ParametersBase(string query)
{
if (!string.IsNullOrWhiteSpace(query))
{
int num = query.Length;
for (int i = ((query.Length > 0) && (query[0] == '?')) ? 1 : 0; i < num; i++)
{
int startIndex = i;
int num4 = -1;
while (i < num)
{
char ch = query[i];
if (ch == '=')
{
if (num4 < 0)
{
num4 = i;
}
}
else if (ch == '&')
{
break;
}
i++;
}
string key = null;
string value;
if (num4 >= 0)
{
key = query.Substring(startIndex, num4 - startIndex);
value = query.Substring(num4 + 1, (i - num4) - 1);
}
else
{
value = query.Substring(startIndex, i - startIndex);
}
if (key != null)
Add(Uri.UnescapeDataString(key), Uri.UnescapeDataString(value));
}
}
}
/// <summary>
/// Searches Parameter collection and returns value if Collection contains key.
/// Otherwise returns null.
/// </summary>
/// <param name="key">The key for the value to be returned.</param>
/// <returns>The value of the parameter referenced by the key; otherwise <c>null</c>.</returns>
public object this[string key]
{
get
{
foreach (var entry in _entries)
{
if (string.Compare(entry.Key, key, StringComparison.Ordinal) == 0)
{
return entry.Value;
}
}
return null;
}
}
/// <summary>
/// The count, or number, of parameters in collection.
/// </summary>
public int Count => _entries.Count;
/// <summary>
/// Returns an IEnumerable of the Keys in the collection.
/// </summary>
public IEnumerable<string> Keys =>
_entries.Select(x => x.Key);
/// <summary>
/// Adds the key and value to the parameters collection.
/// </summary>
/// <param name="key">The key to reference this value in the parameters collection.</param>
/// <param name="value">The value of the parameter to store.</param>
public void Add(string key, object value) =>
_entries.Add(new KeyValuePair<string, object>(key, value));
/// <summary>
/// Checks collection for presence of key.
/// </summary>
/// <param name="key">The key to check in the collection.</param>
/// <returns><c>true</c> if key exists; else returns <c>false</c>.</returns>
public bool ContainsKey(string key) =>
_entries.ContainsKey(key);
/// <summary>
/// Gets an enumerator for the KeyValuePairs in parameter collection.
/// </summary>
/// <returns>Enumerator.</returns>
public IEnumerator<KeyValuePair<string, object>> GetEnumerator() =>
_entries.GetEnumerator();
/// <summary>
/// Returns the value of the member referenced by key.
/// </summary>
/// <typeparam name="T">The type of object to be returned.</typeparam>
/// <param name="key">The key for the value to be returned.</param>
/// <returns>Returns a matching parameter of <typeparamref name="T"/> if one exists in the Collection.</returns>
public T GetValue<T>(string key) =>
_entries.GetValue<T>(key);
/// <summary>
/// Returns an IEnumerable of all parameters.
/// </summary>
/// <typeparam name="T">The type for the values to be returned.</typeparam>
/// <param name="key">The key for the values to be returned.</param>
///<returns>Returns a IEnumerable of all the instances of type <typeparamref name="T"/>.</returns>
public IEnumerable<T> GetValues<T>(string key) =>
_entries.GetValues<T>(key);
/// <summary>
/// Checks to see if the parameter collection contains the value.
/// </summary>
/// <typeparam name="T">The type for the values to be returned.</typeparam>
/// <param name="key">The key for the value to be returned.</param>
/// <param name="value">Value of the returned parameter if it exists.</param>
public bool TryGetValue<T>(string key, out T value) =>
_entries.TryGetValue(key, out value);
IEnumerator IEnumerable.GetEnumerator() =>
GetEnumerator();
/// <summary>
/// Converts parameter collection to a parameter string.
/// </summary>
/// <returns>A string representation of the parameters.</returns>
public override string ToString()
{
var queryBuilder = new StringBuilder();
if (_entries.Count > 0)
{
queryBuilder.Append('?');
var first = true;
foreach (var kvp in _entries)
{
if (!first)
{
queryBuilder.Append('&');
}
else
{
first = false;
}
queryBuilder.Append(Uri.EscapeDataString(kvp.Key));
queryBuilder.Append('=');
queryBuilder.Append(Uri.EscapeDataString(kvp.Value != null ? kvp.Value.ToString() : ""));
}
}
return queryBuilder.ToString();
}
/// <summary>
/// Adds a collection of parameters to the local parameter list.
/// </summary>
/// <param name="parameters">An IEnumerable of KeyValuePairs to add to the current parameter list.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public void FromParameters(IEnumerable<KeyValuePair<string, object>> parameters) =>
_entries.AddRange(parameters);
}
}
@@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
namespace Prism.Common
{
/// <summary>
/// Extension methods for Navigation or Dialog parameters
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static class ParametersExtensions
{
/// <summary>
/// Searches <paramref name="parameters"/> for <paramref name="key"/>
/// </summary>
/// <typeparam name="T">The type of the parameter to return</typeparam>
/// <param name="parameters">A collection of parameters to search</param>
/// <param name="key">The key of the parameter to find</param>
/// <returns>A matching value of <typeparamref name="T"/> if it exists</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public static T GetValue<T>(this IEnumerable<KeyValuePair<string, object>> parameters, string key) =>
(T)GetValue(parameters, key, typeof(T));
/// <summary>
/// Searches <paramref name="parameters"/> for value referenced by <paramref name="key"/>
/// </summary>
/// <param name="parameters">A collection of parameters to search</param>
/// <param name="key">The key of the parameter to find</param>
/// <param name="type">The type of the parameter to return</param>
/// <returns>A matching value of <paramref name="type"/> if it exists</returns>
/// <exception cref="InvalidCastException">Unable to convert the value of Type</exception>
[EditorBrowsable(EditorBrowsableState.Never)]
public static object GetValue(this IEnumerable<KeyValuePair<string, object>> parameters, string key, Type type)
{
foreach (var kvp in parameters)
{
if (string.Compare(kvp.Key, key, StringComparison.Ordinal) == 0)
{
if (TryGetValueInternal(kvp, type, out var value))
return value;
throw new InvalidCastException($"Unable to convert the value of Type '{kvp.Value.GetType().FullName}' to '{type.FullName}' for the key '{key}' ");
}
}
return GetDefault(type);
}
/// <summary>
/// Searches <paramref name="parameters"/> for value referenced by <paramref name="key"/>
/// </summary>
/// <typeparam name="T">The type of the parameter to return</typeparam>
/// <param name="parameters">A collection of parameters to search</param>
/// <param name="key">The key of the parameter to find</param>
/// <param name="value">The value of parameter to return</param>
/// <returns>Success if value is found; otherwise returns <c>false</c></returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool TryGetValue<T>(this IEnumerable<KeyValuePair<string, object>> parameters, string key, out T value)
{
var type = typeof(T);
foreach (var kvp in parameters)
{
if (string.Compare(kvp.Key, key, StringComparison.Ordinal) == 0)
{
var success = TryGetValueInternal(kvp, typeof(T), out object valueAsObject);
value = (T)valueAsObject;
return success;
}
}
value = default;
return false;
}
/// <summary>
/// Searches <paramref name="parameters"/> for value referenced by <paramref name="key"/>
/// </summary>
/// <typeparam name="T">The type of the parameter to return</typeparam>
/// <param name="parameters">A collection of parameters to search</param>
/// <param name="key">The key of the parameter to find</param>
/// <returns>An IEnumerable{T} of all the values referenced by key</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public static IEnumerable<T> GetValues<T>(this IEnumerable<KeyValuePair<string, object>> parameters, string key)
{
List<T> values = new List<T>();
var type = typeof(T);
foreach (var kvp in parameters)
{
if (string.Compare(kvp.Key, key, StringComparison.Ordinal) == 0)
{
TryGetValueInternal(kvp, type, out var value);
values.Add((T)value);
}
}
return values.AsEnumerable();
}
private static bool TryGetValueInternal(KeyValuePair<string, object> kvp, Type type, out object value)
{
value = GetDefault(type);
var success = false;
if (kvp.Value == null)
{
success = true;
}
else if (kvp.Value.GetType() == type)
{
success = true;
value = kvp.Value;
}
else if (type.IsAssignableFrom(kvp.Value.GetType()))
{
success = true;
value = kvp.Value;
}
else if (type.IsEnum)
{
var valueAsString = kvp.Value.ToString();
if (Enum.IsDefined(type, valueAsString))
{
success = true;
value = Enum.Parse(type, valueAsString);
}
else if (int.TryParse(valueAsString, out var numericValue))
{
success = true;
value = Enum.ToObject(type, numericValue);
}
}
if (!success && type.GetInterface("System.IConvertible") != null)
{
success = true;
value = Convert.ChangeType(kvp.Value, type);
}
return success;
}
/// <summary>
/// Checks to see if key exists in parameter collection
/// </summary>
/// <param name="parameters">IEnumerable to search</param>
/// <param name="key">The key to search the <paramref name="parameters"/> for existence</param>
/// <returns><c>true</c> if key exists; <c>false</c> otherwise</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool ContainsKey(this IEnumerable<KeyValuePair<string, object>> parameters, string key) =>
parameters.Any(x => string.Compare(x.Key, key, StringComparison.Ordinal) == 0);
private static object GetDefault(Type type)
{
if (type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
}
}
@@ -1,5 +1,7 @@
using _29WxOrderWpf.Commands;
using _29WxOrderWpf.Common;
using _29WxOrderWpf.Ctrls.PDDInvoice.ViewModels;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -22,18 +24,25 @@ namespace _29WxOrderWpf.Ctrls.PDDInvoice;
/// <summary>
/// PDDInvoiceDialog.xaml 的交互逻辑
/// </summary>
public partial class PDDInvoiceDialog : UserControl
public partial class PDDInvoiceDialog : UserControl, IDialogAware
{
public PDDInvoiceDialog()
public PDDInvoiceDialog(InvoiceConfig config)
{
InitializeComponent();
DataContext = this;
Config = NaiBa.Util.Helper.ConfigHelper.LoadConfig<InvoiceConfig>(ConfigPath);
Config = new InvoiceConfig();
Config.Assign(config);
}
public string Title { get; set; }
public event Action<IDialogResult> RequestClose;
private void PDDInvoiceDialog_Loaded(object sender, RoutedEventArgs e)
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
Title = "设置";
}
private void ViewModel_RequestClose()
@@ -44,21 +53,35 @@ public partial class PDDInvoiceDialog : UserControl
}
private const string ConfigPath = "./invoice.config";
public InvoiceConfig Config { get; }
public ICommand ConfirmCommand => new DelegateCommand(Confirm);
private void Confirm()
{
NaiBa.Util.Helper.ConfigHelper.SaveConfig(ConfigPath, Config);
ViewModel_RequestClose();
RequestClose?.Invoke(new DialogResult(ButtonResult.OK, new DialogParameters
{
{ "config",Config}
}));
}
public ICommand CancelCommand => new DelegateCommand(Cancel);
private void Cancel()
{
ViewModel_RequestClose();
RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel));
}
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
}
@@ -15,6 +15,7 @@ using MAX.Core.Helpers;
using NaiBa.Util.Extension;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -475,13 +476,17 @@ public partial class PDDInvoiceViewModel : BindableBaseEx
private void ShowSettingDialog()
{
var view = new PDDInvoiceDialog();
new DialogWindow
var view = new PDDInvoiceDialog(Config);
DialogService.ShowDialog(view, null, result =>
{
Title = "设置",
Content = view,
}.ShowDialog();
Config = view.Config;
if (result.Result == ButtonResult.OK)
{
Config.Assign(view.Config);
NaiBa.Util.Helper.ConfigHelper.SaveConfig(ConfigPath, Config);
}
});
}
public event EventHandler<int> BatchInvoiceChanged;
@@ -506,7 +511,7 @@ public partial class PDDInvoiceViewModel : BindableBaseEx
BottomMsg = "已取消批量开票";
return;
}
if (AmountTotal >= Config.MaxAmount)
{
return;
@@ -537,6 +542,11 @@ public partial class PDDInvoiceViewModel : BindableBaseEx
order.IsSelected = false;
success++;
AmountTotal += order.order_amount / 100m;
if (Config.IsSaveData)
{
var temp = OrderInvoiceInfoList?.FirstOrDefault(a => a.order_sn == order.order_sn);
if (temp != null) temp.IsInvoiced = true;
}
}
else
{
@@ -547,6 +557,12 @@ public partial class PDDInvoiceViewModel : BindableBaseEx
BottomRMsg = $"批量开票状态:成功 {success} 个,失败 {fail} 个。总金额:{AmountTotal.ToString("N2")}";
StatisticsInvoiceAmount();
await Task.Delay(1000);
if (Config.IsSaveData)
{
SaveOrderInvoiceInfo();
}
}
}
catch (Exception ex)
@@ -716,9 +732,10 @@ public partial class PDDInvoiceViewModel : BindableBaseEx
}
}
StatisticsInvoiceAmount();
SaveOrderInvoiceInfo();
if (Config.IsSaveData)
{
SaveOrderInvoiceInfo();
}
}
#endregion
@@ -897,4 +914,12 @@ public class InvoiceConfig
public string TaxNo { get; set; }
public decimal MaxAmount { get; set; }
public bool IsSaveData { get; set; }
public void Assign(InvoiceConfig config)
{
Title = config.Title;
TaxNo = config.TaxNo;
MaxAmount = config.MaxAmount;
IsSaveData = config.IsSaveData;
}
}