當前位置:成語大全網 - 書法字典 - 如何向WPF的自定義控件添加單擊事件

如何向WPF的自定義控件添加單擊事件

首先,向控件添加屬性,然後向其添加事件,最後添加命令。具體步驟如下:

1,為控件添加壹個屬性(DependencyProperty)。

如下面的代碼所示:

公共?靜電?只讀?DependencyProperty?時間屬性?=?

DependencyProperty註冊(“時間”,?typeof(日期時間),type of(ClockUserCtrl),

新的?FrameworkPropertyMetadata(日期時間。現在新的?PropertyChangedCallback(TimePropertyChangedCallback)));我們添加到壹個控件(或任何WPF類)的依賴屬性都是“公共的”、“靜態的”和“只讀的”,它們的命名方法是“屬性名+屬性”,這是依賴屬性不可更改的書寫方法。對於依賴屬性的註冊,我們可以調用DependencyProperty。Register()方法在聲明屬性時進行註冊。您也可以在其靜態構造函數中註冊它。DependencyProperty屬性的參數。上面的Register方法有:屬性名(與聲明的依賴屬性名“XXXProperty”相比,此屬性名僅缺少後綴“property”,否則將在運行時報告異常)、屬性的數據類型、屬性所有者的類型和元數據。

關於參數中傳遞的元數據:如果是普通類,則應該傳遞PropertyMetadata,如果是FrameworkElement,則可以傳遞FrameworkPropertyMetadata。其中,可以在FrameworkPropertyMetadata中進行壹些標記,以指示當屬性更改時控件應如何反應。例如,屬性的更改會影響控件的繪制,因此屬性的元數據應該這樣寫:?新的

framework property metadata(defaule value,

FrameworkPropertyMetadataOptions。affects render);這樣,當屬性更改時,系統將考慮重新繪制控件。此外,元數據還保護了很多內容,例如默認值、數據驗證、數據更改時的回調函數、是否參與屬性“繼承”等等。

然後,我們將依賴屬性包裝成壹個公共屬性:

【描述(“獲取或設置當前日期和時間“)】

【類別(“常見?屬性“)】

公共?日期時間?時間

{

得到

{

回歸?(日期時間)這個。GetValue(time property);

}

設置

{

這個。SetValue(time property,值);

}

}GetValue和SetValue方法來自DependencyObject類,用於獲取或設置該類的屬性值。

註意:當將依賴屬性包裝成普通屬性時,除了在get和set塊中逐步調用GetValue和SetValue方法之外,不要執行任何操作。以下代碼不合適:

?【描述(“獲取或設置當前日期和時間“)】

【類別(“常見?屬性“)】

公共?日期時間?時間

{

得到

{

回歸?(日期時間)這個。GetValue(time property);

}

設置

{

這個。SetValue(time property,值);

這個。OnTimeUpdated(值);//錯誤

}

}在過去,這可能是許多人的常用編寫方法,但在WPF中,這種編寫方法存在潛在的錯誤,原因如下:我們知道從DependencyObject繼承的類具有GetValue和SetValue方法來獲取或設置屬性值,那麽我們為什麽不直接使用此方法來獲取或設置屬性值,而是將其打包為壹個公共的。凈資產?其實這兩種方法在這裏都是可以的,只是它更符合的習慣。NET開發人員將它們打包成普通的。NET屬性,這更像是JAVA開發人員使用GetValue和SetValue的習慣,但XAML在執行時似乎與JAVA開發人員相同,它不會調用。NET屬性,而是直接使用GetValue或SetValue方法,因此,我們在get塊和set塊中編寫的其他代碼根本不會被XAML執行。因此,就上述時間屬性而言,當C#(或其他)調用該屬性時不會出現問題,但當該屬性在XAML使用時(如在XAML對該屬性進行數據綁定等)會出現問題。),這個。其set塊中的OnTimeUpdated(值);該語句將不被執行。

然後,當時間屬性改變時,妳真的需要調用這個。OnTimeUpdated(值);語句(因為它將引發壹個時間被更新的事件),或者對傳遞的依賴屬性元數據大驚小怪:

新的FrameworkPropertyMetadata(日期時間。現在,新建PropertyChangeCallback(TimePropertyChangeCallback)),我們為屬性的更改指定壹個回調函數,該回調函數將在屬性更改時執行:

私人的?靜電?虛空?TimePropertyChangedCallback(dependency object?發件人?DependencyPropertyChangedEventArgs?arg)

{

如果?(發件人?!=?null?& amp& amp?寄件人?是嗎?ClockUserCtrl)

{

ClockUserCtrl?時鐘?=?寄件人?作為什麽?ClockUserCtrl

時鐘。on time updated((DateTime)arg。舊值?(日期時間)參數。new value);

}

}2、為控件添加壹個事件(RoutedEvent)。

添加路由事件的方法類似於添加相關屬性的方法:

公共?靜電?只讀?RoutedEvent?TimeUpdatedEvent?=?

