功能描述:
ComboBox+TreeView實現的用戶控件,設置數據源後,可以遞歸加載數據,支持雙向綁定
控件截圖:
XAML界面設計:
<UserControl x:Class="ChuanyeOA.CustomControls.ComboBoxTree" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="30" d:DesignWidth="300" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <Grid x:Name="LayoutRoot"> <ComboBox Height="23" Name="cbMain" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" DropDownOpened="cbMain_DropDownOpened" DropDownClosed="cbMain_DropDownClosed"> <ComboBoxItem x:Name="cbItemTreeView"> <ComboBoxItem.Content> <sdk:TreeView Name="tvList" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SelectedItemChanged="tvList_SelectedItemChanged" /> </ComboBoxItem.Content> </ComboBoxItem> <ComboBoxItem x:Name="cbItemDisplay" > </ComboBoxItem> </ComboBox> </Grid> </UserControl>
後臺CS代碼:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Data; using System.Collections; using System.Reflection; /******************************** * 創建人:劉躍飛 * 創建時間:2010-09-21 * 功能描述:ComboBox+TreeView實現的用戶控件,主要實現選擇TreeView中的項做爲ComboBox的項的功能 * 屬性描述:此控件包含以下幾個屬性 * 1.ItemsSource:控件要綁定的數據源 * 2.SelectedValuePath:選中的值的屬性 * 3.DisplayMemberPath:獲取或設置爲每個數據項要顯示的屬性的名稱 * 4.SelectedItem 當前選擇的項 * 5.SelectedValue 當前選擇的值 * 6.IsRecursionEnabled 設置是否啓用遞歸加載數據源中的項 。需要設置ChildName和ParentName兩個屬性 * 7.ChildMemberPath 遞歸加載數據源時,實體中的子級屬性項 * 8. ParentMemberPath 遞歸加載數據源時,實體中的父級屬性項 * 9.IsExpandAll 設置TreeView打開時是全部打開狀態還是收縮狀態 默認爲True打開狀態 * * 使用方法: * 注意事項:本控件設計尚不完善,【ItemsSource】屬性需要在最後設置,否則,將提示錯誤 * 1.界面上直接設置,例如: * <myControl:ComboBoxTree SelectedValue="{Binding DepartmentID, Mode=TwoWay}" DisplayMemberPath="DepartName" SelectedValuePath="ID" IsRecursionEnabled="True" ChildMemberPath="ID" ParentMemberPath="ParentID" ItemsSource="{Binding Data, Source={StaticResource a_DepartmentDomainDataSource}}"> * 2.在後臺代碼中直接設置,例如: * comboBoxTree1.DisplayMemberPath = "Name"; * comboBoxTree1.SelectedValuePath = "ID"; * comboBoxTree1.ChildMemberPath = "ID"; * comboBoxTree1.ParentMemberPath = "ParentID"; * comboBoxTree1.IsRecursionEnabled = true; * comboBoxTree1.ItemSource = MyControls.DepartmentInfo.GetDepartment().AsEnumerable(); * 3.如果啓用遞歸加載,父級ID爲【0】的項,將作爲根節點加載,如果沒有父級ID爲【0】的項,將無法進行加載 * 4.此控件用到了TreeView的ExpandAll擴展方法,需要添加【System.Windows.Controls.Toolkit】類庫的引用,否則將提示找不到此方法 * ***********************************/ namespace ChuanyeOA.CustomControls { public partial class ComboBoxTree : UserControl { public ComboBoxTree() { InitializeComponent(); this.LayoutUpdated += new EventHandler(ComboBoxTree_LayoutUpdated); } void ComboBoxTree_LayoutUpdated(object sender, EventArgs e) { if (this.IsExpandAll) { //--展開所有節點 tvList.ExpandAll(); } } #region ItemSource 設置或獲得綁定的數據源(屬性) public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(ComboBoxTree), new PropertyMetadata(new PropertyChangedCallback(ItemsSourcePropertyChangedCallBack))); /// <summary> /// 數據源 /// </summary> public IEnumerable ItemsSource { get { return (IEnumerable)this.GetValue(ItemsSourceProperty); } set { this.SetValue(ItemsSourceProperty, value); } } //--屬性更改的回調事件 public static void ItemsSourcePropertyChangedCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs args) { if (sender != null) { ComboBoxTree comboBoxTree = sender as ComboBoxTree; if (comboBoxTree.IsRecursionEnabled == false) { // 以列表的方式加載數據 comboBoxTree.LoadTreeViewDataWithList(); } else { //以遞歸的方式加載數據 comboBoxTree.LoadTreeViewDataWithRecursion(); } } } #endregion #region SelectedValuePath 選中的值的屬性 public static readonly DependencyProperty SelectedValuePathProperty = DependencyProperty.Register("SelectedValuePath", typeof(string), typeof(ComboBoxTree), null); /// <summary> /// 獲取或設置每個屬性項要綁定的屬性的名稱 /// </summary> public string SelectedValuePath { get { return (string)this.GetValue(SelectedValuePathProperty); } set { this.SetValue(SelectedValuePathProperty, value); } } #endregion #region DisplayMemberPath 獲取或設置爲每個數據項要顯示的屬性的名稱 public static readonly DependencyProperty DisplayMemberPathProperty = DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(ComboBoxTree), null); /// <summary> /// 獲取或設置爲每個數據項要顯示的屬性的名稱 /// </summary> public string DisplayMemberPath { get { return (string)this.GetValue(DisplayMemberPathProperty); } set { this.SetValue(DisplayMemberPathProperty, value); } } #endregion #region SelectedItem 當前選擇的項 public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(ComboBoxTree), null); /// <summary> /// 當前選擇的項 /// </summary> public object SelectedItem { get { return this.GetValue(SelectedItemProperty); } set { this.SetValue(SelectedItemProperty, value); } } #endregion #region SelectedValue 當前選擇的值 public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register("SelectedValue", typeof(object), typeof(ComboBoxTree), null); /// <summary> /// 當前選擇的值 /// </summary> public object SelectedValue { get { return this.GetValue(SelectedValueProperty); } set { this.SetValue(SelectedValueProperty, value); } } #endregion #region IsRecursionEnabled 設置是否啓用遞歸加載數據源中的項 。需要設置ChildName和ParentName兩個屬性 public static readonly DependencyProperty IsRecursionEnabledProperty = DependencyProperty.Register("IsRecursionEnabled", typeof(bool), typeof(ComboBoxTree), new PropertyMetadata(new PropertyChangedCallback(IsRecursionEnabledCallBack))); /// <summary> /// 設置是否啓用遞歸加載數據源中的項。 /// 需要設置ChildMemberPath和ParentMemberPath兩個屬性,如果這兩個屬性沒有設置,則不啓用遞歸加載。 /// </summary> public bool IsRecursionEnabled { get { return (bool)this.GetValue(IsRecursionEnabledProperty); } set { //if (value == true) //{ // //---如果子級和父級屬性設置不爲空 則開始遞歸加載數據 // if (!string.IsNullOrEmpty(this.ChildMemberPath) && !string.IsNullOrEmpty(this.ParentMemberPath)) // { // if (this.ItemSource != null) // { // this.LoadTreeViewDataWithRecursion(); // } // } //} this.SetValue(IsRecursionEnabledProperty, value); } } public static void IsRecursionEnabledCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs args) { if (sender != null) { ComboBoxTree comboBoxTree = sender as ComboBoxTree; comboBoxTree.IsRecursionEnabled = (bool)args.NewValue; } } #endregion #region ChildMemberPath 遞歸加載數據源時,實體中的子級屬性項 public static readonly DependencyProperty ChildMemberPathProperty = DependencyProperty.Register("ChildMemberPath", typeof(string), typeof(ComboBoxTree), null); /// <summary> /// 遞歸加載數據源時,實體中的子級屬性項 /// </summary> public string ChildMemberPath { get { return (string)this.GetValue(ChildMemberPathProperty); } set { this.SetValue(ChildMemberPathProperty, value); } } #endregion #region ParentMemberPath 遞歸加載數據源時,實體中的父級屬性項 public static readonly DependencyProperty ParentMemberPathProperty = DependencyProperty.Register("ParentMemberPath", typeof(string), typeof(ComboBoxTree), null); /// <summary> /// 遞歸加載數據源時,實體中的父級屬性項 /// </summary> public string ParentMemberPath { get { return (string)this.GetValue(ParentMemberPathProperty); } set { this.SetValue(ParentMemberPathProperty, value); } } #endregion #region IsExpandAll 設置TreeView打開時是全部打開狀態還是收縮狀態 默認爲True打開狀態 /// <summary> /// 設置TreeView打開時是全部打開狀態還是收縮狀態 默認爲True打開狀態 /// </summary> public static readonly DependencyProperty IsExpandAllProperty = DependencyProperty.Register("IsExpandAll", typeof(bool), typeof(ComboBoxTree), new PropertyMetadata(true)); /// <summary> /// 設置TreeView打開時是全部打開狀態還是收縮狀態 默認爲True打開狀態 /// </summary> public bool IsExpandAll { get { return (bool)this.GetValue(IsExpandAllProperty); } set { this.SetValue(IsExpandAllProperty, value); } } #endregion #region 加載數據源方法 /// <summary> /// 用列表的方式加載數據源 /// </summary> private void LoadTreeViewDataWithList() { tvList.Items.Clear();//先清空所有的數據 foreach (var item in ItemsSource) { Type objType = item.GetType(); //--用反射的方式 獲得屬性對應的值 PropertyInfo displayMemberInfo = objType.GetProperty(this.DisplayMemberPath); PropertyInfo selectedValueInfo = objType.GetProperty(this.SelectedValuePath); //--當前要顯示的文本 string displayText = displayMemberInfo.GetValue(item, null).ToString(); //--當前選擇的值 string selectedValue = selectedValueInfo.GetValue(item, null).ToString(); TreeViewItem myitem = new TreeViewItem(); myitem.Header = displayText; myitem.Tag = selectedValue; tvList.Items.Add(myitem); } } /// <summary> /// 用遞歸加載數據源 /// </summary> private void LoadTreeViewDataWithRecursion() { tvList.Items.Clear();//先清空所有的數據 if (ItemsSource != null) { //---如果子級和父級屬性設置不爲空 則開始遞歸加載數據 if (string.IsNullOrEmpty(this.ChildMemberPath) || string.IsNullOrEmpty(this.ParentMemberPath)) { MessageBox.Show("在【ComboBoxTree】控件中,如果啓用了遞歸方式加載數據,必須設置【ChildMemberPath】和【ParentMemberPath】屬性的值。"); } foreach (var item in ItemsSource) { Type objType = item.GetType(); //--用反射的方式 獲得屬性對應的值 PropertyInfo displayMemberInfo = objType.GetProperty(this.DisplayMemberPath); PropertyInfo selectedValueInfo = objType.GetProperty(this.SelectedValuePath); PropertyInfo childValueInfo = objType.GetProperty(this.ChildMemberPath); PropertyInfo parentValueInfo = objType.GetProperty(this.ParentMemberPath); //--當前要顯示的文本 string displayText = displayMemberInfo.GetValue(item, null).ToString(); //--當前選擇的值 string selectedValue = selectedValueInfo.GetValue(item, null).ToString(); //---子級綁定的值 string childValue = childValueInfo.GetValue(item, null).ToString(); //--父級綁定的值 string parentValue = parentValueInfo.GetValue(item, null).ToString(); if (string.IsNullOrEmpty(childValue) || string.IsNullOrEmpty(parentValue)) { return; } if (parentValue == "0")//--所有的父級的值爲【0】的數據默認爲添加到根節點。 { TreeViewItem myitem = new TreeViewItem(); myitem.Header = displayText; myitem.Tag = selectedValue; this.LoadItems(myitem, ItemsSource); tvList.Items.Add(myitem); } } } } /// <summary> /// 遞歸加載數據源 /// </summary> /// <param name="treeviewitem"></param> /// <param name="mylist"></param> private void LoadItems(TreeViewItem treeviewitem, IEnumerable mylist) { if (mylist != null) { foreach (var item in ItemsSource) { Type objType = item.GetType(); //--用反射的方式 獲得屬性對應的值 PropertyInfo displayMemberInfo = objType.GetProperty(this.DisplayMemberPath); PropertyInfo selectedValueInfo = objType.GetProperty(this.SelectedValuePath); PropertyInfo childValueInfo = objType.GetProperty(this.ChildMemberPath); PropertyInfo parentValueInfo = objType.GetProperty(this.ParentMemberPath); //--當前要顯示的文本 string displayText = displayMemberInfo.GetValue(item, null).ToString(); //--當前選擇的值 string selectedValue = selectedValueInfo.GetValue(item, null).ToString(); //---子級綁定的值 string childValue = childValueInfo.GetValue(item, null).ToString(); //--父級綁定的值 string parentValue = parentValueInfo.GetValue(item, null).ToString(); if (string.IsNullOrEmpty(childValue) || string.IsNullOrEmpty(parentValue)) { return; } if (treeviewitem.Tag.ToString() == parentValue) { TreeViewItem myitem = new TreeViewItem(); myitem.Header = displayText; myitem.Tag = selectedValue; treeviewitem.Items.Add(myitem); this.LoadItems(myitem, ItemsSource); } } } } #endregion /// <summary> /// TreeView的選擇事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void tvList_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) { if (tvList.Items.Count > 0) { this.SelectedItem = tvList.SelectedItem; if (string.IsNullOrEmpty(this.DisplayMemberPath) || string.IsNullOrEmpty(this.SelectedValuePath)) { MessageBox.Show("此控件必須設置【DisplayMemberPath】和【SelectedValuePath】屬性的值"); return; } Type objType = null; PropertyInfo displayMemberInfo = null; PropertyInfo selectedValueInfo = null; foreach (var item in ItemsSource) { //獲取實體的類型 objType = item.GetType(); //--用反射的方式 獲得屬性對應的值 displayMemberInfo = objType.GetProperty(this.DisplayMemberPath); selectedValueInfo = objType.GetProperty(this.SelectedValuePath); break; } TreeViewItem treeviewitem = tvList.SelectedItem as TreeViewItem; //--當前要顯示的文本 string displayText = treeviewitem.Header.ToString(); //--當前選擇的值 this.SelectedValue = treeviewitem.Tag.ToString(); cbItemDisplay.Content = displayText;//設置ComboBox要顯示的文本 //設置當前選擇的項 foreach (var item in ItemsSource) { string selvalue = selectedValueInfo.GetValue(item, null).ToString(); if (!string.IsNullOrEmpty(selvalue)) { if (treeviewitem.Tag.ToString() == selvalue) { this.SelectedItem = item; ; } } } } } private void cbMain_DropDownOpened(object sender, EventArgs e) { //--打開時 隱藏要顯示的項 cbItemDisplay.Visibility = System.Windows.Visibility.Collapsed; cbItemTreeView.Visibility = System.Windows.Visibility.Visible; } private void cbMain_DropDownClosed(object sender, EventArgs e) { //--關閉時,使顯示的項可見 cbItemDisplay.Visibility = System.Windows.Visibility.Visible; cbItemTreeView.Visibility = System.Windows.Visibility.Collapsed; cbMain.SelectedItem = cbItemDisplay;//設置當前的選中項爲顯示項 } } }
在使用O2OA進行項目定製化開發時,我們可以開發新的前端組件(x_component)以擴展O2OA來實現更多的業務。這種新增前端組件或者前端業務的開發通常會配合後端自定義應用實現的服務來完成系統內數據的交互。在當系統默認的界面不符合系統
DevExpress Reporting是.NET Framework下功能完善的報表平臺,它附帶了易於使用的Visual Studio報表設計器和豐富的報表控件集,包括數據透視表、圖表,因此您可以構建無與倫比、信息清晰的報表。 獲取Dev
wget https://www.php.net/distributions/php-7.4.33.tar.gz ./configure --prefix=/usr/local/php7.4 --with-openssl --with-
DevExpress Office File API是一個專爲C#, VB.NET 和 ASP.NET等開發人員提供的非可視化.NET庫。有了這個庫,不用安裝Microsoft Office,就可以完全自動處理Excel、Word等文檔。開
1. 測試背景 starrocks 2.0.1版本使用低基數全局字典優化後,性能有很大提升,這是準備重點測試部分,測試後對於聚合sql有明顯的性能提升。當然企業中統計分析中多維數據分析的場景也比較多,有助於整體的性能提升,大家可以規劃合適
LightningChartJS是Web上性能特高的圖表庫,具有出色的執行性能 - 使用高數據速率同時監控數十個數據源。 GPU加速和WebGL渲染確保您的設備的圖形處理器得到有效利用,從而實現高刷新率和流暢的動畫,常用於貿易,工程,航空航
DevExpress XAF是一款強大的現代應用程序框架,它採用模塊化設計,開發人員可以選擇內建模塊,也可以自行創建,從而以更快的速度和比開發人員當前更強有力的方式創建應用程序。 獲取DevExpress 新版正式版下載 項目背景 Minh
轉載自天地風雷水火山澤 目的 因爲我們的數倉數據源是Kafka,離線數倉需要用Flume採集Kafka中的數據到HDFS中。 在實際項目中,我們不可能一直在Xshell中啓動Flume任務,一是因爲項目的Flume任務很多,二是一旦Xsh
DevExpress VCL Controls是Devexpress公司旗下最老牌的用戶界面套包,所包含的控件有:數據錄入、圖表、數據分析、導航、佈局等。該控件能幫助您創建優異的用戶體驗,提供高影響力的業務解決方案,並利用您現有的VCL技能
在現代的多線程編程中,Semaphore和CountDownLatch是兩個非常常見和重要的工具類,它們都可以用來實現多線程間的同步和互斥,提高程序的併發性能和效率。本文將詳細介紹Java中的Semaphore和CountDownLatch
本文描述了界面組件庫DevExpress的Office File API(WinForms & WPF)和受Office啓發的控件在v24.1中發佈的一些功能,並詳細介紹了我們當前的搶先體驗預覽版本v24.1中的內容。 DevExpress
聊聊Swift中的宏 宏,Macros是一種常見的編程技術,傳統的C語言中,即包含了宏功能。宏這種功能,簡單來說是在代碼的預編譯階段進行靜態替換,是一種非運行時的特性。但是往復雜了說,宏實際上也提供了一種”元編程“方式,即對程序本身進行編程
EOS_LOWCODE是一款由普元軟件主導的低代碼產品,緊扣模型驅動開發的理念設計,旨在讓更多用戶快速私有化的構建專業系統。 平臺採用人工智能技術和模型驅動技術,可以在顯著提升複雜應用開發效率的同時降低開發成本;採用快速渲染技術,性能相
tp5命令行報 [BadFunctionCallException] not support: redis 芝麻開門2015 於 2018-09-30 18:29:49 發佈 閱讀量1.3w 收藏 1 點贊數 分類專欄: php 版權 p
DevExpress WinForms擁有180+組件和UI庫,能爲Windows Forms平臺創建具有影響力的業務解決方案。DevExpress WinForms能完美構建流暢、美觀且易於使用的應用程序,無論是Office風格的界面,還