wpf custom control
最近在做WPF,記錄一下自定義控件的制作過程,源碼請點擊:源碼。
1、目標
實現一個如圖所示的可增減的數字框:
2、先畫Template
可以在Generic.xaml中畫,也可以用MergedDictionary連接到其他xaml中。
<ResourceDictionary.MergedDictionaries><ResourceDictionary Source="/CustomControls;component/Themes/UpDownNumeric.xaml"/> </ResourceDictionary.MergedDictionaries>3、再實現UpDownNumeric
基類選擇Control,也可以根據目標就近選擇基類(比如ItemsControl、HeaderedContentControl之類的)。想好要暴露哪些屬性、事件和命令,比如在這個例子里,只要暴露1個ValueProperty、2個CommandProperty(只貼增的,減類似不重復貼了)、和1個ValueChanged事件即可。
public static readonly DependencyProperty ValueProperty =DependencyProperty.Register("Value", typeof(int), typeof(UpDownNumeric),new PropertyMetadata(new PropertyChangedCallback(OnValueChanged)));public static readonly DependencyProperty UpCommandProperty =DependencyProperty.Register("UpCommand", typeof(ICommand), typeof(UpDownNumeric));public static readonly RoutedEvent ValueChangedEvent =EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble,typeof(RoutedPropertyChangedEventHandler<int>), typeof(UpDownNumeric));再把這些屬性包裝成我們熟悉的.net的屬性和事件,基于DelegateCommand實現命令、和觸發ValueChanged的事件即可。
4、坑1:如果邏輯里的屬性與控件的屬性類型不匹配,要實現相應的IValueConverter
在這個例子里, 我把int型的Value綁定到TextBox的Text,int到string不能直接綁定,因此要實現一個Int2StringConverter,并在綁定時指定。否則不會顯示值。
<TextBox Text="{TemplateBinding Value, Converter={StaticResource Int2StringConverter}}"/>5、坑2:Image.Source的Pack Uri路徑
這個路徑如果沒寫對,要么編譯不通過,要么雖然編譯成功但運行的時候顯示不出來。這里有幾點關鍵:
5.1、右鍵圖片->屬性->生成操作->務必選擇“資源”(Resource)
請不要選擇“內容”或“嵌入的資源”,也不要將圖片添加到“項目資源”中?!皬椭频捷敵瞿夸洝边x擇“不復制”。我分別嘗試了這幾種生成方式,如下:
資源:生成到.g.resources
內容:不生成到dll里
嵌入的資源:生成到Resources文件夾中,與.g.resources同級
項目資源:生成到*.Properties.Resources.resources
5.2、Pack Uri路徑
網上到處是copy來的一大堆理論,看的暈。我試下來,在vs的Image.Source屬性窗口里選,由vs自動生成的路徑總是OK的,如下:
手動輸入容易出錯。只要生成為“資源”,下面3種寫法都是正確的。
絕對路徑:pack:///application:,,,/CustomControls;component/Resources/up.png
絕對路徑-縮寫版:/CustomControls;component/Resources/up.png
相對路徑:../Resources/up.png
6、坑3:Template與控件Logic務必分離
這里的分離是指:Logic不應知道具體的控件名,Logic只暴露依賴屬性(包括屬性+命令),Template負責綁定屬性。這種分離的好處是:如果用戶不喜歡你的Template,自己再定制一個,只需綁定到同樣的屬性+命令,即可實現控件的行為。否則用戶就無法改寫Template了。
6.1、錯誤的實現方式
private Button upBtn; public override void OnApplyTemplate(){upBtn = (Button)this.Template.FindName("btnUp", this);upBtn.Click = btn_Click; }這樣寫,就把Logic和Template綁死了。
6.2、正確的實現方式
//后臺定義UpCommandProperty,實現為DelegateCommand或RoutedCommand,前臺Template去綁定 public static readonly DependencyProperty UpCommandProperty =DependencyProperty.Register("UpCommand", typeof(ICommand), typeof(UpDownNumeric));<Button Command="{TemplateBinding UpCommand}"/>轉載于:https://www.cnblogs.com/AlexanderYao/p/4711019.html
總結
以上是生活随笔為你收集整理的wpf custom control的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Codeforces Round #Pi
- 下一篇: Error when loading t