在WinForm中,將DataGridView控件的列的AutoSizeMode屬性設(shè)置為Fill,然后將FillWeight屬性設(shè)置為列寬所占的權(quán)重,這樣可實(shí)現(xiàn)列寬自動(dòng)填充列,下圖說明自動(dòng)填充寬度的算法:
但是在Silverlight中,DataGrid控件的列寬只有四種模式:Auto、Pixel、SizeToCells、SizeToHeader,沒有Fill模式,無法實(shí)現(xiàn)自動(dòng)填充列寬。
那怎么實(shí)現(xiàn)此功能呢?用自定義模板?似乎比較麻煩,并且很難實(shí)現(xiàn)重用。看來只有用自定義控件了,先初步分析,首先,我們要控制列寬,肯定得處理DataGrid的SizeChanged事件;其次,我們必須定義DataGrid中每列寬度的填充模式;最后,還得定義每列寬度所占的權(quán)重。后兩個(gè)步驟如何實(shí)現(xiàn)呢?Silverlight DataGrid控件中的列有三種類型DataGridTextColumn、DataGridCheckBoxColumn以及DataGridTemplateColumn,如果我們?cè)俜謩e為這三種類型創(chuàng)建子類來添加自定義屬性顯然太麻煩。
DataGrid需要知道每個(gè)DataGridColumn中的寬度模式及填充比例,以便在DataGrid SizeChanged事件中設(shè)置每列的寬度,但是我們又要避免重新去定義每個(gè)DataGridColumn類型。Silverlight已經(jīng)為此中問題提供了一種設(shè)計(jì)模式:即附加屬性。我們常用的Grid布局控件,其中Grid.Row及Grid.Column屬性即為附加屬性,添加到Grid中的控件并沒有Row和Column屬性,但是通過Grid的Row和Column附加屬性即可通知Grid控件應(yīng)該被放到哪行哪列。同理,我們?yōu)镈ataGrid添加一個(gè)附加屬性,即可讓DataGrid中的每一列向DataGrid說明該列的填充模式和寬度所占的權(quán)重。為了簡便,我們添加一個(gè)附加屬性:WidthWeight,int類型,如果為0表示該列為固定寬度,否則表示該列所占權(quán)重。
關(guān)于附加屬性,請(qǐng)參考Silverlight SDK文檔,有中文版本,簡單易學(xué):)
代碼:
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 Test
{
public class AutoFillDataGrid : DataGrid
{
public static readonly DependencyProperty WidthWeightProperty = DependencyProperty.RegisterAttached(
"WidthWeight", typeof(int), typeof(AutoFillDataGrid), new PropertyMetadata(0));
private double paddingRight = 0;
public AutoFillDataGrid()
{
this.SizeChanged += new SizeChangedEventHandler(AutoFillDataGrid_SizeChanged);
}
void AutoFillDataGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
int weight = 0;
double fix = 0;
int temp = 0;
Queue<DataGridColumn> queue = new Queue<DataGridColumn>();
foreach (DataGridColumn column in this.Columns)
{
temp = (int)column.GetValue(WidthWeightProperty);
if (temp > 0)
{
weight += temp;
queue.Enqueue(column);
}
else
{
fix += column.ActualWidth;
}
}
double width = e.NewSize.Width - this.paddingRight - fix - this.Padding.Left - this.Padding.Right;
double actualWidth = 0;
while (queue.Count > 0)
{
DataGridColumn column = queue.Dequeue();
temp = (int)column.GetValue(WidthWeightProperty);
actualWidth = width * (double)temp / weight;
if (actualWidth < column.MinWidth)
{
actualWidth = column.MinWidth;
}
if (actualWidth > column.MaxWidth)
{
actualWidth = column.MaxWidth;
}
column.Width = new DataGridLength(actualWidth);
}
}
/// <summary>
/// 右ò邊?間?距à,?可é看′著?為aDataGrid的?滾?動(dòng)ˉ條?寬í度è
/// </summary>
public double PaddingRight
{
get
{
return this.paddingRight;
}
set
{
this.paddingRight = value;
}
}
public static void SetWidthWeight(DataGridColumn column, int value)
{
column.SetValue(WidthWeightProperty, value);
}
public static int GetWidthWeight(DataGridColumn column)
{
return (int)column.GetValue(WidthWeightProperty);
}
}
}
OK,我們已經(jīng)實(shí)現(xiàn)自己的DataGrid控件,下一步就是如何使用了:
最簡單的辦法,在Silverlight項(xiàng)目上單擊右鍵,選擇生成,完成后,打開我們的xaml文件,此時(shí)工具箱中會(huì)出現(xiàn)我們的AutoFillDataGrid控件,拖動(dòng)到xaml文件中即可。然后就像使用DataGrid控件一樣,向AutoFillDataGrid中添加列,關(guān)鍵點(diǎn)是在需要自動(dòng)填充列寬的DataGridColumn上設(shè)置AutoFillDataGrid.WidthWeight屬性。
示例源碼下載 <---Visual 2010,如果使用Visual 2008請(qǐng)自己創(chuàng)建新工程,然后粘貼代碼