首先我們來說最簡單的畫面的呈現。
一.在自定義控件上畫矩形
增加一個自定義控件類:
打開創建的類重載OnRender函數並注釋掉靜態構造函數,代碼如下
public class CustomerRender : Control
{
//static CustomerRender()
//{
// DefaultStyleKeyProperty.OverrideMetadata(typeof (CustomerRender), new FrameworkPropertyMetadata(typeof (CustomerRender)));
//}
protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawRectangle(Brushes.Bisque, null, new Rect(0, 0, 50, 50));
}
}
在Window1這個類中修改如下
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
CustomerRender customerRender = new CustomerRender();
customerRender.Width = 200;
customerRender.Height = 300;
this.Content = customerRender;
}
}
運行程序我們可以看到:
當然你還可以通過drawingContext來畫圓圈、不規則矩形、圓角矩形 和寫文字等等。具體可以看DrawingContext 中的API介紹和MSDN文檔。
二.拖動矩形
一般來說UI是數據的反應,UI的變化其實是後段數據的變化 。我們一般在移動到方塊上方後,按住鼠標開始拖動,那麼在鼠標移動上去之後 ,我們首先判斷此位置是否有矩形,點擊鼠標的時候,我們記錄點下的這個坐標 為A,鼠標移動的時候我們根據移動時候鼠標所在坐標和原來的A坐標比較,然後 把這個差值和矩形的開始坐標相加,通過InvalidateVisual()方法不斷重畫就達 到了移動的效果。
如果你需要鼠標移動出窗口還可以移動該矩形請加CaptureMouse()來 鎖定當前鼠標,但不要忘記在鼠標放開的時候把它給釋放掉 ReleaseMouseCapture()。
我們在window類中為我們的控件賦上底色
InitializeComponent();
CustomerRender customerRender = new CustomerRender();
customerRender.Width = 200;
customerRender.Height = 300;
customerRender.Background = Brushes.Green;
this.Content = customerRender;
並在控件的OnRender函數中 加入
drawingContext.DrawRectangle(Background, null,new Rect(new Point(0,0),this.RenderSize));
效果如圖:
這時你拖動方塊可能會發現方塊可以被移出背景,這在WPF下是允許的 ,但有時候這又不符合情理,我們需要把多余的部分裁減掉。
protected override void OnRender(DrawingContext drawingContext)
{
Rect rect = new Rect(new Point(0, 0), this.RenderSize);
drawingContext.DrawRectangle(Background, null, rect);
//創建一個填充色為Bisque邊框色為Orange,橫坐標 為2,縱坐標為3,寬度為80,長度為50的矩形
Pen pen = new Pen(Brushes.Orange, 1);
pen.Freeze();//凍結可以加快呈現速度
RectangleGeometry rectangleGeometry = new RectangleGeometry(rect);
rectangleGeometry.Freeze();
drawingContext.PushClip(rectangleGeometry);
drawingContext.DrawRectangle(Brushes.Bisque, pen, _rectangle);
drawingContext.Pop();
}
主要注意drawingContext.PushClip (rectangleGeometry);到drawingContext.Pop();之間是剪切的有效范圍。
Pop()結束符不僅僅用於剪切,還適用於遮幕,Effect效果等有Push開頭 的那些玩藝。(關於GuidelineSet推薦一個網址: http://www.wpftutorial.net/DrawOnPhysicalDevicePixels.html)
剪切 後的效果如下:
三.動畫效果
當然我們也可以做些拖動預覽效果如 下:
實現的原理無非是拖動的時候畫一個假矩形,並把該矩形呈現的代碼 放在剪切的效果之外,拖動結束後把假的位置給真的調用重畫一遍就實現了。
我們能不能用動畫效果使得矩形慢慢移動到指定位置,答案當然是肯定 的。這裡可以用System.Windows.Media.Animation命名空間下的一些方法來實現
RectAnimation rectAnimation = new RectAnimation
(_rectangle,_preivewRectangle,new Duration(TimeSpan.FromMilliseconds (600)));
drawingContext.DrawRectangle(Brushes.Bisque, pen, _rectangle,rectAnimation.CreateClock());
你也可以用來做顏 色的變換,大小的變化等等。
四.多個矩形
有多個矩形可以把矩 形放到一個集合中依次判斷,層疊的話就是後段數據存放的先後順序問題,UI顯 示的快慢和後段數據查找有直接的聯系,這個也是算法的價值體現。
小 結
這裡講的做法也是winform裡的大多數實現方式,只不過WPF使得我們 對像素處理關心的更少,自繪在WPF的應用中相對winform要少了很多,除非用在 大數據量的地方,WPF復合控件能完成大部分的需求——只要你能熟 練定義樣式,並了解可視樹,邏輯樹,以及各個控件的用法。
本文配套源碼