天天看點

wpf控件設計時支援(3)

原文: wpf控件設計時支援(3)

  1. wpf設計時調試
  2. 編輯模型
  3. 裝飾器

1.wpf設計時調試

為了更好的了解wpf設計時架構,那麼調試則非常重要,通過以下配置可以調試控件的設計時代碼

(1)将啟動項目配置成外部的visual studio ide啟動程式devenv.exe

wpf控件設計時支援(3)

(2)F5啟動調試然後會打開一個新的visual studio ide,這個時候要記得重新打開你要調試的那個項目.

以上兩個步驟就可以實作設計時調試了

2.編輯模型體系

當選中某些控件出現的設計時,這個選中的控件便成了可編輯的對象. 設計環境會傳回一個ModelItem的類,這個類可以幫助你更改控件視圖,用于互動.這裡的做法與直接更改wpf控件有些不同,如直接改變wpf一個控件的一個屬性

this.Content = "Hello";      
http://11011.net/software/vspaste

在設計環境下,也可以擷取到處在編輯狀态的控件,若采取上面的做法,雖可以變更控件的視圖,但卻未變更控件在xaml的更改.

設計環境下所有控件的更改都封裝在ModelItem類中.做法如下

//selectedContent's Type is ModelItem
selectedContent.Properties["Content"].SetValue("Hello");
//selectedContent.Properties[ContentControl.ContentProperty].SetValue("Hello");      
http://11011.net/software/vspaste

selectedContent類型是ModelItem,其中用Properties索引值擷取屬性,有兩種方式擷取屬性,字元串和靜态項屬性

在上篇介紹過控件上下文菜單的設計時做法,我們以此為基礎做個示例,以ContentControl為例,如下圖

wpf控件設計時支援(3)

共有4個操作,SetHello和SetRedForeground用于測試ModelItem變更控件視圖的功能,

第三個和第四個菜單用于測試變更時事務的操作.(即要麼全過,要麼全不過)

以下為詳細代碼

public class ContentMenuProvider : PrimarySelectionContextMenuProvider
    {
        //略去構造函數添加MenuAcion的代碼
void ModelEditingScopeFailMenuAction_Execute(object sender, MenuActionEventArgs e)
       {
           ModelItem selectedContent = e.Selection.PrimarySelection;
           using (ModelEditingScope scope = selectedContent.BeginEdit("test"))
           {
               //selectedContent's Type is ModelItem
               selectedContent.Properties["Content"].SetValue("TextModelEditingScope");
               //wrong
               selectedContent.Properties["Foreground"].SetValue("Red");
               scope.Complete();
           }
       }

       void ModelEditingScopeMenuAction_Execute(object sender, MenuActionEventArgs e)
       {
           ModelItem selectedContent = e.Selection.PrimarySelection;
           using (ModelEditingScope scope = selectedContent.BeginEdit("test"))
           {
               selectedContent.Properties["Content"].SetValue("TextModelEditingScope");
               selectedContent.Properties["Foreground"].SetValue(Brushes.Green);
               scope.Complete();
           }
       }

       void SetRedForegroundMenuAction_Execute(object sender, MenuActionEventArgs e)
       {
           ModelItem selectedContent = e.Selection.PrimarySelection;
           selectedContent.Properties["Foreground"].SetValue(Brushes.Red);
           selectedContent.Properties[Control.ForegroundProperty].SetValue(Brushes.Red);
       }

       void SetHelloMenuAction_Execute(object sender, MenuActionEventArgs e)
       {
           ModelItem selectedContent = e.Selection.PrimarySelection;
           //ContentControl element = selectedContent.View as ContentControl;
           //selectedContent.Content = "hello";
           selectedContent.Properties["Content"].SetValue("Hello");
       }
    }      

這裡ModelItem通過MenuActionEventArgs傳遞進來.當需要事務支援時,則需要用到ModelEditingScope對象,通過ModelItem的BeginEdit方法,當全部變更完成時,則調用ModelEditingScope的Complete方法.

這裡可以知道ModelItem是設計器對控件做出所有的變更的一個封裝,也是wpf控件設計器的一個基礎.上面介紹通過Properties索引值變更視圖,具體ModelItem其他的功能可以參考msdn相關文檔.

3.裝飾器

wpf控件設計時支援(3)

上圖是asp.net裡面GridView控件的一個設計視圖,右側的可視化面闆到了wpf控件的設計時就稱為裝飾器,那麼這個裝飾器其實就是wpf的控件,實作可視化界面對于使用者而言非常重要,可以了解該控件的常用功能,也省卻了一些開發時間.不過目前wpf内置控件似乎沒一個控件是具有這一功能的,隻能希望下版visual studio對wpf控件時做的更好了,可怕的是我們自己無法擴充内置控件的設計時,隻能等着微軟來做,最可怕的是visual studio 2010把wpf設計時部分的api全變掉,那麼這裡就全白寫了.

裝飾器功能由AdornerProvider提供,我們從内置提供的PrimarySelectionAdornerProvider類派生一個裝飾器.

