之前我們講到wpf組件基類以及組件開發,現在我們圍繞之前的內容去開發一個組件。
效果圖請加群查看,在群共享里面。
做出這個呢 是比較繁瑣的。
首先要使用我們的基類
繼承基類的模板自動生成如下幾個文件:HrvColumnSeries這四個文件 HrvColumnSeries.cs是去設置組件的名稱和組件在列表上顯示的圖片,我們所做的組件不是在vs上使用,而是在我們自己開發的設計器上,所以需要這些。
代碼如下:
public class HrvColumnSeries : ComponentBase { public HrvColumnSeries() { Content = new HrvColumnSeriesShape(); } public override string TextName { get { return "HrvColumnSeries"; } } public override string IconName { get { return "HrvColumnSeries.png"; } } }
HrvColumnSeriesEvent.cs 文件 組件在使用時有相應的事件 比如一個button也有click事件 這是我們的事件 一下為例子:
public class HrvColumnSeriesEvent : ComponentEventBase { private string _Click; [Category("基礎事件")] [Description("單擊事件.")] [EventInfo("Click")] public string Click { get { return _Click; } set { if (_Click == value) return; _Click = value; OnPropertyChanged("Click"); } } public void OnClick(object sender, RoutedEventArgs e) { if (Click != null) { } } }
毫無疑問HrvColumnSeriesProperty.cs 這個就是我們的組件屬性了
因為這一章不只是組件 還有數據庫數據更新 前台動態更新。
所以屬性就比較多如下:
public class HrvColumnSeriesProperty : ComponentPropertyBase { private static string _ComputerName = ".\\sqlexpress"; [Category("數據源")] [Description("計算機名稱")] public string ComputerName { get { return _ComputerName; } set { _ComputerName = value; OnPropertyChanged("ComputerName"); } } private string _DataBaseName = "ColumnSeriesDB"; [Category("數據源")] [Description("數據庫名稱")] public string DataBaseName { get { return _DataBaseName; } set { _DataBaseName = value; OnPropertyChanged("DataBaseName"); } } private string _UID = "sa"; [Category("數據源")] [Description("用戶名")] public string UID { get { return _UID; } set { _UID = value; OnPropertyChanged("UID"); } } private string _PWD = "sa"; [Category("數據源")] [Description("密碼")] public string PWD { get { return _PWD; } set { _PWD = value; OnPropertyChanged("PWD"); } } private bool _IsWindowLogin = true; [Category("數據源")] [Description("是否為Window身份驗證")] public bool IsWindowLogin { get { return _IsWindowLogin; } set { _IsWindowLogin = value; OnPropertyChanged("IsWindowLogin"); } } private string _XTableName = "ColumnSeriesTable"; [Category("數據源")] [Description("X軸表名")] public string XTableName { get { return _XTableName; } set { _XTableName = value; OnPropertyChanged("XTableName"); } } private string _YTableName = "ColumnSeriesData"; [Category("數據源")] [Description("Y軸表名")] public string YTableName { get { return _YTableName; } set { _YTableName = value; OnPropertyChanged("YTableName"); } } private string _XTableID = "ColumnSData"; [Category("數據源")] [Description("X軸表ID")] public string XTableID { get { return _XTableID; } set { _XTableID = value; OnPropertyChanged("XTableID"); } } private string _YTableID = "ID"; [Category("數據源")] [Description("Y軸表ID")] public string YTableID { get { return _YTableID; } set { _YTableID = value; OnPropertyChanged("YTableID"); } } private string _Title = "柱狀圖"; [Category("基本")] [Description("標題")] public string Title { get { return _Title; } set { _Title = value; OnPropertyChanged("Title"); } } private string _DataColumnName = "MinData;MaxData"; [Category("數據源")] [Description("數據源列名,多數據源名稱用分號隔開")] public string DataColumnName { get { return _DataColumnName; } set { _DataColumnName = value; OnPropertyChanged("DataColumnName"); } } private string _XAxisName = "sad ada"; [Category("數據源")] [Description("軸線名稱")] public string XAxisName { get { return _XAxisName; } set { _XAxisName = value; OnPropertyChanged("XAxisName"); } } private string _ToolTipName = "asdsa($):"; [Category("數據源")] [Description("軸線提示文本")] public string ToolTipName { get { return _ToolTipName + "{field}"; } set { _ToolTipName = value; OnPropertyChanged("ToolTipName"); } } private bool _ShowValueOnBar=true ; [Category("數據源")] [Description("是否顯示數據源標注")] public bool ShowValueOnBar { get { return _ShowValueOnBar; } set { _ShowValueOnBar = value; OnPropertyChanged("ShowValueOnBar"); } } //讀取保存的數據 public override void ReadXml(System.Xml.Linq.XElement element) { base.ReadXml(element); ShowValueOnBar = element.ReadBool("ShowValueOnBar", ShowValueOnBar); ToolTipName = element.ReadString("ToolTipName"); XAxisName = element.ReadString("XAxisName"); DataColumnName = element.ReadString("DataColumnName"); Title = element.ReadString("Title"); YTableID = element.ReadString("YTableID"); XTableID = element.ReadString("XTableID"); YTableName = element.ReadString("YTableName"); XTableName = element.ReadString("XTableName"); IsWindowLogin = element.ReadBool("IsWindowLogin", IsWindowLogin); PWD = element.ReadString("PWD"); UID = element.ReadString("UID"); DataBaseName = element.ReadString("DataBaseName"); ComputerName = element.ReadString("ComputerName"); } //保存屬性 public override void WriteXml(System.Xml.XmlWriter writer) { base.WriteXml(writer); writer.WriteAttributeString("ShowValueOnBar", ShowValueOnBar.ToString()); writer.WriteAttributeString("ToolTipName", ToolTipName); writer.WriteAttributeString("XAxisName", XAxisName); writer.WriteAttributeString("DataColumnName", DataColumnName); writer.WriteAttributeString("Title", Title); writer.WriteAttributeString("YTableID", YTableID); writer.WriteAttributeString("XTableID", XTableID); writer.WriteAttributeString("YTableName", YTableName); writer.WriteAttributeString("XTableName", XTableName); writer.WriteAttributeString("IsWindowLogin", IsWindowLogin.ToString()); writer.WriteAttributeString("PWD", PWD); writer.WriteAttributeString("UID", UID); writer.WriteAttributeString("DataBaseName", DataBaseName); writer.WriteAttributeString("ComputerName", ComputerName); } }
在這里我們使用的是固定的數據格式 包括數據庫的表也是固定的。
至於這些屬性呢 數據庫名稱什么的我們可以自己去設置 唯有格式是固定的,下面的保存和讀取是當組件放在設計器上的時候有編輯完的東西需要保存,當保存了是設計器上的東西時 當然也需要保存組件的屬性了,這個保存的方法在基類。
至於HrvColumnSeriesShape.cs 我們用作將組件的屬性以及事件去綁定起來(雙向綁定) 可以保證屬性的動態變化
public class HrvColumnSeriesShape : HrvContent { public HrvColumnSeriesProperty _Property; public HrvColumnSeriesEvent _Event; public HrvColumnSeriesShape() { this.Content = new ColumnSeries(); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.ComputerNameProperty, new Binding("ComputerName") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.DataBaseNameProperty, new Binding("DataBaseName") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.UIDProperty, new Binding("UID") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.PWDProperty, new Binding("PWD") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.IsWindowLoginProperty, new Binding("IsWindowLogin") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.XTableNameProperty, new Binding("XTableName") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.YTableNameProperty, new Binding("YTableName") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.TitleProperty, new Binding("Title") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.DataColumnNameProperty, new Binding("DataColumnName") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.XAxisNameProperty, new Binding("XAxisName") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.ToolTipNameProperty, new Binding("ToolTipName") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.ShowValueOnBarProperty, new Binding("ShowValueOnBar") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.XTableIDProperty, new Binding("XTableID") { Source = this.Property, Mode = BindingMode.TwoWay }); BindingOperations.SetBinding(this.Content as ColumnSeries, ColumnSeries.YTableIDProperty, new Binding("YTableID") { Source = this.Property, Mode = BindingMode.TwoWay }); } public override ComponentPropertyBase Property { get { if (_Property == null) { _Property = new HrvColumnSeriesProperty(); } return _Property; } } public override ComponentEventBase Event { get { if (_Event == null) { _Event = new HrvColumnSeriesEvent(); } return _Event; } }
如此我們的組件基本的構成就講完了,接下來就是數據的讀取以及前端的動態更新了!
ColumnSeries.xaml.cs屬性如下:
#region 屬性 public static DependencyProperty ComputerNameProperty = DependencyProperty.Register("ComputerName", typeof(string), typeof(ColumnSeries)); public string ComputerName { get { return (string)GetValue(ComputerNameProperty); } set { SetValue(ComputerNameProperty, value); } } public static DependencyProperty DataBaseNameProperty = DependencyProperty.Register("DataBaseName", typeof(string), typeof(ColumnSeries)); public string DataBaseName { get { return (string)GetValue(DataBaseNameProperty); } set { SetValue(DataBaseNameProperty, value); } } public static DependencyProperty UIDProperty = DependencyProperty.Register("UID", typeof(string), typeof(ColumnSeries)); public string UID { get { return (string)GetValue(UIDProperty); } set { SetValue(UIDProperty, value); } } public static DependencyProperty PWDProperty = DependencyProperty.Register("PWD", typeof(string), typeof(ColumnSeries)); public string PWD { get { return (string)GetValue(PWDProperty); } set { SetValue(PWDProperty, value); } } public static DependencyProperty IsWindowLoginProperty = DependencyProperty.Register("IsWindowLogin", typeof(bool), typeof(ColumnSeries)); public bool IsWindowLogin { get { return Convert.ToBoolean(GetValue(IsWindowLoginProperty)); } set { SetValue(IsWindowLoginProperty, value); } } public static DependencyProperty XTableNameProperty = DependencyProperty.Register("XTableName", typeof(string), typeof(ColumnSeries)); public string XTableName { get { return (string)GetValue(XTableNameProperty); } set { SetValue(XTableNameProperty, value); } } public static DependencyProperty YTableNameProperty = DependencyProperty.Register("YTableName", typeof(string), typeof(ColumnSeries)); public string YTableName { get { return (string)GetValue(YTableNameProperty); } set { SetValue(YTableNameProperty, value); } } public static DependencyProperty XTableIDProperty = DependencyProperty.Register("XTableID", typeof(string), typeof(ColumnSeries)); public string XTableID { get { return (string)GetValue(XTableIDProperty); } set { SetValue(XTableIDProperty, value); } } public static DependencyProperty YTableIDProperty = DependencyProperty.Register("YTableID", typeof(string), typeof(ColumnSeries)); public string YTableID { get { return (string)GetValue(YTableIDProperty); } set { SetValue(YTableIDProperty, value); } } public static DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(ColumnSeries)); public string Title { get { return (string)GetValue(TitleProperty); } set { SetValue(TitleProperty, value); } } public static DependencyProperty DataColumnNameProperty = DependencyProperty.Register("DataColumnName", typeof(string), typeof(ColumnSeries)); public string DataColumnName { get { return (string)GetValue(DataColumnNameProperty); } set { SetValue(DataColumnNameProperty, value); } } public static DependencyProperty XAxisNameProperty = DependencyProperty.Register("XAxisName", typeof(string), typeof(ColumnSeries)); public string XAxisName { get { return (string)GetValue(XAxisNameProperty); } set { SetValue(XAxisNameProperty, value); } } public static DependencyProperty ToolTipNameProperty = DependencyProperty.Register("ToolTipName", typeof(string), typeof(ColumnSeries)); public string ToolTipName { get { return (string)GetValue(ToolTipNameProperty); } set { SetValue(ToolTipNameProperty, value); } } public static DependencyProperty ShowValueOnBarProperty = DependencyProperty.Register("ShowValueOnBar", typeof(bool), typeof(ColumnSeries)); public bool ShowValueOnBar { get { return Convert.ToBoolean(GetValue(ShowValueOnBarProperty)); } set { SetValue(ShowValueOnBarProperty, value); } } private DataSet _Data; public DataSet Data { get { return _Data; } set { _Data = value; } } #endregion
為什么定義這種呢? 這是為了將組件的屬性和數據讀取這一塊綁定 為了保證在綁定之后屬性的動態變化,所以我們使用了依賴項屬性。
關於監聽數據庫值得改變去動態顯示數據(SqlDependency)這部分內容在
WPF非輪詢方式更新數據庫變化SqlDependency(數據庫修改前台自動更新)
這一章節會有詳細的講解,以下內容 看的懂看一下 覺得繁瑣的 就不看了。
數據的讀取:
private string con; private string[] dataColumn; private string sql; #region 數據庫連接 public void GetDataSet() { SqlConnection connection = new SqlConnection(con); Data = new DataSet(); SqlCommand command = new SqlCommand(sql, connection); command.CommandType = CommandType.Text; connection.Open(); SqlDependency dependency = new SqlDependency(command); dependency.OnChange += new OnChangeEventHandler(dependency_OnChange); DataTable dt = new DataTable(); SqlDataReader sda = command.ExecuteReader(); foreach (string data in dataColumn) { DataColumn dc = new DataColumn(data); dt.Columns.Add(dc); } while (sda.Read()) { DataRow row = dt.NewRow(); foreach (string data in dataColumn) { row[data] = sda[data].ToString(); } dt.Rows.Add(row); } Data.Tables.Add(dt); sda.Close(); //} //catch (Exception ex) //{ //} } private void dependency_OnChange(object sender, SqlNotificationEventArgs e) { DrawChart(); } #endregion string CName; string DName; string ID; string PassWord; bool windowLogin; string XTName; string YTName; string DCName; string XAName; string XTID; string YTID; protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { base.OnPropertyChanged(e); if (CName != null && DName != null && ID != null && PassWord != null && XTName != null && YTName != null && DCName != null && XAName != null && XTID != null && YTID != null) if (CName != ComputerName || DName != DataBaseName || ID != UID || PassWord != PWD || windowLogin != IsWindowLogin || XTName != XTableName || YTName != YTableName || DCName != DataColumnName || XAName != XAxisName || XTID != XTableID || YTID != YTableID) DrawChart(); CName = ComputerName; DName = DataBaseName; ID = UID; PassWord = PWD; windowLogin = IsWindowLogin; XTName = XTableName; YTName = YTableName; DCName = DataColumnName; XAName = XAxisName; XTID = XTableID; YTID = YTableID; } #region 顯示數據 private void DrawChart() { this.Dispatcher.Invoke(new System.Action(() => { con = @"server=" + ComputerName + @";database=" + DataBaseName + ";uid=" + UID + ";pwd=" + PWD + ";Integrated Security=" + IsWindowLogin; dataColumn = (DataColumnName + ";Name").Split(';'); sql = "SELECT "; foreach (string data in dataColumn) { sql += data + ","; } sql = sql.Remove(sql.Length - 1); sql += " FROM [dbo].[" + XTableName + "] INNER JOIN [dbo].[" + YTableName + "] ON " + YTableName + "." + YTableID + "=" + XTableName + "." + XTableID; try { SqlDependency.Start(con); GetDataSet(); } catch(Exception ex) { MessageBox.Show(ex.Message.ToString(),"數據連接錯誤!"); } chart2.Reset(); Binding titleBind = new Binding { Source = this, Path = new PropertyPath("Title") }; BindingOperations.SetBinding(this.chart2, BarChart.TitleProperty, titleBind); string[] column = new string[dataColumn.Length - 1]; for (int i = 0; i < dataColumn.Length - 1; i++) { column[i] = dataColumn[i]; } if (column == null) return; foreach (string data in column) { chart2.ValueField.Add(data); } Binding ToolTipNameBind = new Binding { Source = this, Path = new PropertyPath("ToolTipName") }; BindingOperations.SetBinding(this.chart2, BarChart.ToolTipTextProperty, ToolTipNameBind); chart2.XAxisText = XAxisName; chart2.XAxisField = "Name"; Binding showBarBind = new Binding { Source = this, Path = new PropertyPath("ShowValueOnBar") }; BindingOperations.SetBinding(this.chart2, BarChart.ShowValueOnBarsProperty, showBarBind); if (Data == null) return; Binding DataSourceBind = new Binding { Source = this, Path = new PropertyPath("Data") }; BindingOperations.SetBinding(this.chart2, BarChart.DataSourceProperty, DataSourceBind); chart2.Generate(); })); } #endregion private void UserControl_Loaded(object sender, RoutedEventArgs e) { DrawChart(); } private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e) { chart2.Width = 450; chart2.Height = 300; }
OnPropertyChanged解釋下這個 這個是在屬性更改的時候發生,因為數據庫的連接字符串是無法做動態更新的 比如更改完數據庫名稱之后馬上要自動去連接那個數據庫之前的方法就無法實現了,所以我們使用了這個事件 當數據庫名稱、表名、列明等發生改變的時候去重新獲取數據。
目前就講這些,至於柱狀圖下章繼續,柱狀圖更加繁瑣。
需要組件基類模板的,想要柱狀圖源碼的請加群:
WPF、AE技術交流群:94234450
不管你遇到了什么問題,我們都不會讓你獨自去面對!