C# 如何装饰WPF面板?
我想编写一个自定义C# 如何装饰WPF面板?,c#,.net,wpf,custom-controls,C#,.net,Wpf,Custom Controls,我想编写一个自定义面板,它将利用Decorator paten。这意味着它将有一些其他的面板作为属性。当某个元素添加到自定义面板时,我想将其也添加到装饰面板(存储在属性中),当某个元素被删除时,我也想将其从装饰面板中删除。我该怎么做 当发生对InternalChildrens的更改时,是否有一些方法要被重写或触发一些事件 多谢各位 编辑:基本上我想做一些像我想把任何面板动画之一。因此,我想用我的装饰器装饰任何面板,使其成为动画。我不完全理解此问题的上下文,但您可以覆盖OnVisualChildr
面板
,它将利用Decorator paten。这意味着它将有一些其他的面板
作为属性。当某个元素添加到自定义面板时,我想将其也添加到装饰面板(存储在属性中),当某个元素被删除时,我也想将其从装饰面板中删除。我该怎么做
当发生对InternalChildrens的更改时,是否有一些方法要被重写或触发一些事件
多谢各位
编辑:基本上我想做一些像我想把任何面板动画之一。因此,我想用我的装饰器装饰任何面板,使其成为动画。我不完全理解此问题的上下文,但您可以覆盖OnVisualChildrenChanged
不幸的是,你不能这么做 您将立即得到一个异常,表示控件只能有一个逻辑父级 虽然你能做的是双重授权。您的配电盘将测量/排列委托给另一个配电盘,作为回报,它将向其提供“重影”,这些重影将作为它的子对象,并将自己的测量/排列委托给您配电盘的子对象 代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
public class DelegatePanel : Panel
{
private sealed class DelegateChild : FrameworkElement
{
readonly Func<Size, Size> measure;
readonly Func<Size, Size> arrange;
public DelegateChild(Func<Size,Size> measure, Func<Size,Size> arrange)
{
this.measure = measure;
this.arrange = arrange;
}
protected override Size MeasureOverride(Size availableSize)
{
return measure(availableSize);
}
protected override Size ArrangeOverride(Size finalSize)
{
return arrange(finalSize);
}
}
readonly Dictionary<UIElement, UIElement> delegateByChild = new Dictionary<UIElement,UIElement>();
public Panel LayoutPanel
{
get { return (Panel)GetValue(LayoutPanelProperty); }
set { SetValue(LayoutPanelProperty, value); }
}
public static readonly DependencyProperty LayoutPanelProperty =
DependencyProperty.Register("LayoutPanel", typeof(Panel), typeof(DelegatePanel), new PropertyMetadata(null));
protected override Size MeasureOverride(Size availableSize)
{
if(this.LayoutPanel==null)
return base.MeasureOverride(availableSize);
this.delegateByChild.Clear();
this.LayoutPanel.Children.Clear();
foreach (UIElement _child in this.Children)
{
var child = _child;
var delegateChild = new DelegateChild(
availableChildSize =>
{
child.Measure(availableChildSize);
return child.DesiredSize;
},
finalChildSize =>
{
return finalChildSize;
});
delegateByChild[child] = delegateChild;
this.LayoutPanel.Children.Add(delegateChild);
}
this.LayoutPanel.Measure(availableSize);
return this.LayoutPanel.DesiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
if(this.LayoutPanel==null)
return base.ArrangeOverride(finalSize);
this.LayoutPanel.Arrange(new Rect(finalSize));
foreach (var kv in delegateByChild)
{
var child = kv.Key;
var delegateChild = kv.Value;
var position = delegateChild.TranslatePoint(default(Point), this.LayoutPanel);
Rect finalChildBounds = new Rect(
position,
delegateChild.RenderSize);
child.Arrange(finalChildBounds);
}
return this.LayoutPanel.RenderSize;
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows.Controls;
使用System.Windows;
公共类委派面板:面板
{
私有密封类DelegateChild:FrameworkElement
{
只读Func度量;
只读函数排列;
公共委托子对象(函数度量、函数排列)
{
这个.measure=度量;
安排;安排;
}
受保护的覆盖尺寸测量覆盖(尺寸可用尺寸)
{
返回度量(可用性);
}
受保护的替代尺寸排列替代(尺寸最终化)
{
退货安排(最终化);
}
}
readonly Dictionary delegateByChild=新字典();
公共面板布局面板
{
获取{return(Panel)GetValue(LayoutPanelProperty);}
set{SetValue(LayoutPanelProperty,value);}
}
公共静态只读从属属性LayoutPanelProperty=
DependencyProperty.Register(“LayoutPanel”、typeof(Panel)、typeof(DelegatePanel)、new PropertyMetadata(null));
受保护的覆盖尺寸测量覆盖(尺寸可用尺寸)
{
if(this.LayoutPanel==null)
返回基准。测量超越(可用尺寸);
this.delegateByChild.Clear();
this.LayoutPanel.Children.Clear();
foreach(UIElement\u this.Children中的子元素)
{
var child=_child;
var delegateChild=新的delegateChild(
availableChildSize=>
{
child.Measure(可用childsize);
返回child.DesiredSize;
},
finalChildSize=>
{
返回finalChildSize;
});
delegateByChild[child]=delegateChild;
this.LayoutPanel.Children.Add(delegateChild);
}
this.LayoutPanel.Measure(availableSize);
返回this.LayoutPanel.DesiredSize;
}
受保护的替代尺寸排列替代(尺寸最终化)
{
if(this.LayoutPanel==null)
返回基数。安排覆盖(最终化);
this.LayoutPanel.Arrange(新Rect(最终化));
foreach(由子代指定的var kv)
{
var child=千伏钥匙;
var delegateChild=千伏值;
var position=delegateChild.TranslatePoint(默认值(点),this.LayoutPanel);
Rect finalChildBounds=新的Rect(
立场,,
delegateChild.RenderSize);
儿童。安排(最终儿童边界);
}
返回this.LayoutPanel.RenderSize;
}
}
免责声明:这不实现VirtualzingPanel。因此,虽然它在ItemsControl和gang内部工作,但对于大型集合来说,它的执行速度不够快。我也这么想,但这是正确的做法吗?由于绑定而添加元素时是否也调用OnVisualChildrenChanged?这将是可取的。另一方面,当添加边框时,OnVisualChildren是否发生了变化?这是不可取的…什么样的动画,你希望能够与“任何面板”?不同类型的面板(网格、画布、stackpanel、dockpanel等)对于如何在其中定位项目具有完全不同的功能。我不认为有一个通用的方法来做你所描述的事情…有。但这是我的诀窍,很难描述。但是技术细节似乎对我来说是个问题:(当我第一次看“双重授权”时,我确信你说过,尽管你可以做的是玩。我完全同意。:)但是,请注意,DockPanel.Dock之类的东西不会从你的真实孩子传播到授权布局面板的鬼子。