事件管理器。RegisterRoutedEvent(“time updated“,

路由策略。泡泡?type of(RoutedPropertyChangedEventHandler & lt;日期時間& gt),?type of(ClockUserCtrl);與支持方法eventmanager對應的參數。registerroutedevent()是:事件名稱、事件循環的方式(向上循環、向下循環或不循環)、事件對應的EventHandler的類型、事件所有者的類型。

然後將事件包裝成普通事件。網絡事件:

?【描述(“在日期或時間更新後發生”)】

公共?事件?RoutedPropertyChangedEventHandler & lt;日期時間& gt?時間更新

{

增加

{

這個。AddHandler(TimeUpdatedEvent,?值);

}

去除

{

這個。remove handler(TimeUpdatedEvent,?值);

}

}請註意,與依賴屬性壹樣,不要在add和remove塊中添加AddHandler和RemoveHandler之外的代碼。

題外話,事件參數中的e.Handled=true不是為了終止事件的循環,它只是為了標記事件,因此默認情況下,當標記為true時,不會調用那些事件處理程序。要註冊標記為true的事件的處理方法並執行它,請使用AddHandler方法,並將最後壹個參數handlerEventsToo設置為true,如下所示:

this.myInkCanvas.AddHandler(

墨水畫布。MouseLeftButtonDownEvent,

新的?MouseButtonEventHandler(

myInkCanvas _ MouseLeftButtonDown),

真);

私人的?虛空?myInkCanvas _ MouseLeftButtonDown(

對象?發件人?MouseButtonEventArgs?e)

{

//做?某物

}然後編寫常用的OnXXX方法:

受保護?虛擬的?虛空?OnTimeUpdated(日期時間?舊值?日期時間?新價值)

{

RoutedPropertyChangedEventArgs & lt。日期時間& gt?arg?=?

新的?RoutedPropertyChangedEventArgs & lt。日期時間& gt(舊值,?newValue,TimeUpdatedEvent);

這個。RaiseEvent(arg);

}3、為控件添加命令。

向自定義控件添加像WPF內置控件這樣的命令是壹件好事(事實上,這也是減少CustomControl中界面和後臺邏輯之間耦合的壹種方法,這將在本系列文章的下壹篇文章中詳細討論)。

WPF內置了兩種類型的命令:路由命令和路由命令。後者有壹個附加的文本屬性,用於自動本地化與界面上的命令相對應的文本。有關更多信息,請參考WPF的命令和命令綁定(I)和WPF的命令和命令綁定(II)。

這裏我們定義了壹個命令,它的功能是通過控件的聲音來告訴時間。首先,我們定義壹個命令:

公共?靜電?只讀?RoutedUICommand?SpeakCommand?=?新的?routed uicommand(“Speak“,?“說吧”,?type of(ClockUserCtrl);

這些參數被命名為顯示名稱、命令名稱和命令所有者類型。

然後在控件的靜態函數中定義壹個命令綁定,該函數定義了命令的具體細節:對應的命令是什麽?它能完成什麽樣的功能,能在當前環境中執行嗎?

?命令綁定?命令綁定?=?新的?命令綁定(SpeakCommand,?新的?ExecutedRoutedEventHandler(execute speak),

新的?CanExecuteRoutedEventHandler(canexecutespace));

私人的?靜電?虛空?ExecuteSpeak(對象?發件人?ExecutedRoutedEventArgs?arg)

{

ClockUserCtrl?時鐘?=?寄件人?作為什麽?ClockUserCtrl

如果?(時鐘?!=?空)

{

時鐘。speak thetime();

}

}

私人的?靜電?虛空?canexecutespace(object?發件人?CanExecuteRoutedEventArgs?arg)

{

ClockUserCtrl?時鐘?=?寄件人?作為什麽?ClockUserCtrl

arg。能執行嗎?=?(時鐘?!=?null);

}CanExecuteRoutedEventArgs的} CanExecute屬性用於表示當前命令是否可用,也就是說系統會不斷查看命令和命令的對象,並根據您提供的條件判斷當前命令是否可用。例如,文本框的狀態變為“只讀”後,其“粘貼”命令將不可用,作用於文本框的粘貼按鈕將自動禁用,否則將啟用。

新的ExecuteDrouteDeventhandler(execute speak)委托指定了執行命令時要完成的任務,這是通過回調ExceteSpeak函數來實現的。

私人的?靜電?虛空?ExecuteSpeak(對象?發件人?ExecutedRoutedEventArgs?arg)

{

ClockUserCtrl?時鐘?=?寄件人?作為什麽?ClockUserCtrl

如果?(時鐘?!=?空)

{

時鐘。speak thetime();

}

}

私人的?虛空?說話時間()

{

日期時間?本地時間?=?這個。time . ToLocalTime();

弦樂?textToSpeak?=?“現在,“+?本地時間。ToShortDateString()?+","+?本地時間。ToShortTimeString()?+“,星期“?+?(整數)本地時間。DayOfWeek

this . speecher . speak async(textToSpeak);

}我們還可以為命令添加快捷鍵,這是通過InputBinding實現的,它將命令與命令的快捷鍵相關聯,例如:

輸入綁定?輸入綁定?=?新的?input binding(speak command,新的?鼠標手勢(鼠標動作。left click);

CommandManager。RegisterClassInputBinding(type of(clock user ctrl),?input binding);

這樣當我們用鼠標點擊控件時,就會觸發控件的Speak命令,從而調用SpeakTheTime函數進行語音播報。

快捷鍵可以由MouseGesture或KeyGesture定義。