SilverLight自定义布局控件
看到葡萄城控件团队里边关于silverlight的布局控件的内部结构和Pro.Silverlight.4布局控件后收益匪浅,自己也顺手参考着例子写了个布局控件。控件类似于Grid,但有一个Count属性,表示一行可以放的控件数量。可以根据自己的需要改变这个属性,来确定一行的显示。
代码
public class UniformPanel : Panel {
//定义Count属性
public int Count { get { return (int)GetValue(CountProperty); } set { SetValue(CountProperty, value); } } public static readonly DependencyProperty CountProperty = DependencyProperty.Register("Count", typeof(int), typeof(UniformPanel), new PropertyMetadata(new PropertyChangedCallback(CountChanged))); private double column; private double row; //根据Count属性计算总终确定的行数和列数
private void Caculate() { double childCount = (double)this.Children.Count; if (childCount > 0) { if (childCount > Count) { column = Count; row = (int)Math.Ceiling(childCount / Count); } else if (childCount < Count) { column = childCount; row = 1; } } } //重写MeasureOverrride方法确定最终需要的大小
protected override Size MeasureOverride(Size availableSize) { Caculate(); Size maxSize = new Size(0, 0); foreach (UIElement item in this.Children) { item.Measure(availableSize); maxSize.Height = Math.Max(item.DesiredSize.Height, maxSize.Height); maxSize.Width = Math.Max(item.DesiredSize.Width, maxSize.Width); } double maxWidth = Math.Max(maxSize.Width * column, availableSize.Width); double maxHeight = Math.Max(maxSize.Height * row, availableSize.Height); return new Size(maxWidth, maxHeight); } //重写ArrangOverride方法
protected override Size ArrangeOverride(Size finalSize) { Refresh(finalSize); return finalSize; } //Count属性改变触发的事件
private static void CountChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { UniformPanel panel = (UniformPanel)sender;
//如果控件没有定义自己的宽高则默认为200*200,否则将报错
if (double.IsNaN(panel.Width) || double.IsNaN(panel.Height)) { panel.Height = 200; panel.Width = 200; } panel.Refresh(new Size(panel.Width, panel.Height)); } public void Refresh(Size finalSize) { Caculate(); double x = finalSize.Width / column; double y = finalSize.Height / row; Rect rect = new Rect(0, 0, x, y); foreach (UIElement item in this.Children) { item.Arrange(rect); rect.X+=x; if (rect.X >= x * column) { rect.Y += y; rect.X = 0; if (rect.Y > y * row) rect = new Rect(0, 0, 0, 0); } } } }
设置Count=2效果
设置Count=4效果
源码下载