WPF使用装饰器实现SAP焦点样式

16 篇文章 5 订阅
2 篇文章 0 订阅

SAP当焦点进入控件时,会在控件的四个角上出现红框,见下图示例。 

要实现这样的功能是有点难度的,幸好WPF提供了装饰器这个玩意,实现起来就容易了。
先说一下思路:
1.重写控件的装饰器;
2.指定窗体上的所有控件使用自定义的装饰器;
3.当控件获得焦点时显示装饰器。

现在,第一步重写装饰器Adorner,主要是绘制四个角边框的方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Windows;
using System.Windows.Media;

namespace ControlAdorner {
	public class SimpleAdorner:Adorner {
		public SimpleAdorner(UIElement adornedElement):base(adornedElement) {}

		protected override void OnRender(System.Windows.Media.DrawingContext drawingContext) {
			Rect adornedElementRect = new Rect(this.AdornedElement.RenderSize);

			Pen renderPen = new Pen(new SolidColorBrush(Colors.Red), 1.0);

			// Draw a circle at each corner.
			drawingContext.DrawLine(renderPen, new Point(adornedElementRect.TopLeft.X - 3, adornedElementRect.TopLeft.Y - 3), new Point(adornedElementRect.TopLeft.X + 5, adornedElementRect.TopLeft.Y - 3));
			drawingContext.DrawLine(renderPen, new Point(adornedElementRect.TopLeft.X - 3, adornedElementRect.TopLeft.Y - 3), new Point(adornedElementRect.TopLeft.X - 3, adornedElementRect.TopLeft.Y + 5));

			drawingContext.DrawLine(renderPen, new Point(adornedElementRect.TopRight.X + 3, adornedElementRect.TopRight.Y - 3), new Point(adornedElementRect.TopRight.X - 5, adornedElementRect.TopRight.Y - 3));
			drawingContext.DrawLine(renderPen, new Point(adornedElementRect.TopRight.X + 3, adornedElementRect.TopRight.Y - 3), new Point(adornedElementRect.TopRight.X + 3, adornedElementRect.TopRight.Y + 5));

			drawingContext.DrawLine(renderPen, new Point(adornedElementRect.BottomLeft.X - 3, adornedElementRect.BottomLeft.Y + 3), new Point(adornedElementRect.BottomLeft.X + 5, adornedElementRect.BottomLeft.Y + 3));
			drawingContext.DrawLine(renderPen, new Point(adornedElementRect.BottomLeft.X - 3, adornedElementRect.BottomLeft.Y + 3), new Point(adornedElementRect.BottomLeft.X - 3, adornedElementRect.BottomLeft.Y - 5));

			drawingContext.DrawLine(renderPen, new Point(adornedElementRect.BottomRight.X + 3, adornedElementRect.BottomRight.Y + 3), new Point(adornedElementRect.BottomRight.X - 5, adornedElementRect.BottomRight.Y + 3));
			drawingContext.DrawLine(renderPen, new Point(adornedElementRect.BottomRight.X + 3, adornedElementRect.BottomRight.Y + 3), new Point(adornedElementRect.BottomRight.X + 3, adornedElementRect.BottomRight.Y - 5));
		}
	}
}


 第二步,先创建一个窗体,然后拖曳一些控件,如上图;然后遍历控件,为控件指定自定义装饰器

public partial class MainWindow : Window {

	//AdornerLayer layer1;

	public MainWindow() {
		InitializeComponent();
	}

	private void Window_Loaded(object sender, RoutedEventArgs e) {
		AdornerLayer layer1 = AdornerLayer.GetAdornerLayer(this.Content as Grid);

		List<Visual> list = new List<Visual>();
		AppHelper.EnumVisual(list, this);
		AppHelper.AddAdorner(list, layer1);
	}
}


辅助类

public class AppHelper {
	/// <summary>
	/// 枚举可视控件
	/// </summary>
	/// <param name="list"></param>
	/// <param name="myVisual"></param>
	/// <returns></returns>
	public static List<Visual> EnumVisual(List<Visual> list, Visual myVisual) {
		for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++) {
			Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);
			if (childVisual != null) {
				if (childVisual is TextBox ||
					childVisual is ComboBox ||
					childVisual is CheckBox ||
					childVisual is ListBox ||
					childVisual is Button ||
					childVisual is RadioButton) {
					list.Add(childVisual);
				} else {
					EnumVisual(list, childVisual);
				}
			}
		}
		return list;
	}
	/// <summary>
	/// 添加装饰层和装饰器
	/// </summary>
	/// <param name="list"></param>
	/// <param name="layer"></param>
	public static void AddAdorner(List<Visual> list, AdornerLayer layer) {
		foreach (Visual v in list) {
			UIElement ele = v as UIElement;
			ele.GotFocus += (s, e2) => {
				if (ele.IsFocused) {
					ClearAdorners(list, ele, layer);
					layer.Add(new SimpleAdorner(ele));
				}
			};
		}
	}

	/// <summary>
	/// 清除装饰器
	/// </summary>
	/// <param name="list"></param>
	/// <param name="element"></param>
	/// <param name="layer"></param>
	public static void ClearAdorners(List<Visual> list, UIElement element, AdornerLayer layer) {
		foreach (Visual v in list) {
			UIElement ele = v as UIElement;
			if (ele != element) {
				Adorner[] ads = layer.GetAdorners(ele);
				if (ads != null) {
					for (int i = ads.Length - 1; i >= 0; i--) {
						layer.Remove(ads[i]);
					}
				}
			}
		}
	}
}


 项目源代码 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值