自定义布局控件
1、添加自定义控件
添加新项->WPF->自定义控件(WPF)
在Themes文件夹下Generic.xaml
会自动生成自定义控件的模板样式
2、实现自定义布局控件功能
1、继承自Panel
public abstract class Panel : FrameworkElement, IAddChild
Panel继承自FrameworkElement,实现IAddChild,可以在自定义的布局控件中添加子元素(控件)
如果继承Control,无法在控件内部添加子元素
修改为继承Panel,需要删除Generic.xaml
中自动生成的模板样式
2、重写MeasureOverride
和ArrangeOverride
方法
官方定义:
/// <summary>/// 在派生类中重写时,测量子元素在布局中所需的大小,并确定由 FrameworkElement 派生的类的大小。/// </summary>/// <param name="availableSize">此元素可提供给子元素的可用大小。 可指定无穷大作为一个值,该值指示元素将调整到适应内容的大小。</param>/// <returns>此元素基于其对子元素大小的计算确定它在布局期间所需要的大小</returns>protected virtual System.Windows.Size MeasureOverride (System.Windows.Size availableSize);/// <summary>/// 在派生类中重写时,为 FrameworkElement 派生类定位子元素并确定大小。/// </summary>/// <param name="finalSize">父级中应使用此元素排列自身及其子元素的最终区域。</param>/// <returns>使用的实际大小。</returns>protected virtual System.Windows.Size ArrangeOverride (System.Windows.Size finalSize);
MeasureOverride
测量子元素在布局中所需的大小
ArrangeOverride
定位子元素并确定大小。实现模式应调用 Arrange(Rect) 每个可见子元素,并将每个子元素的最终所需大小作为 finalRect 参数传递uIElement?.Arrange(new Rect(finalSize));
想要自定义布局处理的排列过程的控制作者应重写此方法
不重写这两个方法,会导致布局控件内的控件无法正确显示
参考Grid源码:
Size MeasureOverride(Size constraint)
Size ArrangeOverride(Size arrangeSize)
实现一个简易的Panel
public class SimplePanel : Panel{static SimplePanel(){DefaultStyleKeyProperty.OverrideMetadata(typeof(SimplePanel), new FrameworkPropertyMetadata(typeof(SimplePanel)));}protected override Size MeasureOverride(Size availableSize){Size result = default(Size);UIElementCollection internalChildren = base.InternalChildren;foreach (UIElement uIElement in internalChildren){if (uIElement != null){uIElement.Measure(availableSize);result.Width = Math.Max(result.Width, uIElement.DesiredSize.Width);result.Height = Math.Max(result.Height, uIElement.DesiredSize.Height);}}return result;}protected override Size ArrangeOverride(Size finalSize){UIElementCollection internalChildren = base.InternalChildren;foreach (UIElement uIElement in internalChildren){uIElement?.Arrange(new Rect(finalSize));}return finalSize;}}
异常情况:
如果添加自定义控件出现报错界面
关闭同项目下已经打开的Themes文件夹中的Generic.xaml
文件,重新添加就行,或者手动添加模板样式。
Generic.xaml
打开的情况无法自动添加模板样式。