在第一篇中,Desktop类有一个问题就是不支持Rows设置为三或三以上的数
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Collections.Generic; namespace yrsj.Controls { public class Desktop : Canvas { private string clickName = string.Empty;//记录单击控件名称 private List<double> Tops = new List<double>();//Top位置坐标 private List<CustomPanel> Panels = new List<CustomPanel>();//Panel集 private int ctlNum = int.MaxValue; private int rowCtlNum = int.MinValue; private bool isLoaded = false; public static readonly DependencyProperty RowsProperty = DependencyProperty.Register("Rows", typeof(int), typeof(Desktop), new PropertyMetadata(1, RowsChanged)); public int Rows { get { return (int)GetValue(RowsProperty); } set { SetValue(RowsProperty, value); } } private static void RowsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { Desktop desktop = sender as Desktop; if (desktop == null) return; int rows = 0; if (e.NewValue != null) int.TryParse(e.NewValue.ToString(), out rows); if (rows > 0) desktop.rowCtlNum = (desktop.ctlNum / rows) + (desktop.ctlNum % rows > 0 ? 1 : 0); } public Desktop() : base() { this.MinWidth = 480; this.MinHeight = 400; this.Loaded += new RoutedEventHandler(Desktop_Loaded); } void Desktop_Loaded(object sender, RoutedEventArgs e) { if (isLoaded) return; for (int i = 0; i < this.Children.Count; i++) { CustomPanel panel = this.Children[i] as CustomPanel; if (panel == null) continue; if (panel.Name == null || panel.Name.Trim() == "") panel.Name = "panel" + i.ToString(); panel.Click += BodyPanel_Click; panel.Margin = new Thickness(5, 3, 3, 3); Panels.Add(panel); } ctlNum = Panels.Count; if (Rows == 0) Rows = 1; rowCtlNum = (ctlNum / Rows) + (ctlNum % Rows > 0 ? 1 : 0); this.SizeChanged += new SizeChangedEventHandler(Desktop_SizeChanged); Desktop_SizeChanged(sender, null); isLoaded = true; } private void Desktop_SizeChanged(object sender, SizeChangedEventArgs e) { Double LWidth = 0;//小对象的宽度 Double MWidth = 0;//大对象的宽度 Double MHeight = 0;//大对象的高度 Double LHeight = 0;//小对象的高度 CalcPanelWidthAndHeight(out LWidth, out LHeight, out MWidth, out MHeight); //判断执行动画 if (string.IsNullOrEmpty(clickName) == true)//初始化动画,也就是第一次点击 { this.Children.Clear(); SetNormalState(MHeight, null); } else { Initialization(MWidth, MHeight, LWidth, LHeight); } } private void SetNormalState(double height, Storyboard sb) { Double MiddleWidth = this.ActualWidth / rowCtlNum - 5;//对象宽度 Double MiddleHeight = height / Rows - rowCtlNum - 5;//对象高度 int curRow = 0; for (int i = 0; i < ctlNum; i++) { if (i >= rowCtlNum) curRow = i / rowCtlNum; CustomPanel temp = Panels[i]; double left = 0; double top = 0; if (i < rowCtlNum)//控制行Top { top = 2;//第一行顶点 left = MiddleWidth * i + i * 5;//第一行的左边距 } else { top = this.ActualHeight / Rows * curRow;//第二行顶点 left = MiddleWidth * (i - rowCtlNum * curRow) + (i - rowCtlNum * curRow) * 5;//第二行的左边距 } if (sb == null) { temp.Width = MiddleWidth; temp.Height = MiddleHeight; temp.SetValue(Canvas.LeftProperty, left);//与Margin有所不同 temp.SetValue(Canvas.TopProperty, top); this.Children.Add(temp); } else ReducePanel(sb, temp, MiddleWidth, MiddleHeight, top, left); } } private void CalcPanelWidthAndHeight(out double lWidth, out double lHeight, out double mWidth, out double mHeight) { lWidth = 200;//小对象的宽度 mWidth = this.ActualWidth - lWidth - 5;//大对象的宽度 mHeight = this.ActualHeight - 5;//大对象的高度 lHeight = (mHeight - (ctlNum - 1) * 6) / (ctlNum - 1);//小对象的高度 } private void BodyPanel_Click(object sender, RoutedEventArgs e) { CustomPanel panel = sender as CustomPanel; //Canvas ca = panel.Parent as Canvas; Double LWidth = 0;//小对象的宽度 Double MWidth = 0;//大对象的宽度 Double MHeight = 0;//大对象的高度 Double LHeight = 0;//小对象的高度 CalcPanelWidthAndHeight(out LWidth, out LHeight, out MWidth, out MHeight); //判断执行动画 if (string.IsNullOrEmpty(clickName) == true)//初始化动画,也就是第一次点击 { clickName = panel.Name;//保存为上一个点击按钮 Initialization(MWidth, MHeight, LWidth, LHeight); } else { Storyboard sb = new Storyboard(); if (panel.Name == clickName)//还原界面 { //当点击上一个点击的按钮时,还原初始界面 SetNormalState(MHeight, sb); clickName = string.Empty; } else//位置交换 { CustomPanel ctl = this.FindName(clickName) as CustomPanel; MaxPanel(sb, panel, MWidth - 5, MHeight - 10); ctl.Button.IsMax = false; ReducePanel(sb, ctl, LWidth, LHeight, Canvas.GetTop(panel), MWidth); clickName = panel.Name; } sb.Begin(); } } /// <summary> /// 获取每个对象顶点的位置数组 /// </summary> /// <param name="ca"></param> /// <returns></returns> public List<double> topList(Canvas ca) { List<double> ListTmp = new List<double>();//Top位置坐标 //初始化Tops坐标 //Tops.Add((ctlNum - 1)); Double MHeight = this.ActualHeight - 5;//大对象的高度 Double LTop = (MHeight - (ctlNum - 1) * 6) / (ctlNum - 1);//小对象的高度 for (int i = 0; i < ctlNum - 1; i++) { //95:初始化后控件高 3:间距 ListTmp.Add(i * LTop + i * 5 + 5); } return ListTmp; } /// <summary> /// 所有对象归位 /// </summary> /// <param name="MaxWidth">大对象的宽</param> /// <param name="MaxHeight">大对象的高</param> /// <param name="LWidth">小对象的宽</param> /// <param name="LHeight">小对象的高</param> private void Initialization(double MaxWidth, double MaxHeight, Double LWidth, Double LHeight) { Tops = topList(this); Storyboard sb = new Storyboard(); int iTop = 0; for (int i = 0; i < ctlNum; i++) { CustomPanel ctl = Panels[i]; if (ctl.Name == clickName)//判断是否是单击对象 { MaxPanel(sb, ctl, MaxWidth - 5, MaxHeight - 10);//第一次点击时 } else { ctl.Button.IsMax = false; ReducePanel(sb, ctl, LWidth, LHeight, Tops[iTop], MaxWidth);//其它的缩小归位 iTop++; } } sb.Begin(); } /// <summary> /// 放大Panel对象 /// </summary> /// <param name="sb"></param> /// <param name="panel"></param> private void MaxPanel(Storyboard sb, CustomPanel panel, double MaxWidth, double MaxHeight) { sb.Children.Add(CreateDoubleAnimation(panel, "(FrameworkElement.Width)", panel.Width, MaxWidth)); sb.Children.Add(CreateDoubleAnimation(panel, "(FrameworkElement.Height)", panel.Height, MaxHeight)); sb.Children.Add(CreateDoubleAnimation(panel, "(Canvas.Top)", Canvas.GetTop(panel), 5)); sb.Children.Add(CreateDoubleAnimation(panel, "(Canvas.Left)", Canvas.GetLeft(panel), 0)); } /// <summary> /// 缩小Panel对象,也就是小窗口的大小 /// </summary> /// <param name="sb">动画板</param> /// <param name="panel">动画对象</param> /// <param name="width">宽度(缩小目标)</param> /// <param name="height">高度(缩小目标)</param> /// <param name="Top">对象最终顶边</param> /// <param name="Left">对象最终左边</param> private void ReducePanel(Storyboard sb, CustomPanel panel, double width, double height, double Top, double Left) { sb.Children.Add(CreateDoubleAnimation(panel, "(FrameworkElement.Width)", panel.Width, width)); sb.Children.Add(CreateDoubleAnimation(panel, "(FrameworkElement.Height)", panel.Height, height)); sb.Children.Add(CreateDoubleAnimation(panel, "(Canvas.Top)", Canvas.GetTop(panel), Top)); sb.Children.Add(CreateDoubleAnimation(panel, "(Canvas.Left)", Canvas.GetLeft(panel), Left)); } /// <summary> /// 创建一个DoubleAnimation动画对象 /// </summary> /// <param name="element">动画对象</param> /// <param name="property">动画对象属性</param> /// <param name="from">起始值</param> /// <param name="to">结束值</param> /// <returns></returns> public static DoubleAnimation CreateDoubleAnimation(DependencyObject element, string property, double from, double to) { DoubleAnimation da = new DoubleAnimation(); TimeSpan tsBeginTime = new TimeSpan(0, 0, 0, 0, 0);//开始时间 TimeSpan tsDuration = TimeSpan.FromMilliseconds(1000);//播放时间的长度 da.BeginTime = tsBeginTime; da.Duration = new Duration(tsDuration);//播放长度 da.To = to; da.From = from; da.EasingFunction = new PowerEase() { EasingMode = EasingMode.EaseOut, Power = 3 }; Storyboard.SetTarget(da, element); Storyboard.SetTargetProperty(da, new PropertyPath(property)); return da; } } }
接上篇
BlackPanel
[TemplatePart(Name = PanelDescript, Type = typeof(TextBlock))]
public class BlackPanel : CustomPanel
{
protected internal const string PanelDescript = "txtDescript";
protected internal TextBlock txtDescript;
public static readonly DependencyProperty TitleDescriptProperty =
DependencyProperty.Register("TitleDescript", typeof(string), typeof(BlackPanel), new PropertyMetadata("", new PropertyChangedCallback(TitleDescriptChanged)));
public string TitleDescript
{
get { return (string)GetValue(TitleDescriptProperty); }
set { SetValue(TitleDescriptProperty, value); }
}
private static void TitleDescriptChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
BlackPanel panel = sender as BlackPanel;
if (panel == null) return;
if (e.NewValue != null && panel.txtDescript != null)
panel.txtDescript.Text = e.NewValue.ToString();
else if (panel.txtDescript != null)
panel.txtDescript.Text = "";
}
public BlackPanel()
: base()
{
this.DefaultStyleKey = typeof(BlackPanel);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
txtDescript = base.GetTemplateChild(PanelDescript) as TextBlock;
if (txtDescript != null)
txtDescript.Text = TitleDescript;
}
}
BlackPanel样式
<Style TargetType="local:BlackPanel">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:BlackPanel">
<Grid x:Name="Root" Background="#fff5f5f5">
<Rectangle RadiusX="2" RadiusY="2" Stroke="#ffc3c3c3"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28"/>
<RowDefinition Height="17"/>
<RowDefinition/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="1">
<Grid.Background>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#ff4c8a8c" Offset="0.4"/>
<GradientStop Color="#ff32777f" Offset="1"/>
</LinearGradientBrush>
</Grid.Background>
<local:PanelButton x:Name="btnMax" Margin="0 3 3 0" BorderBrush="White" Width="11" Height="11"
VerticalAlignment="Top" HorizontalAlignment="Right"/>
<TextBlock x:Name="txtTitle" Foreground="#ffffffff" Margin="10 0" FontSize="14" FontWeight="Bold"
HorizontalAlignment="Left" VerticalAlignment="Bottom" Text=""/>
</Grid>
<Grid Grid.Row="1" Margin="1 -1 1 0">
<Grid.Background>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#ff15373b" Offset="0.4"/>
<GradientStop Color="#ff030a0b" Offset="1"/>
</LinearGradientBrush>
</Grid.Background>
<TextBlock x:Name="txtDescript" Text="" Foreground="#ffffffff"/>
</Grid>
<ContentControl x:Name="contentControl" Grid.Row="2" Content="{TemplateBinding Content}" Margin="5 2"
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
<TextBlock x:Name="txtFooter" Grid.Row="3" Foreground="#ff808080" FontSize="12" Visibility="Collapsed"
VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="0 0 10 3"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
GrayPanel
[TemplatePart(Name = PanelImage, Type = typeof(Image))]
[TemplatePart(Name = PanelDescript, Type = typeof(TextBlock))]
public class GrayPanel : CustomPanel
{
protected internal const string PanelImage = "img";
protected internal const string PanelDescript = "txtDescript";
protected internal Image img;
protected internal TextBlock txtDescript;
/// <summary>
/// 按钮图片
/// </summary>
public static readonly DependencyProperty ImageProperty =
DependencyProperty.Register("Image", typeof(ImageSource), typeof(GrayPanel), new PropertyMetadata(null, new PropertyChangedCallback(ImageChanged)));
/// <summary>
/// 按钮图片
/// </summary>
public ImageSource Image
{
get { return (ImageSource)GetValue(ImageProperty); }
set { SetValue(ImageProperty, value); }
}
private static void ImageChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
GrayPanel panel = sender as GrayPanel;
if (panel == null) return;
if (e.NewValue != null && panel.img != null)
panel.img.Source = (ImageSource)e.NewValue;
else if (panel.img != null)
panel.img.Source = null;
}
public static readonly DependencyProperty TitleDescriptProperty =
DependencyProperty.Register("TitleDescript", typeof(string), typeof(GrayPanel), new PropertyMetadata("", new PropertyChangedCallback(TitleDescriptChanged)));
public string TitleDescript
{
get { return (string)GetValue(TitleDescriptProperty); }
set { SetValue(TitleDescriptProperty, value); }
}
private static void TitleDescriptChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
GrayPanel panel = sender as GrayPanel;
if (panel == null) return;
if (e.NewValue != null && panel.txtDescript != null)
panel.txtDescript.Text = e.NewValue.ToString();
else if (panel.txtDescript != null)
panel.txtDescript.Text = "";
}
public GrayPanel()
: base()
{
this.DefaultStyleKey = typeof(GrayPanel);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
img = base.GetTemplateChild(PanelImage) as Image;
txtDescript = base.GetTemplateChild(PanelDescript) as TextBlock;
if (img != null)
img.Source = Image;
if (txtDescript != null)
txtDescript.Text = TitleDescript;
}
}
GrayPanel样式
<Style TargetType="local:GrayPanel">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:GrayPanel">
<Grid x:Name="Root" Background="#fff5f5f5">
<Rectangle RadiusX="2" RadiusY="2" Stroke="#ffc3c3c3"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="55"/>
<RowDefinition/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#fff5f5f5" Margin="1">
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
<RowDefinition/>
<RowDefinition Height="1"/>
<RowDefinition Height="1"/>
</Grid.RowDefinitions>
<Image x:Name="img" Grid.RowSpan="2" Width="30" Height="26" Margin="10 15 0 0"
HorizontalAlignment="Left" VerticalAlignment="Top"/>
<local:PanelButton x:Name="btnMax" Margin="0 3 3 0" BorderBrush="#ff3e3e3e" Width="11" Height="11"
VerticalAlignment="Top" HorizontalAlignment="Right"/>
<TextBlock x:Name="txtTitle" Text="" Grid.Row="0" Margin="45 0 0 0" FontWeight="Bold"
HorizontalAlignment="Left" VerticalAlignment="Bottom" FontSize="14" Foreground="#ff3e3e3e"/>
<TextBlock x:Name="txtDescript" Text="" Grid.Row="1" Margin="45 0 0 0" Foreground="#ffaaaaaa"
HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Rectangle Grid.Row="2" Fill="#ff363636" Margin="5 0"/>
<Rectangle Grid.Row="3" Fill="#ff000000" Margin="5 0"/>
</Grid>
<ContentControl x:Name="contentControl" Grid.Row="1" Margin="5 2"
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
<TextBlock x:Name="txtFooter" Grid.Row="2" Foreground="#ff808080" FontSize="12" Visibility="Collapsed"
VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="0 0 10 3"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
GreenPanel
public class GreenPanel : CustomPanel
{
public GreenPanel()
: base()
{
this.DefaultStyleKey = typeof(GreenPanel);
}
}
GreenPanel样式
<Style TargetType="local:GreenPanel">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:GreenPanel">
<Grid x:Name="Root" Background="#fff5f5f5">
<Rectangle RadiusX="2" RadiusY="2" Stroke="#ffc3c3c3"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
<RowDefinition/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="1">
<Grid.Background>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#ff7fc473" Offset="0.4"/>
<GradientStop Color="#ff4f8c2a" Offset="1"/>
</LinearGradientBrush>
</Grid.Background>
<local:PanelButton x:Name="btnMax" Margin="0 3 3 0" BorderBrush="White" Width="11" Height="11"
VerticalAlignment="Top" HorizontalAlignment="Right"/>
<TextBlock x:Name="txtTitle" Foreground="#ffffffff" Margin="10 0" FontSize="14" FontWeight="Bold"
HorizontalAlignment="Left" VerticalAlignment="Bottom" Text=""/>
</Grid>
<ContentControl x:Name="contentControl" Grid.Row="1" Margin="5 2"
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
<TextBlock x:Name="txtFooter" Grid.Row="2" Foreground="#ff808080" FontSize="12" Visibility="Collapsed"
VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="0 0 10 3"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
最后附上使用方式
<my:Desktop x:Name="caMain" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Rows="2" Grid.Row="3" Margin="4 0">
<my:BlackPanel Margin="5 3 3 3" Title="待办列表 [共2项]"
TitleDescript="Connected to Earansoft Service"
Footer="最后更新于:今天 14:21">
<my:BlackPanel.Content>
<TextBlock Text="test" VerticalAlignment="Top"/>
</my:BlackPanel.Content>
</my:BlackPanel>
<my:GrayPanel Margin="5 3 3 3" Image="Images/test.png"
Title="公司追杀榜 [共3项]" TitleDescript="24小时工作倒计时"
Footer="下次自动更新时间:今天 14:50">
<my:GrayPanel.Content>
<TextBlock Text="test" VerticalAlignment="Top"/>
</my:GrayPanel.Content>
</my:GrayPanel>
<my:GreenPanel Margin="5 3 3 3" Title="企业战略、部门战略和个人战略"
Footer="最后更新于:今天 14:21">
<my:GreenPanel.Content>
<TextBlock Text="test" VerticalAlignment="Top"/>
</my:GreenPanel.Content>
</my:GreenPanel>
<my:BlackPanel Margin="5 3 3 3" Title="待办列表 [共2项]"
TitleDescript="Connected to Earansoft Service"
Footer="最后更新于:今天 14:21">
<my:BlackPanel.Content>
<TextBlock Text="test" VerticalAlignment="Top"/>
</my:BlackPanel.Content>
</my:BlackPanel>
<my:GrayPanel Margin="5 3 3 3" Image="Images/test.png"
Title="公司追杀榜 [共3项]" TitleDescript="24小时工作倒计时"
Footer="下次自动更新时间:今天 14:50">
<my:GrayPanel.Content>
<TextBlock Text="test" VerticalAlignment="Top"/>
</my:GrayPanel.Content>
</my:GrayPanel>
<my:GreenPanel Margin="5 3 3 3" Title="企业战略、部门战略和个人战略"
Footer="最后更新于:今天 14:21">
<my:GreenPanel.Content>
<TextBlock Text="test" VerticalAlignment="Top"/>
</my:GreenPanel.Content>
</my:GreenPanel>
</my:Desktop>
想要界面的朋友可到下面链接下载,这是我最初上传的界面程序,完整的代码我就不上传了,以免引起不必要的麻烦
http://download.csdn.net/detail/zdming2000/3997692