macad.bingding,commands,common

发布于:2024-04-14 ⋅ 阅读:(184) ⋅ 点赞:(0)

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 的依赖属性,用于存储要传递的数据。通过将数据绑定到 BindingProxyData 属性,可以在 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));
        }
    }
}

这段代码定义了两个类 ActionCommandActionCommand<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(每英寸的点数单位)。这个枚举可能用于表示各种测量值的单位,例如尺寸、角度、比例等。


网站公告

今日签到

点亮在社区的每一天
去签到