1.
using System.Windows;
using System.Windows.Data;namespace Macad.Presentation
{// 定义了一个辅助类 BindingHelperpublic static class BindingHelper{// 创建绑定的静态方法,接受源对象、路径和绑定模式,并返回一个绑定实例public static Binding Create(object source, string path, BindingMode mode){return new Binding(){Source = source,Path = new PropertyPath(path),Mode = mode};}// 创建带有转换器的绑定的静态方法,接受源对象、路径、绑定模式、值转换器和转换器参数,并返回一个绑定实例public static Binding Create(object source, string path, BindingMode mode, IValueConverter converter, object converterParameter=null){return new Binding(){Source = source,Path = new PropertyPath(path),Mode = mode,Converter = converter,ConverterParameter = converterParameter};}}
}
这段代码定义了一个静态辅助类 BindingHelper
,其中包含两个静态方法用于创建绑定。第一个方法 Create
接受源对象、路径和绑定模式,并返回一个绑定实例,用于创建简单的绑定。第二个方法 Create
接受源对象、路径、绑定模式、值转换器和转换器参数,并返回一个绑定实例,用于创建带有值转换器的绑定。这些方法提供了便捷的方式来创建不同类型的绑定,简化了代码编写过程。
2.
using System.Windows;namespace Macad.Presentation
{// 定义了一个 BindingProxy 类,继承自 Freezable 类public class BindingProxy : Freezable{// 重写 CreateInstanceCore 方法,用于创建 BindingProxy 实例protected override Freezable CreateInstanceCore(){return new BindingProxy();}// 定义了名为 Data 的依赖属性,用于存储绑定数据public object Data{get { return (object)GetValue(DataProperty); }set { SetValue(DataProperty, value); }}// 使用 DependencyProperty 注册了 Data 依赖属性,用于支持数据绑定public static readonly DependencyProperty DataProperty =DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));}
}
这段代码定义了一个名为 BindingProxy
的类,继承自 Freezable
类。它的作用是提供一个中间对象,用于在 XAML 中传递数据。它包含一个名为 Data
的依赖属性,用于存储要传递的数据。通过将数据绑定到 BindingProxy
的 Data
属性,可以在 XAML 中实现数据传递,这对于某些场景下的数据绑定非常有用。
3.
using System.Windows;namespace Macad.Presentation
{// 定义了一个抽象类 DependencyCallbackObject,继承自 DependencyObject 类public abstract class DependencyCallbackObject : DependencyObject{// 静态方法,用于处理依赖属性的静态 PropertyChanged 回调protected static void PropertyChangedStaticCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs){// 将依赖属性的变化事件委托给派生类的 PropertyChangedCallback 方法处理var instance = dependencyObject as DependencyCallbackObject;if (instance != null){instance.PropertyChangedCallback(eventArgs);}}// 抽象方法,派生类需要实现此方法来处理依赖属性的变化事件public abstract void PropertyChangedCallback(DependencyPropertyChangedEventArgs eventArgs);}
}
4.
using System;
using System.Globalization;
using System.Reflection;
using System.Windows.Data;namespace Macad.Presentation
{// 定义了一个名为 MethodBinding 的继承自 Binding 的类public class MethodBinding : Binding{// 内部私有类 MethodConverter 实现了 IValueConverter 接口class MethodConverter : IValueConverter{readonly string _MethodName;// MethodConverter 类的构造函数,接收一个 methodName 参数public MethodConverter(string methodName){this._MethodName = methodName;}// Convert 方法用于将源数据转换为绑定目标对象public object Convert(object value, Type targetType, object parameter, CultureInfo culture){// 使用反射查找源数据类型中的指定方法var mi = value.GetType().GetMethod(_MethodName, BindingFlags.Public | BindingFlags.Instance);if (mi == null){// 如果找不到指定方法,则抛出异常throw new InvalidOperationException("Could not find method with name '" + _MethodName + "' on type '" + value.GetType() + "'.");}// 根据目标类型选择合适的委托类型并返回对应的委托实例if (targetType == typeof(Func<object, bool>)){return new Func<object, bool>(x => (bool)mi.Invoke(value, new object[] { x }));}else if (targetType == typeof(Func<int, object, bool>)){return new Func<int, object, bool>((i, x) => (bool)mi.Invoke(value, new object[] { i, x }));}else if (targetType == typeof(Func<string, bool>)){return new Func<string, bool>(s => (bool)mi.Invoke(value, new object[] { s }));}else if (targetType == typeof(Func<int, string, bool>)){return new Func<int, string, bool>((i, s) => (bool)mi.Invoke(value, new object[] { i, s }));}else if (targetType == typeof(Action<object>)){return new Action<object>(x => mi.Invoke(value, new object[] { x }));}else if (targetType == typeof(Action<int, object>)){return new Action<int, object>((i, x) => mi.Invoke(value, new object[] { i, x }));}else if (targetType == typeof(Func<bool>)){return new Func<bool>(() => (bool)mi.Invoke(value, new object[] { }));}else if (targetType == typeof(Func<object>)){return new Func<object>(() => mi.Invoke(value, null));}return null;}// ConvertBack 方法,因为这是单向绑定,因此不需要实现此方法public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){throw new NotImplementedException();}}// MethodBinding 类的构造函数,接收一个 methodName 参数,并创建 MethodConverter 的实例作为 Converterpublic MethodBinding(string methodName){Converter = new MethodConverter(methodName);}}
}
这段代码定义了一个名为 MethodBinding
的类,用于创建绑定到指定方法的绑定。它包含了一个内部私有类 MethodConverter
,实现了 IValueConverter
接口,用于将方法转换为委托以供绑定使用。MethodBinding
的构造函数接收一个 methodName
参数,并创建 MethodConverter
的实例作为 Converter
,从而将指定方法绑定到目标对象。该类通过反射查找源数据类型中的指定方法,并根据目标类型选择合适的委托类型进行转换,最终返回对应的委托实例,以便在绑定中执行指定方法。
5.
namespace Macad.Presentation
{using System;using System.Windows.Controls;using System.Windows.Markup;using System.Xaml;// 标记扩展类型 RootObject,继承自 MarkupExtension[MarkupExtensionReturnType(typeof(ContentControl))]public class RootObject : MarkupExtension{// 实现 ProvideValue 方法,返回根对象public override object ProvideValue(IServiceProvider serviceProvider){// 从 IServiceProvider 获取 IRootObjectProvider 接口的实例var rootObjectProvider = (IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider));// 返回根对象,如果未找到则返回 nullreturn rootObjectProvider != null ? rootObjectProvider.RootObject : null;}}
}
这段代码定义了一个名为 RootObject
的类,它是一个标记扩展,用于在 XAML 中获取根对象。它重写了 ProvideValue
方法,该方法返回当前 XAML 上下文中的根对象。通过在 XAML 中使用 RootObject
标记扩展,可以在代码中获取到根对象,从而实现在 XAML 与代码之间的数据传递和交互。
6.commands
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Data;
using System.Windows.Input;namespace Macad.Presentation
{// 定义接口 IActionCommand,继承自 ICommand 和 INotifyPropertyChangedpublic interface IActionCommand : ICommand, INotifyPropertyChanged{string GetHeader(object parameter); // 获取命令的标题string GetTitle(object parameter); // 获取命令的标题string GetIcon(object parameter); // 获取命令的图标string GetDescription(object parameter); // 获取命令的描述string GetHelpTopic(object parameter); // 获取命令的帮助主题string Shortcut { get; set; } // 获取或设置命令的快捷键(object Object, string Path) GetBindingSource(object parameter); // 获取命令的绑定源Binding GetIsCheckedBinding(object parameter); // 获取命令的 IsChecked 绑定}//--------------------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------------------// 实现 IActionCommand 接口的 ActionCommand 类,继承自 RelayCommandpublic sealed class ActionCommand : RelayCommand, IActionCommand{public Func<string> Header { get; set; } // 获取或设置命令的标题public string GetHeader(object parameter) => Header?.Invoke(); // 获取命令的标题public Func<string> Title { get; set; } // 获取或设置命令的标题public string GetTitle(object parameter) => Title?.Invoke(); // 获取命令的标题public Func<string> Icon { get; set; } // 获取或设置命令的图标public string GetIcon(object parameter) => Icon?.Invoke(); // 获取命令的图标public Func<string> Description { get; set; } // 获取或设置命令的描述public string GetDescription(object parameter) => Description?.Invoke(); // 获取命令的描述public (object Object, string Path) BindingSource { get; set; } // 获取或设置命令的绑定源public (object Object, string Path) GetBindingSource(object parameter) => BindingSource; // 获取命令的绑定源public Binding IsCheckedBinding { get; set; } // 获取或设置命令的 IsChecked 绑定public Binding GetIsCheckedBinding(object parameter) => IsCheckedBinding; // 获取命令的 IsChecked 绑定public string HelpTopic { get; set; } // 获取或设置命令的帮助主题public string GetHelpTopic(object parameter) => HelpTopic; // 获取命令的帮助主题public string Shortcut // 获取或设置命令的快捷键{get { return _Shortcut; }set { _Shortcut = value; RaisePropertyChanged(); }}string _Shortcut;//--------------------------------------------------------------------------------------------------// 构造函数,接收执行操作的 Actionpublic ActionCommand(Action execute) : base(execute){}// 构造函数,接收执行操作的 Action 和判断是否可执行的 Func<bool>public ActionCommand(Action execute, Func<bool> canExecute) : base(execute, canExecute){}//--------------------------------------------------------------------------------------------------// PropertyChanged 事件public event PropertyChangedEventHandler PropertyChanged;// 触发 PropertyChanged 事件void RaisePropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}//--------------------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------------------// 泛型类 ActionCommand<T>,实现 IActionCommand 接口,继承自 RelayCommand<T>public class ActionCommand<T> : RelayCommand<T>, IActionCommand{public Func<T, string> Header { get; set; } // 获取或设置命令的标题public string GetHeader(object parameter) => Header?.Invoke(ConvertParameter(parameter)); // 获取命令的标题public Func<T, string> Title { get; set; } // 获取或设置命令的标题public string GetTitle(object parameter) => Title?.Invoke(ConvertParameter(parameter)); // 获取命令的标题public Func<T, string> Icon { get; set; } // 获取或设置命令的图标public string GetIcon(object parameter) => Icon?.Invoke(ConvertParameter(parameter)); // 获取命令的图标public Func<T, (object Object, string Path)> BindingSource { get; set; } // 获取或设置命令的绑定源public (object Object, string Path) GetBindingSource(object parameter) => BindingSource?.Invoke(ConvertParameter(parameter)) ?? (null, null); // 获取命令的绑定源public Func<T, string> Description { get; set; } // 获取或设置命令的描述public string GetDescription(object parameter) => Description?.Invoke(ConvertParameter(parameter)); // 获取命令的描述public Func<T, Binding> IsCheckedBinding { get; set; } // 获取或设置命令的 IsChecked 绑定public Binding GetIsCheckedBinding(object parameter) => IsCheckedBinding?.Invoke(ConvertParameter(parameter)); // 获取命令的 IsChecked 绑定public Func<T, string> HelpTopic { get; set; } // 获取或设置命令的帮助主题public string GetHelpTopic(object parameter) => HelpTopic?.Invoke(ConvertParameter(parameter)); // 获取命令的帮助主题public string Shortcut // 获取或设置命令的快捷键{get { return _Shortcut; }set { _Shortcut = value; RaisePropertyChanged(); }}string _Shortcut;//--------------------------------------------------------------------------------------------------// 构造函数,接收执行操作的 Action<T>public ActionCommand(Action<T> execute) : base(execute){}// 构造函数,接收执行操作的 Action<T> 和判断是否可执行的 Predicate<T>public ActionCommand(Action<T> execute, Predicate<T> canExecute) : base(execute, canExecute){}// 构造函数,接收执行操作的 Action<T> 和判断是否可执行的 Func<bool>public ActionCommand(Action<T> execute, Func<bool> canExecute) : base(execute, canExecute){}//--------------------------------------------------------------------------------------------------// PropertyChanged 事件public event PropertyChangedEventHandler PropertyChanged;// 触发 PropertyChanged 事件void RaisePropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
}
这段代码定义了两个类 ActionCommand
和 ActionCommand<T>
,它们实现了 IActionCommand
接口,其中:
ActionCommand
类用于表示没有参数的命令,而ActionCommand<T>
类用于表示带有一个参数的命令。- 这两个类都继承自
RelayCommand
,它们充当了命令的执行器,提供了执行操作和判断是否可执行的功能。 - 接口
IActionCommand
定义了获取命令各种属性的方法,如标题、图标、描述、快捷键等。 - 这些命令类还实现了
INotifyPropertyChanged
接口,以便在属性值改变时通知其他对象。 - 通过这些类,可以在 WPF 应用程序中方便地定义和使用命令,并且支持命令属性的动态绑定和更新。
7.
using System;
using System.Windows.Input;namespace Macad.Presentation
{/// <summary>/// 定义一个将命令转发到预定义委托处理程序的命令。/// </summary>public class RelayCommand : ICommand{readonly Action _execute; // 要执行的方法readonly Func<bool> _canExecute; // 决定命令是否可以执行的方法/// <summary>/// 初始化 <see cref="RelayCommand"/> 类的新实例。/// </summary>/// <param name="execute">命令触发时要执行的方法。</param>public RelayCommand(Action execute): this(execute, null){}/// <summary>/// 初始化 <see cref="RelayCommand"/> 类的新实例。/// </summary>/// <param name="execute">命令触发时要执行的方法。</param>/// <param name="canExecute">用于确定命令是否可以执行的方法。</param>public RelayCommand(Action execute, Func<bool> canExecute){if (execute == null)throw new ArgumentNullException(nameof(execute));_execute = execute;_canExecute = canExecute;}/// <summary>/// 定义确定命令在其当前状态下是否可以执行的方法。/// </summary>/// <param name="parameter">命令使用的数据。如果命令不需要传递数据,则此对象可以设置为 null。</param>/// <returns>/// 如果此命令可以执行,则为 true;否则为 false。/// </returns>[System.Diagnostics.DebuggerStepThrough]public bool CanExecute(object parameter){return (_canExecute is null) || _canExecute.Invoke();}[System.Diagnostics.DebuggerStepThrough]public bool CanExecute(){return (_canExecute is null) || _canExecute.Invoke();}/// <summary>/// 当影响命令是否应执行的更改发生时发生。/// </summary>public event EventHandler CanExecuteChanged{add { CommandManager.RequerySuggested += value; } // 当 CommandManager 提示重新查询时,添加事件处理程序remove { CommandManager.RequerySuggested -= value; } // 移除事件处理程序}/// <summary>/// 定义在调用命令时要调用的方法。/// </summary>/// <param name="parameter">命令使用的数据。如果命令不需要传递数据,则此对象可以设置为 null。</param>public void Execute(object parameter){_execute(); // 执行命令}public void Execute(){_execute(); // 执行命令}}
}
这段代码定义了一个名为 RelayCommand
的类,用于表示一个将命令转发到预定义委托处理程序的命令。它实现了 ICommand
接口,其中:
_execute
字段保存要执行的方法,_canExecute
字段保存确定命令是否可执行的方法。- 通过构造函数可以指定要执行的方法和确定是否可执行的方法。
CanExecute
方法确定命令在当前状态下是否可以执行,如果_canExecute
方法为 null 或者返回 true,则认为命令可以执行。CanExecuteChanged
事件在影响命令是否应执行的更改发生时触发。Execute
方法定义在调用命令时要调用的方法,它执行_execute
中保存的方法。
这个 RelayCommand
类可以用于在 WPF 应用程序中定义和使用命令,使得视图和视图模型之间的交互更加灵活和简洁。
8.
using System;
using System.Globalization;
using System.Windows.Input;namespace Macad.Presentation
{/// <summary>/// 定义一个将命令转发到预定义委托处理程序的命令。/// </summary>public class RelayCommand<T> : ICommand{readonly Action<T> _execute; // 要执行的方法readonly Predicate<T> _canExecute; // 确定命令是否可以执行的方法readonly Func<bool> _canExecute2; // 用于确定命令是否可以执行的方法(另一种方式)/// <summary>/// 初始化 <see cref="RelayCommand"/> 类的新实例。/// </summary>/// <param name="execute">命令触发时要执行的方法。</param>public RelayCommand(Action<T> execute){_execute = execute ?? throw new ArgumentNullException(nameof(execute)); // 如果 execute 为 null,则抛出异常}/// <summary>/// 初始化 <see cref="RelayCommand"/> 类的新实例。/// </summary>/// <param name="execute">命令触发时要执行的方法。</param>/// <param name="canExecute">用于确定命令是否可以执行的方法。</param>public RelayCommand(Action<T> execute, Predicate<T> canExecute){_execute = execute ?? throw new ArgumentNullException(nameof(execute)); // 如果 execute 为 null,则抛出异常_canExecute = canExecute; // 保存确定命令是否可以执行的方法}/// <summary>/// 初始化 <see cref="RelayCommand"/> 类的新实例。/// </summary>/// <param name="execute">命令触发时要执行的方法。</param>/// <param name="canExecute">用于确定命令是否可以执行的方法。</param>public RelayCommand(Action<T> execute, Func<bool> canExecute){_execute = execute ?? throw new ArgumentNullException(nameof(execute)); // 如果 execute 为 null,则抛出异常_canExecute2 = canExecute; // 保存确定命令是否可以执行的方法(另一种方式)}/// <summary>/// 定义确定命令在其当前状态下是否可以执行的方法。/// </summary>/// <param name="parameter">命令使用的数据。如果命令不需要传递数据,则此对象可以设置为 null。</param>/// <returns>/// 如果此命令可以执行,则为 true;否则为 false。/// </returns>[System.Diagnostics.DebuggerStepThrough]public bool CanExecute(object parameter){if(_canExecute != null) // 如果 _canExecute 方法不为 nullreturn _canExecute.Invoke(ConvertParameter(parameter)); // 调用 _canExecute 方法判断命令是否可以执行if (_canExecute2 != null) // 如果 _canExecute2 方法不为 nullreturn _canExecute2.Invoke(); // 调用 _canExecute2 方法判断命令是否可以执行return true; // 默认情况下认为命令可以执行}/// <summary>/// 当影响命令是否应执行的更改发生时发生。/// </summary>public event EventHandler CanExecuteChanged{add { CommandManager.RequerySuggested += value; } // 当 CommandManager 提示重新查询时,添加事件处理程序remove { CommandManager.RequerySuggested -= value; } // 移除事件处理程序}/// <summary>/// 定义在调用命令时要调用的方法。/// </summary>/// <param name="parameter">命令使用的数据。如果命令不需要传递数据,则此对象可以设置为 null。</param>public void Execute(object parameter){_execute(ConvertParameter(parameter)); // 调用 _execute 方法执行命令}/// <summary>/// 定义在调用命令时要调用的方法。/// </summary>/// <param name="parameter">命令使用的数据。如果命令不需要传递数据,则此对象可以设置为 null。</param>public void Execute(T parameter){_execute(parameter); // 调用 _execute 方法执行命令}protected T ConvertParameter(object parameter){if (parameter is string) // 如果参数是字符串类型{if (typeof(T) == typeof(string)) // 如果 T 的类型是字符串类型return (T)parameter; // 直接转换返回var s = (string)parameter;if (string.IsNullOrEmpty(s)) // 如果字符串为空或 nullreturn default(T); // 返回默认值if (typeof(T).IsEnum) // 如果 T 的类型是枚举return (T)Enum.Parse(typeof(T), s, true); // 解析枚举并返回return (T)Convert.ChangeType(s, typeof(T), CultureInfo.InvariantCulture); // 使用 ChangeType 转换并返回}if (parameter is T) // 如果参数的类型与 T 相同{return (T)parameter; // 直接返回}if (parameter == null) // 如果参数为 null{if (typeof(T) == typeof(double)) // 如果 T 的类型是双精度浮点数return (T) (object) double.NaN; // 返回 NaNif (typeof(T) == typeof(float)) // 如果 T 的类型是单精度浮点数return (T) (object) float.NaN; // 返回 NaNif (typeof(T) == typeof(int)) // 如果 T 的类型是整数return (T) (object) int.MinValue; // 返回最小整数值}return default(T); // 返回默认值}}
}
这段代码定义了一个名为 RelayCommand<T>
的泛型类,用于表示一个将命令转发到预定义委托处理程序的命令。它实现了 ICommand
接口,其中:
_execute
字段保存要执行的方法,_canExecute
字段保存确定命令是否可执行的方法,_canExecute2
字段保存确定命令是否可执行的方法(另一种方式)。- 通过构造函数可以指定要执行的方法和确定是否可执行的方法。
CanExecute
方法确定命令在当前状态下是否可以执行,如果_canExecute
或_canExecute2
方法不为 null,则分别调用它们来判断命令是否可以执行。CanExecuteChanged
事件在影响命令是否应执行的更改发生时触发。Execute
方法定义在调用命令时要调用的方法,它执行_execute
中保存的方法,并通过ConvertParameter
方法将传递的参数转换为指定类型。
9.common
namespace Macad.Presentation
{// 定义了一个名为 ValueUnits 的枚举public enum ValueUnits{None, // 表示没有单位Length, // 表示长度单位Degree, // 表示角度单位Percent, // 表示百分比单位DotsPerInch // 表示每英寸的点数单位}
}
这段代码定义了一个名为 ValueUnits
的枚举,其中包含了一些表示不同单位的成员,包括 None(没有单位)、Length(长度单位)、Degree(角度单位)、Percent(百分比单位)和 DotsPerInch(每英寸的点数单位)。这个枚举可能用于表示各种测量值的单位,例如尺寸、角度、比例等。