wpf控件設計時支援(3)

派生類需要重寫以上兩個方法,當選中該設計器相關控件時,會調用Activate方法,離開時調用Deactivate方法.為了介紹裝飾器的使用方法.示例将盡量簡單,以介紹裝飾器功能.

一般情況下,裝飾器需要一下幾個步驟

(1)定義一個AdornerPanel對象,并把控件相關裝飾器添加到AdornerPanel中,然後将這個裝飾器容器添加到AdornerProvider的Adorners屬性中,這項操作在Activate方法中完成.

protected override void Activate(ModelItem item, DependencyObject view)
{
    Slider opacitySlider = new Slider();
    opacitySlider.Background = Brushes.Red;
    AdornerPanel myPanel = new AdornerPanel();
    myPanel.Children.Add(opacitySlider);
    Adorners.Add(myPanel);
    base.Activate(item, view);
}      

注意Activate方法也将ModelItem傳遞進來,就意味着通過裝飾器的方式也可以變更控件視圖

(2)定位裝飾器

再來看asp.net的GridView的設計時面闆,其出現在控件的右側,wpf設計時裝飾器體系允許變更裝飾器位置,上面做的第一個步驟并無法在視圖上看到控件的裝飾器,那是因為裝飾器的定位問題.這個步驟必須完成.

這項工作由AdornerPlacementCollection對象來完成,再通過AdornerPanel的靜态方法SetPlacements來設定裝飾器的位置.

我們來看一下AdornerPlacementCollection的幾個方法,初看會比較暈,無法判斷幾個方法的差別

wpf控件設計時支援(3)

以上8個方法可以看做4個方法,都是與高度寬度有關的.下面以圖來說明,我們定義的控件裝飾器是一個Slider控件.目前隻用于示範作用,它做不了什麼其他事情.

wpf控件設計時支援(3)

以上是原控件,裝飾器建立在此基礎之上,這裡說明一下上面8個方法的參數,都是一緻的,第一個是倍數因子,第二個偏移量

(1)設定容器大小

為了示範,是以裝飾器控件以紅色背景标記,以下代碼添加在Activate方法後面,SizeRelativeToContentWidth && Height方法設定裝飾器容器的大小,設定寬度和高度為控件内容高度和寬度的1倍

wpf控件設計時支援(3)

相應代碼

AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.SizeRelativeToContentWidth(1, 0);
placement.SizeRelativeToContentHeight(1, 0);

AdornerPanel.SetPlacements(opacitySlider, placement);      
http://11011.net/software/vspaste

(2)變更裝飾器位置(PositionRelativeToAdornerWidth方法),倍數參數為正數則向右移,負數則向左移

wpf控件設計時支援(3)

代碼變更為

AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.SizeRelativeToContentWidth(1, 0);
placement.SizeRelativeToContentHeight(1, 0);
placement.PositionRelativeToAdornerWidth(1, 0);
AdornerPanel.SetPlacements(opacitySlider, placement);      
http://11011.net/software/vspaste

(3)DesiredWidth和DesiredHeight,注意在設計時,控件與容器之間也有着間距,如下紅圈

wpf控件設計時支援(3)

SizeRelativeToAdornerDesiredWidth方法用于調整裝飾器的DesiredWidth.看下圖黃色紅圈的位置變更,裝飾器向右側移動一個DesiredWidth,并寬度添加一個DesiredWidth.

wpf控件設計時支援(3)
AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.SizeRelativeToContentWidth(1, 0);
placement.SizeRelativeToContentHeight(1, 0);
placement.PositionRelativeToAdornerWidth(1, 0);
placement.SizeRelativeToAdornerDesiredWidth(1, 0);
AdornerPanel.SetPlacements(opacitySlider, placement);      
http://11011.net/software/vspaste

注意PositionRelativeToAdornerWidth方法變更為PositionRelativeToContentWidth方法,那麼SizeRelativeToAdornerDesiredWidth方法隻會使裝飾器寬度變更,而位置則不做變更.如下圖

wpf控件設計時支援(3)
AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.SizeRelativeToContentWidth(1, 0);
placement.SizeRelativeToContentHeight(1, 0);
//placement.PositionRelativeToAdornerWidth(1, 0);
placement.PositionRelativeToContentWidth(1, 0);
placement.SizeRelativeToAdornerDesiredWidth(5, 0);
AdornerPanel.SetPlacements(opacitySlider, placement);      
http://11011.net/software/vspaste

一邊情況下不設定容器高度,因為控件的高度是不确定的,是以現在調整如下

wpf控件設計時支援(3)

現在最終代碼變更為

AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.SizeRelativeToContentWidth(1, 0);
placement.PositionRelativeToAdornerWidth(1, 0);
placement.SizeRelativeToAdornerDesiredHeight(1, 0);
AdornerPanel.SetPlacements(opacitySlider, placement);      

上面方法可以做多次嘗試,便于好的了解.

demo下載下傳

過年在家寫的,比較亂,沒有全部介紹完整.接着繼續寫.

繼續閱讀