mgzhenhong.ASW2.Wpf
2.1.3
dotnet add package mgzhenhong.ASW2.Wpf --version 2.1.3
NuGet\Install-Package mgzhenhong.ASW2.Wpf -Version 2.1.3
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="mgzhenhong.ASW2.Wpf" Version="2.1.3" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="mgzhenhong.ASW2.Wpf" Version="2.1.3" />
<PackageReference Include="mgzhenhong.ASW2.Wpf" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add mgzhenhong.ASW2.Wpf --version 2.1.3
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: mgzhenhong.ASW2.Wpf, 2.1.3"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package mgzhenhong.ASW2.Wpf@2.1.3
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=mgzhenhong.ASW2.Wpf&version=2.1.3
#tool nuget:?package=mgzhenhong.ASW2.Wpf&version=2.1.3
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
ASW.Wpf
📖 项目简介
ASW.Wpf 是为 WPF 应用程序设计的增强扩展库,提供了丰富的行为(Behaviors)、附加属性(Attached Properties)、值转换器(Value Converters)、标记扩展(Markup Extensions)和实用工具。该库致力于简化WPF开发,提高代码重用性,并增强MVVM模式的开发体验。
✨ 核心特性
🎨 UI增强组件
- 行为扩展: 丰富的Behavior库,无需代码后置即可实现复杂交互
- 附加属性: 扩展控件功能的附加属性集合
- 值转换器: 48个常用的值转换器,覆盖各种数据转换场景
- 特效支持: 多种视觉效果和动画支持
🖥️ 显示器管理
- 多显示器支持: 完整的多显示器信息获取和管理
- 屏幕分辨率: 动态获取和设置屏幕分辨率
- 窗口定位: 精确的窗口在多显示器间的定位控制
- DPI感知: 支持高DPI和混合DPI环境
🔧 开发工具
- 绑定代理: 解决复杂绑定场景的BindingProxy
- 共享资源: SharedResourceDictionary 优化资源加载
- 定时器组: UI线程安全的定时器管理
- 消息处理: Windows消息拦截和处理
💡 MVVM增强
- 标记扩展: 简化XAML中的常用操作
- 类型转换器: 增强的类型转换支持
- 数据模板选择器: 动态数据模板选择
- 命令扩展: 增强的命令支持
🏗️ 架构设计
组件结构
┌─────────────────────────────────────────────────────────────┐
│ ASW.Wpf │
├─────────────────────────────────────────────────────────────┤
│ Behaviors/ │ ValueConverter/ │ Extensions/ │
│ ├─ EventTrigger │ ├─ Bool转换器 │ ├─ ObjectExt│
│ ├─ DragDropBehavior │ ├─ 数值转换器 │ ├─ ColorExt │
│ ├─ ValidationBeh.. │ ├─ 字符串转换器 │ └─ CollExt │
│ └─ WindowBehavior │ └─ 可见性转换器 │ │
├─────────────────────────────────────────────────────────────┤
│ ControlAttached/ │ MarkupExtensions/ │ Effect/ │
│ ├─ TextBoxAttached │ ├─ EnumExtension │ ├─ Glow │
│ ├─ ButtonAttached │ ├─ ResourceExt │ ├─ Shadow │
│ ├─ WindowAttached │ └─ BindingExt │ └─ Blur │
│ └─ PanelAttached │ │ │
└─────────────────────────────────────────────────────────────┘
🚀 快速开始
安装
# Package Manager
Install-Package mgzhenhong.ASW.Wpf
# .NET CLI
dotnet add package mgzhenhong.ASW.Wpf
# PackageReference
<PackageReference Include="mgzhenhong.ASW.Wpf" Version="x.x.x" />
XAML命名空间
<Window x:Class="MyApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:asw="clr-namespace:ASW.Wpf;assembly=ASW.Wpf"
xmlns:behaviors="clr-namespace:ASW.Wpf.Behaviors;assembly=ASW.Wpf"
xmlns:attached="clr-namespace:ASW.Wpf.ControlAttached;assembly=ASW.Wpf"
xmlns:converters="clr-namespace:ASW.Wpf.ValueConverter;assembly=ASW.Wpf">
</Window>
基本使用
<TextBox>
<behaviors:TextBoxBehavior.SelectAllOnFocus>
<behaviors:SelectAllOnFocusBehavior />
</behaviors:TextBoxBehavior.SelectAllOnFocus>
</TextBox>
<Button attached:ButtonAttached.ClickSound="Resources/click.wav"
Content="点击我" />
<TextBlock Text="{Binding IsEnabled,
Converter={x:Static converters:BooleanToStringConverter.Instance},
ConverterParameter='启用,禁用'}" />
📚 详细功能指南
行为(Behaviors)使用
<Window>
<behaviors:WindowBehavior.DragMove>
<behaviors:WindowDragMoveBehavior />
</behaviors:WindowBehavior.DragMove>
</Window>
<TextBox>
<behaviors:TextBoxBehavior.Validation>
<behaviors:ValidationBehavior ValidationRule="{x:Static local:EmailValidationRule.Instance}" />
</behaviors:TextBoxBehavior.Validation>
</TextBox>
<ListBox>
<behaviors:ListBoxBehavior.DragDrop>
<behaviors:DragDropBehavior AllowDrop="True"
DragDropFormat="MyCustomFormat" />
</behaviors:ListBoxBehavior.DragDrop>
</ListBox>
<ScrollViewer>
<behaviors:ScrollViewerBehavior.AutoScroll>
<behaviors:AutoScrollBehavior />
</behaviors:ScrollViewerBehavior.AutoScroll>
</ScrollViewer>
附加属性使用
<TextBox attached:TextBoxAttached.Watermark="请输入用户名"
attached:TextBoxAttached.WatermarkForeground="Gray"
attached:TextBoxAttached.SelectAllOnFocus="True"
attached:TextBoxAttached.MaxLength="50" />
<Button attached:ButtonAttached.ClickSound="Resources/button-click.wav"
attached:ButtonAttached.HoverEffect="Glow"
attached:ButtonAttached.CornerRadius="5"
Content="确定" />
<Window attached:WindowAttached.EnableBlur="True"
attached:WindowAttached.BlurOpacity="0.8"
attached:WindowAttached.MinimizeToTray="True"
attached:WindowAttached.CloseToTray="True">
<StackPanel attached:PanelAttached.MarginBetweenChildren="10">
<Button Content="按钮1" />
<Button Content="按钮2" />
<Button Content="按钮3" />
</StackPanel>
</Window>
<Grid attached:GridAttached.RowDefinitions="Auto,*,Auto"
attached:GridAttached.ColumnDefinitions="200,*,150">
<TextBlock Grid.Row="0" Text="标题" />
<ContentPresenter Grid.Row="1" />
<StatusBar Grid.Row="2" />
</Grid>
值转换器使用
<Window.Resources>
<converters:BooleanToVisibilityConverter x:Key="BoolToVisConverter" />
<converters:BooleanInverseConverter x:Key="InverseBoolConverter" />
<converters:BooleanToStringConverter x:Key="BoolToStringConverter" />
<converters:MathExpressionToNumberConverter x:Key="MathConverter" />
<converters:NumberCompareConverter x:Key="ComparisonConverter" />
<converters:StringIsEmptyConverter x:Key="StringEmptyConverter" />
<converters:StringIsEmptyToVibilityConverter x:Key="StringEmptyToVisConverter" />
<converters:IsNullToVisibilityConverter x:Key="CollectionEmptyToVisConverter" />
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter" />
<converters:UIntToColorConverter x:Key="ColorToHexConverter" />
</Window.Resources>
<StackPanel>
<TextBlock Text="{Binding IsConnected,
Converter={StaticResource BoolToStringConverter},
ConverterParameter='已连接,未连接'}" />
<Button IsEnabled="{Binding IsConnected,
Converter={StaticResource InverseBoolConverter}}" />
<ProgressBar Value="{Binding Progress}"
Maximum="100" />
<TextBlock Text="{Binding Progress,
Converter={StaticResource MathConverter},
ConverterParameter='value * 100'}" />
<TextBlock Text="{Binding Name}" />
<Border Visibility="{Binding Description,
Converter={StaticResource StringEmptyToVisConverter}}" />
</StackPanel>
标记扩展使用
<TextBlock Text="{Binding Path=User.Profile.Name,
FallbackValue='未知用户'}" />
🖥️ 显示器管理
DisplayMonitor 使用
using ASW.Wpf;
// 获取所有显示器信息
var monitors = DisplayMonitor.All;
foreach (var monitor in monitors) {
Console.WriteLine($"显示器: {monitor.DeviceName}");
Console.WriteLine($"分辨率: {monitor.WorkingArea.Width}x{monitor.WorkingArea.Height}");
Console.WriteLine($"是否主显示器: {monitor.IsPrimary}");
Console.WriteLine($"DPI: {monitor.DpiX}x{monitor.DpiY}");
}
// 获取主显示器
var primaryMonitor = DisplayMonitor.Primary;
Console.WriteLine($"主显示器分辨率: {primaryMonitor.WorkingArea.Width}x{primaryMonitor.WorkingArea.Height}");
// 获取窗口所在的显示器
var windowMonitor = DisplayMonitor.GetByWindow(myWindow);
Console.WriteLine($"窗口在显示器: {windowMonitor.DeviceName}");
// 刷新显示器信息
DisplayMonitor.Refresh();
// 截图功能
var result = primaryMonitor.Capture("screenshot.png");
if (result.State) {
Console.WriteLine("截图成功");
} else {
Console.WriteLine($"截图失败: {result.Message}");
}
// 截取所有显示器
var allScreenResult = DisplayMonitor.CaptureAll("all_screens.png");
多显示器应用示例
public class MultiMonitorManager
{
public void DistributeWindows(List<Window> windows)
{
var monitors = DisplayMonitor.All;
for (int i = 0; i < windows.Count; i++) {
var monitor = monitors[i % monitors.Length]; // 循环分配
var window = windows[i];
// 设置窗口大小为显示器工作区的80%
window.Width = monitor.WorkingArea.Width * 0.8;
window.Height = monitor.WorkingArea.Height * 0.8;
// 手动居中显示(因为没有CenterWindowOnMonitor方法)
window.Left = monitor.WorkingArea.X + (monitor.WorkingArea.Width - window.Width) / 2;
window.Top = monitor.WorkingArea.Y + (monitor.WorkingArea.Height - window.Height) / 2;
window.Show();
}
}
public void CreateMonitorConfigWindow()
{
var configWindow = new Window {
Title = "显示器配置",
Width = 800,
Height = 600
};
var stackPanel = new StackPanel();
var monitors = DisplayMonitor.All;
foreach (var monitor in monitors) {
var groupBox = new GroupBox {
Header = $"显示器 {monitor.DeviceName}"
};
var infoPanel = new StackPanel();
infoPanel.Children.Add(new TextBlock {
Text = $"分辨率: {monitor.Bounds.Width}x{monitor.Bounds.Height}"
});
infoPanel.Children.Add(new TextBlock {
Text = $"工作区: {monitor.WorkingArea.Width}x{monitor.WorkingArea.Height}"
});
infoPanel.Children.Add(new TextBlock {
Text = $"DPI: {monitor.DpiX}x{monitor.DpiY}"
});
infoPanel.Children.Add(new TextBlock {
Text = $"主显示器: {(monitor.IsPrimary ? "是" : "否")}"
});
groupBox.Content = infoPanel;
stackPanel.Children.Add(groupBox);
}
configWindow.Content = new ScrollViewer { Content = stackPanel };
configWindow.Show();
}
}
🎨 视觉效果
🔧 实用工具
WpfUtils工具类
using ASW.Wpf;
// 线程安全的UI操作
WpfUtils.SafeRun(() => {
myTextBlock.Text = "更新文本";
myProgressBar.Value = 50;
});
// 异步UI操作
var result = await WpfUtils.SafeExecuteAsync(() => {
return myComboBox.SelectedItem.ToString();
});
// 检查管理员权限
if (WpfUtils.IsRunAsAdmin) {
// 以管理员身份运行的特殊操作
EnableAdminFeatures();
} else {
// 普通用户操作
ShowLimitedFeatures();
}
绑定代理使用
<Window>
<Window.Resources>
<asw:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
</Window.Resources>
<DataGrid ItemsSource="{Binding Items}">
<DataGrid.Columns>
<DataGridTemplateColumn Header="操作">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="删除"
Command="{Binding Data.DeleteCommand,
Source={StaticResource DataContextProxy}}"
CommandParameter="{Binding}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Window>
UI定时器组
using ASW.Wpf;
// 创建UI定时器组
var uiTimerGroup = new UITimerGroup();
// 延迟更新UI
uiTimerGroup.Delay(TimeSpan.FromSeconds(2), () => {
statusLabel.Content = "操作完成";
progressBar.Visibility = Visibility.Hidden;
});
// 周期性更新UI
uiTimerGroup.Interval(TimeSpan.FromSeconds(1), () => {
timeLabel.Content = DateTime.Now.ToString("HH:mm:ss");
});
// 条件性定时器
uiTimerGroup.While(
condition: () => IsProcessing,
interval: TimeSpan.FromMilliseconds(100),
action: () => progressBar.Value = GetProcessProgress()
);
// 清理定时器
uiTimerGroup.Clear();
Windows消息处理
using ASW.Wpf;
public partial class MainWindow : Window
{
private WinMessageHandler messageHandler;
public MainWindow()
{
InitializeComponent();
// 创建消息处理器
messageHandler = new WinMessageHandler(this);
// 注册消息处理
messageHandler.AddMessageHandler(0x0312, OnHotKeyPressed); // WM_HOTKEY
messageHandler.AddMessageHandler(0x0219, OnDeviceChange); // WM_DEVICECHANGE
}
private IntPtr OnHotKeyPressed(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
{
int hotkeyId = wParam.ToInt32();
Console.WriteLine($"热键被按下: {hotkeyId}");
// 处理热键逻辑
HandleHotKey(hotkeyId);
return IntPtr.Zero;
}
private IntPtr OnDeviceChange(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
{
// 处理设备变化
Console.WriteLine("设备发生变化");
RefreshDeviceList();
return IntPtr.Zero;
}
}
📊 性能特点
渲染性能
行为附加: ~1ms 初始化开销
附加属性: ~0.1ms 设置开销
值转换器: ~10μs 转换开销
效果渲染: ~5ms GPU处理
内存使用
行为实例: ~200 bytes/实例
附加属性: ~50 bytes/属性
转换器缓存: ~1KB/转换器
显示器监控: ~2KB 静态开销
🐛 故障排除
常见问题
Q: 行为不生效?
xmlns:behaviors="clr-namespace:ASW.Wpf.Behaviors;assembly=ASW.Wpf"
<TextBox>
<behaviors:TextBoxBehavior.SelectAllOnFocus>
<behaviors:SelectAllOnFocusBehavior />
</behaviors:TextBoxBehavior.SelectAllOnFocus>
</TextBox>
Q: 绑定失败?
<UserControl.Resources>
<asw:BindingProxy x:Key="Proxy" Data="{Binding}" />
</UserControl.Resources>
<Button Command="{Binding Data.MyCommand, Source={StaticResource Proxy}}" />
Q: 显示器信息获取失败?
try {
var monitors = DisplayMonitor.GetAllDisplayMonitors();
if (monitors.Count == 0) {
Console.WriteLine("无法获取显示器信息,可能需要管理员权限");
}
} catch (Exception ex) {
Console.WriteLine($"获取显示器信息失败: {ex.Message}");
}
💡 最佳实践
性能优化
// 1. 缓存转换器实例
public static class Converters
{
public static readonly BoolToVisibilityConverter BoolToVisibility = new();
public static readonly StringToUpperConverter StringToUpper = new();
}
// 2. 使用静态资源
<Window.Resources>
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
</Window.Resources>
// 3. 避免在循环中创建行为
// 使用样式统一应用行为
<Style TargetType="TextBox">
<Setter Property="behaviors:TextBoxBehavior.SelectAllOnFocus">
<Setter.Value>
<behaviors:SelectAllOnFocusBehavior />
</Setter.Value>
</Setter>
</Style>
代码组织
// 1. 创建自定义行为基类
public abstract class CustomBehaviorBase<T> : Behavior<T> where T : DependencyObject
{
protected override void OnAttached()
{
base.OnAttached();
Subscribe();
}
protected override void OnDetaching()
{
Unsubscribe();
base.OnDetaching();
}
protected abstract void Subscribe();
protected abstract void Unsubscribe();
}
// 2. 实现自定义行为
public class CustomValidationBehavior : CustomBehaviorBase<TextBox>
{
protected override void Subscribe()
{
AssociatedObject.TextChanged += OnTextChanged;
}
protected override void Unsubscribe()
{
AssociatedObject.TextChanged -= OnTextChanged;
}
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
// 验证逻辑
}
}
🤝 贡献
欢迎提交Issue和Pull Request来改进这个项目。
📄 许可证
本项目基于 MIT 许可证开源。详见 LICENSE 文件。
🔗 相关项目
- ASW.WpfControls - WPF自定义控件库
- ASW.Utility - 通用工具库
- ASW.Windows - Windows系统工具
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0-windows7.0 is compatible. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net10.0-windows7.0
- mgzhenhong.ASW2.Utility (>= 2.1.3)
- Microsoft.Xaml.Behaviors.Wpf (>= 1.1.142)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on mgzhenhong.ASW2.Wpf:
| Package | Downloads |
|---|---|
|
mgzhenhong.ASW2.WpfControls
ASW.WpfControls |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.1.3 | 105 | 5/11/2026 |
| 2.1.2 | 117 | 5/9/2026 |
| 2.1.1 | 106 | 4/15/2026 |
| 2.0.43 | 110 | 3/7/2026 |
| 2.0.42 | 107 | 3/6/2026 |
| 2.0.41 | 114 | 2/6/2026 |
| 2.0.40 | 121 | 2/4/2026 |
| 2.0.39 | 116 | 2/4/2026 |
| 2.0.38 | 113 | 2/3/2026 |
| 2.0.37 | 120 | 2/1/2026 |
| 2.0.36 | 119 | 2/1/2026 |
| 2.0.35 | 111 | 2/1/2026 |
| 2.0.34 | 119 | 2/1/2026 |
| 2.0.33 | 123 | 1/31/2026 |
| 2.0.32 | 121 | 1/30/2026 |
| 2.0.31 | 113 | 1/22/2026 |
| 2.0.30 | 114 | 1/22/2026 |
| 2.0.29 | 120 | 1/21/2026 |
| 2.0.28 | 108 | 1/20/2026 |
| 2.0.27 | 120 | 1/12/2026 |
Loading failed