天天看點

WPF中如何使用C#建立DataTemplate資料模版

WPF中如何使用C#建立DataTemplate資料模版

 看到部落格園有篇文章談到“使用C#程式設計的方式建立DataTemplate資料模闆”(原文位址), 部落客的做法是建立一個FrameworkElementFactory對象,設定好後将其設定為DataTemplate對象的VisualTree屬 性。我認為此方法有待商榷,蓋因查閱MSDN,發現FrameworkElementFactory類的介紹頁面上有一段備注:

  (http://msdn.microsoft.com/zh-cn/library/system.windows.frameworkelementfactory.aspx)

  備注:通過此類以程式設計方式建立模闆這種方式已被否決,這些模闆是 FrameworkTemplate(如 ControlTemplate 或 DataTemplate)的子類;使用此類建立模闆時,并非所有模闆功能都可用。以程式設計方式建立模闆的推薦方式是:使用 XamlReader 類的 Load 方法從字元串或記憶體流中加載 XAML。

  是以,正确的做法似乎是程式設計建立一段XAML代碼并且使用XamlReader類的Load方法将其構造成為執行個體對象。下面代碼展示了這一做法(為了示範,資料綁定操作全部由C#代碼而不是xaml完成):

  下面代碼完成一個小程式,該程式可以輸入名字和昵稱,将之加入到ListBox清單中,如果選中ListBox某一項,輸入框内容會實時更新,也可以實時修改名字和昵稱。首先使用XAML描述出程式界面:

MainWindow.xaml:

  1.     <label>姓名</label> 
  2.     <label>昵稱</label> 
  3. <button>增加</button> 

  下面将TextBox、ListBox的資料源全部綁定到我們自己的資料結構上,先定義一個NickName類,實作INotifyPropertyChanged接口:

MainWindow.xaml.cs:

  1. public class NickName: INotifyPropertyChanged  
  2. {  
  3.     public NickName() : this( “Name”, “Nick” ) { }  
  4.     public NickName( string name, string nick )  
  5.     {  
  6.         namename_ = name; nicknick_ = nick;  
  7.     }  
  8.     public event PropertyChangedEventHandler PropertyChanged;  
  9.     private void FireEvent( string propertyName )  
  10.     {  
  11.         if( PropertyChanged != null )  
  12.         PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );  
  13.     }  
  14.     private string name_;  
  15.     public string Name  
  16.     {  
  17.         get { return name_; }  
  18.         set{  
  19.             if( name_ == value ) return;  
  20.             name_ = value;  
  21.             FireEvent( “Name” );  
  22.         }  
  23.     }  
  24.     private string nick_;  
  25.     public string Nick  
  26.     {  
  27.         get { return nick_; }  
  28.         set{  
  29.             if( nick_ == value ) return;  
  30.             nick_ = value;  
  31.             FireEvent( “Nick” );  
  32.         }  
  33.     }  

  下面代碼在記憶體中使用XAML定義了一個DataTemplate,并将之執行個體化,完成了ListBox的資料綁定操作:

MainWindow.xaml.cs:

  1. public partial class MainWindow: Window  
  2. {  
  3.     //ObservableCollection<>集合實作了INotifyCollectionChanged接口  
  4.     public ObservableCollection nickNames_ = new ObservableCollection();  
  5.     public MainWindow()  
  6.     {  
  7.         InitializeComponent();  
  8.         DoDataBinding();  
  9.         //點選“增加”按鈕時将TextBox中的内容增加到nickNames_容器中  
  10.         //由于ListBox已經綁定到nickNames_,這将導緻ListBox顯示内容的更新  
  11.         btnAdd_.Click += ( o, e ) => {  
  12.             nickNames_.Add( new NickName() );  
  13.         };  
  14.     }  
  15.     private void DoDataBinding()  
  16.     {  
  17.         //設定總體的資料上下文,它将影響DockPanel裡面所有控件  
  18.         dockPanel_.DataContext = nickNames_;  
  19.         //将ListBox綁定到nickNames_,并設定同步更新目前Item屬性  
  20.         lstBox_.SetBinding( ListBox.ItemsSourceProperty, string.Empty );  
  21.         lstBox_.IsSynchronizedWithCurrentItem = true;  
  22.         //記憶體中動态生成一個XAML,描述了一個DataTemplate  
  23.         XNamespace ns = “http://schemas.microsoft.com/winfx/2006/xaml/presentation”;  
  24.         XElement xDataTemplate =  
  25.             new XElement( ns + “DataTemplate”, new XAttribute( “xmlns”, “http://schemas.microsoft.com/winfx/2006/xaml/presentation” ),  
  26.                 new XElement( ns + “TextBlock”,  
  27.                     new XElement( ns + “TextBlock”, new XAttribute( “Width”, “100″ ), new XAttribute( “Text”, “{Binding Path=Name}” ) ),  
  28.                     new XElement( ns + “TextBlock”, new XAttribute( “Width”, “100″ ), new XAttribute( “Text”, “{Binding Path=Nick}” ) )  
  29.                 )  
  30.             );  
  31.         //将記憶體中的XAML執行個體化成為DataTemplate對象,并指派給  
  32.         //ListBox的ItemTemplate屬性,完成資料綁定  
  33.         XmlReader xr = xDataTemplate.CreateReader();  
  34.         DataTemplate dataTemplate = XamlReader.Load( xr ) as DataTemplate;  
  35.         lstBox_.ItemTemplate = dataTemplate;  
  36.         //将兩個TextBox分别綁定到目前Item的Name和Nick屬性上  
  37.         txtBoxName_.SetBinding( TextBox.TextProperty, “Name” );  
  38.         txtBoxNick_.SetBinding( TextBox.TextProperty, “Nick” );  
  39.     }  

  通過上述代碼,已經成功使用C#代碼建立了DataTemplate資料模闆,并完成了這個小程式:

  由于剛開始學習WPF,代碼中難免有不當之處,懇請牛人指正。

By liuxiaobo

【本文首發于: 搜尋研發部官方部落格】 http://stblog.baidu-tech.com/?p=100 【 關注百度技術沙龍】

轉載于:https://blog.51cto.com/baidutech/743790

c#