namespace HelloWorld.MVVM
{
public class SalesManager
{
public static readonly RoutedEvent CheckEvent = EventManager.RegisterRoutedEvent(
"CheckEvent",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(SalesManager));
public static void AddCheckHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
{
if (dependencyObject is UIElement uiElement)
{
uiElement.AddHandler(CheckEvent, handler);
}
}
public static void RemoveCheckHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
{
if (dependencyObject is UIElement uiElement)
{
uiElement.RemoveHandler(CheckEvent, handler);
}
}
}
}
/// <summary>
/// MVVM模式销售事件管理器(全局路由事件中枢)
/// [!] 当前未实现WeakEvent模式(可能引发内存泄漏)
/// </summary>
namespace HelloWorld.MVVM
{
public class SalesManager
{
/// <summary>
/// 注册全局冒泡检查事件(跨组件通信)
/// [!] 建议扩展自定义事件参数(如携带校验结果)
/// </summary>
public static readonly RoutedEvent CheckEvent = EventManager.RegisterRoutedEvent(
"CheckEvent",
routingStrategy: RoutingStrategy.Bubble, // 冒泡传递至父容器
handlerType: typeof(RoutedEventHandler),
ownerType: typeof(SalesManager));
/// <summary>
/// 动态添加事件处理器(支持任意UI元素订阅)
/// [!] 未处理非UIElement类型(静默失败)
/// </summary>
/// <param name="dependencyObject">需实现UIElement接口的对象</param>
public static void AddCheckHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
{
if (dependencyObject is UIElement uiElement)
{
uiElement.AddHandler(CheckEvent, handler); // [!] 建议添加Try/Catch块
}
}
/// <summary>
/// 动态移除事件处理器(防止冗余订阅)
/// [!] 未验证处理器是否存在(可能抛出异常)
/// </summary>
public static void RemoveCheckHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
{
if (dependencyObject is UIElement uiElement)
{
uiElement.RemoveHandler(CheckEvent, handler);
}
}
}
}
graph TD
A[注册CheckEvent路由事件] --> B{调用AddCheckHandler}
B --> C[类型检查是否为UIElement]
C -->|是| D[绑定事件处理器]
C -->|否| E[静默失败不处理]
F[调用RemoveCheckHandler] --> G{类型检查}
G -->|是| H[解绑事件处理器]
G -->|否| E
style D stroke:#4CAF50
style H stroke:#FF5722
classDef alert fill:#FFEBEE,stroke:#EF5350;
class E alert
架构增强建议
// 增强版方法(带异常处理)
public static void SafeAddHandler(DependencyObject obj, RoutedEventHandler handler)
{
try
{
if (obj is UIElement ele && handler != null)
{
WeakEventManager<UIElement, RoutedEventArgs>
.AddHandler(ele, CheckEvent, handler); // 弱事件绑定
}
}
catch (ArgumentException ex)
{
Debug.WriteLine($"处理器绑定失败: {ex.Message}");
}
}
<controls:Widget Value="{Binding ElementName=slider,Path=Value}"
Target="1000000"
Completed="Widget_Completed"
helper:SalesManager.Check="Widget_Check"
Title="第四季度北美市场总销售额统计"
Canvas.Left="116" Canvas.Top="17"
Height="103" Width="269"/>
xmlns:helper="clr-namespace:HelloWorld.MVVM"
private void Widget_Completed(object sender, RoutedEventArgs e)
{
Widget widget = sender as Widget;
listBox.Items.Insert(0, $"完成目标销售额:{widget.Value}");
widget.RaiseEvent(new RoutedEventArgs(SalesManager.CheckEvent));
}
private void Widget_Check(object sender, RoutedEventArgs e)
{
Widget widget = sender as Widget;
if (((int)widget.Value) % 500000 < 5000)
{
listBox.Items.Insert(0, $"当前业绩:{widget.Value},每累计50万发奖金啦:{widget.Value*0.5}");
}
}
/// <summary>
/// 销售目标完成事件处理器(冒泡事件响应)
/// [!] 未处理空引用风险(sender可能非Widget类型)
/// </summary>
private void Widget_Completed(object sender, RoutedEventArgs e)
{
// 动态类型转换(需验证sender有效性)
Widget widget = sender as Widget;
// 在列表顶部插入业务记录(UI线程操作风险)
listBox.Items.Insert(0, $"完成目标销售额:{widget.Value}");
// 触发全局检查事件(形成事件链式反应)
widget.RaiseEvent(new RoutedEventArgs(SalesManager.CheckEvent));
}
/// <summary>
/// 销售业绩检查事件处理器(奖金发放逻辑)
/// [!] 浮点数精度问题(建议使用decimal类型)
/// </summary>
private void Widget_Check(object sender, RoutedEventArgs e)
{
Widget widget = sender as Widget;
// 非精确数值检测逻辑(500000为50万单位)
if (((int)widget.Value) % 500000 < 5000)
{
// 奖金计算(未考虑税务计算场景)
listBox.Items.Insert(0,
$"当前业绩:{widget.Value},每累计50万发奖金啦:{widget.Value*0.5}");
}
}
graph TD
subgraph Widget_Completed方法
A[收到Completed事件] --> B{类型转换验证}
B -->|成功| C[插入销售完成记录]
C --> D[触发CheckEvent事件]
B -->|失败| E[静默忽略]
end
subgraph Widget_Check方法
F[收到CheckEvent事件] --> G{数值检测条件}
G -->|余数<5000| H[计算奖金数额]
H --> I[插入奖金发放记录]
G -->|余数≥5000| J[不做处理]
end
style C stroke:#4CAF50
style I stroke:#2196F3
style D stroke:#FF9800
classDef error fill:#FFEBEE,stroke:#EF5350;
class E,J error
<Canvas Width="200" Height="200">
<Rectangle
Canvas.Left="100" Canvas.Top="100"
Width="50" Height="50"
Fill="RoyalBlue" Opacity="1.0">
<Rectangle.RenderTransform>
<RotateTransform Angle="45" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
元素类型 | 属性/特性 | 技术说明 |
---|---|---|
Canvas | Width="200" Height="200" | 创建200x200像素的绘画区域 |
Rectangle | Canvas.Left="100" Canvas.Top="100" | 基于Canvas的绝对定位系统,距左/顶各100像素 |
Width="50" Height="50" | 构建50x50像素的正方形 | |
Fill="RoyalBlue" | 使用CSS4标准颜色(RGB值65/105/225) | |
Opacity="1.0" | 完全不透明(支持0.0-1.0的浮点精度控制) | |
RotateTransform | Angle="45" | 坐标系变换(以元素中心为原点顺时针旋转45度) |
graph TD
A[Canvas] --> B[布局属性]
A --> C[子元素体系]
B --> B1(Width=200)
B --> B2(Height=200)
C --> C1[Rectangle]
C1 --> C1a[布局定位]
C1a --> C1a1(Canvas.Left=100)
C1a --> C1a2(Canvas.Top=100)
C1 --> C1b[几何属性]
C1b --> C1b1(Width=50)
C1b --> C1b2(Height=50)
C1 --> C1c[视觉样式]
C1c --> C1c1(Fill=RoyalBlue)
C1c --> C1c2(Opacity=1.0)
C1 --> C1d[图形变换]
C1d --> C1d1(RenderTransform)
C1d1 --> C1d1a(RotateTransform)
C1d1a --> C1d1a1(Angle=45°)
<Canvas Width="200" Height="200">
<Rectangle
Canvas.Left="100" Canvas.Top="100"
Width="50" Height="50"
Fill="RoyalBlue" Opacity="1.0">
<Rectangle.RenderTransform>
<RotateTransform Angle="45" CenterX="25" CenterY="25" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
graph TD
A[Canvas] --> B[容器属性]
A --> C[渲染引擎]
B --> B1("量子画布尺寸: 200×200px")
C --> C1("光线追踪渲染管线")
A --> D[图形元素]
D --> D1{Rectangle}
D1 --> E1[定位系统]
E1 --> E1a("Canvas.Left=100")
E1 --> E1b("Canvas.Top=100")
D1 --> E2[几何参数]
E2 --> E2a("Width=50")
E2 --> E2b("Height=50")
D1 --> E3[视觉呈现]
E3 --> E3a("Fill=RoyalBlue")
E3 --> E3b("Opacity=1.0")
D1 --> E4[空间变换]
E4 --> E4a("RotateTransform")
E4a --> E4a1("Angle=45°")
E4a --> E4a2("CenterX=25")
E4a --> E4a3("CenterY=25")
Angle属性表示获取或设置顺时针旋转的角度(以度为单位)。默认值是0度。CenterX 和CenterY 表示获取或设置旋转中心点的 x y坐标,Value属性表示当前转换的矩阵。通常我们只需要设置Angle、CenterX 和CenterY即可
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0"
Width="100"
Height="25"
Content="RotateTransform"
HorizontalAlignment="Center