2013-02-19 97 views
12

WPF自定義控件WPF自定義控件構造,觸發器和事件

我想構建一個新的自定義控件。我發現很少的教程給了我一些關於如何實現這一點的線索。據我所知,創建一個新的自定義控件總是通過擴展當前控件來完成的,甚至可以從層次結構的基本級別擴展控件,例如,甚至可以擴展:

  • 的UIElement
  • FrameworkElement的
  • 控制
  • ContentControl中
  • HeaderedContentControl
  • 的ItemsControl
  • 選擇
  • RangeBase

寫在下面的教程:http://wpftutorial.net/HowToCreateACustomControl.html

所以,我也跟着教程和創造型自定義控件庫的一個新的項目,得到了我的通用的.xaml和我的代碼背後。到現在爲止還挺好。

有三種類型或類別的事件我可以區分。

  1. 活動是由窗口(或容器),將用我的控制耗材:這些都是我想暴露於外的事件。如何寫這些?

  2. 與控制本身相關且未暴露於外部的事件;例如, ,如果鼠標超過了我的控制範圍,我想對此作出反應 。我能做到的是,在XAML:

    <ControlTemplate.Triggers> 
        <Trigger Property="IsMouseOver" Value="true"> 
        <Setter Property="Fill" TargetName="LeftTraingularIndicator"> 
         <Setter.Value> 
         <SolidColorBrush Color="Yellow" /> 
         </Setter.Value> 
        </Setter> 
        </Trigger> 
    </ControlTemplate.Triggers> 
    

假設淡然的我有填充屬性在我 ControlTemplate中被命名爲X的元素:

問題NAME = 「LeftTraingularIndicator」:

現在我想在我的XAML中對IsMouseDown做出反應。我怎麼做? 沒有「IsMouseDown」觸發器。此外,如果我想讓 對後面的代碼做出反應呢?甚至更進一步如果我想要 將LeftTraingularIndicator「Fill」從後面的代碼改成什麼?

  • 該相關如果我想在反應「LeftTraigularIndicator」的 爲「IsMouseOver」什麼子元件,其是視覺 施工我的ControlTemplate的一部分,例如,在活動XAML /甚至在代碼隱藏? 也許甚至兩個。
  • 我現在正在嘗試2天...感覺我錯過了我對事物工作原理的理解。沒有找到任何深入解釋這些問題的教程。

    我希望看到我在這裏提出的每個問題的幾行例子。

    謝謝。

    回答

    8

    經過廣泛的研究...

    1)暴露事件外... 簡單,如果你是從其它類暴露。

    public delegate void myDelegate(int someValue); 
    public event myDelegate myEvent; 
    
    在你的代碼

    和地方:

    if(myEvent!=null) 
        myEvent(5); 
    

    沒有在該部分新。

    2)從後面的代碼創建實例構造

    public MyCustomControl() 
    { 
        MouseMove += MyCustomControl_MouseMove; 
    } 
    
    
    void MyCustomControl_MouseMove(object sender, MouseEventArgs e) 
    { 
        //now you can react to the movement of the mouse. 
        //if for example I want to address an element, let's say a rectangle: 
    
        var ele = (Rectangle)Template.FindName("myRect",this); 
        ele.Fill=myNewBrush; 
    
        // provided that we have an element named "myRect" (x:name="myRect") in 
        // the generic.xaml style->Control Template-> which corresponds to that name. 
    
    } 
    

    3)不推薦 - 因爲它屬於的用戶控件,而不是定製控件的範圍。 自定義控件是「原子」,用戶控件更適合於組合控件的目的 。

    ,但並非不可能......

    var myButton = (Button)Template.FindName("myButton",this); 
    myButton.OnMouseMove += .... 
    

    只需記住:應該在被稱爲

    • 任何代碼隱藏必須命名。

    • 您的xaml應該不知道背後的代碼是什麼。 (不包括! - 請繼續閱讀)

    • 當您設計您的XAML時,代碼隱藏中應該知道的部分必須使用正確的名稱。

    我真的希望這將幫助其他人誰得到了「牆」,試圖發展 自己的定製控件時。

    +0

    你唯一不能與用戶控件做將它們用作窗口基類。這使得編寫窗口模板非常痛苦。 – rookie1024 2016-07-01 17:35:09

    +0

    對於3,如果您在Generic.xaml中應用了模板,則可以通過重寫'OnApplyTemplate()'來獲取任何命名的部分,因爲只有包含部分的模板已經設置,纔會運行該模板。 – Lauraducky 2017-12-20 00:02:40

    6

    如果我正確理解你的問題 - 下面是我的解釋。

    WPF事件系統提供3種類型的事件: 1.鼓泡 2.隧道 3.直接

    如果事件被定義(intrensically)作爲冒泡事件,則該事件被從冒泡來源到它的容器。例如:如果一個網格有兩個按鈕 - Rectangle1和Rectangle2,那麼點擊這些矩形就會冒泡到網格中。隧道是相反的,事件從父母到孩子隧道。

    有直接事件是非常特殊的 - 它們只適用於事件沒有意義的情況下冒泡。例如,在上面的場景中,在任何一個矩形上冒泡MouseOver事件都沒有任何意義 - 因爲每當鼠標進入矩形時,事件就會冒泡到網格 - 這是人們可能期望的。

    你的問題:

    活動是由窗口(或容器),將用我的控制耗材:這些都是我想暴露於外。該事件怎麼寫的?

    你基本上需要寫一個冒泡事件。下面是從MSDN的例子寫上一個按鈕冒泡敲擊事件(我還沒有嘗試過我自己)Routed event example

    public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
    "Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButtonSimple)); 
    

    你的問題:

    問題:現在我想反應我XAML到IsMouseDown ...我該怎麼做?沒有「IsMouseDown」觸發器..更多更多如果我想對後面的代碼做出反應,該怎麼辦?甚至更進一步怎麼樣,如果我想從背後的代碼改變LeftTraingularIndicator「填充」?

    順便說一句,你似乎有一些與事件和觸發器混淆(因爲我看你可以交替使用它們)。儘管它們是相關的,但它們並不相同。

    回到你的問題 - WPF允許屬性更改的觸發器 - 這就是本質上你所關注的 - IsMouseOver在這種情況下。但缺少的是該屬性是ControlTemplate的目標(我不知道它是什麼)。我只是推斷ControlTemplate的目標是一個矩形。在這種情況下,它沒有「IsMouseDown」屬性來掛鉤屬性觸發器。這就是你無法找到它的原因。你必須寫一個AttachedEvent其他選項(它們是非常相似的AttachedProperties)..整體另一個話題:(

    我希望盡我所能:)

    +0

    我喜歡你的答案,因爲它進一步闡明瞭關於事件方向的主題espicailly,但是當試圖構建新的自定義控件時,我試圖關注XAML和代碼隱藏之間的聯繫。當你創建帶有美麗形狀的XAML時,很大的一面是,而2分鐘後你開始意識到你無法爲這些項目提供功能,我相信很多人進入了這個牆。命名的部分是唯一將功能鏈接到XAML的東西,但它並不直觀,因爲沒有人希望XAML仍然需要知道背後的代碼。 – 2013-02-20 06:31:23