1.
using System.Windows;
using System.Windows.Data;
namespace Macad.Presentation
{
// 定义了一个辅助类 BindingHelper
public 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 的实例作为 Converter
public 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));
// 返回根对象,如果未找到则返回 null
return 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 和 INotifyPropertyChanged
public 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 类,继承自 RelayCommand
public 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;
//--------------------------------------------------------------------------------------------------
// 构造函数,接收执行操作的 Action
public 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 方法不为 null
return _canExecute.Invoke(ConvertParameter(parameter)); // 调用 _canExecute 方法判断命令是否可以执行
if (_canExecute2 != null) // 如果 _canExecute2 方法不为 null
return _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)) // 如果字符串为空或 null
return 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; // 返回 NaN
if (typeof(T) == typeof(float)) // 如果 T 的类型是单精度浮点数
return (T) (object) float.NaN; // 返回 NaN
if (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(每英寸的点数单位)。这个枚举可能用于表示各种测量值的单位,例如尺寸、角度、比例等。