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]);
}
}
}
}
}
}