フレームワークでDevExpressTreeListおよびTreeListLookupEditコントロールを使用する方法



How Use Devexpress Treelist



DevExpressWinformsコントロール 140を超えるUIコントロールとライブラリが組み込まれており、スムーズで美しく、使いやすいアプリケーションを構築するのに最適です。 DevExpress WinForm v20.1が新しくリリースされました。体験してみませんか? クリックしてダウンロード>>

DevExpressによって提供されるツリーリストコントロールTreeListとツリードロップダウンリストコントロールTreeListLookupEditは、どちらも非常に強力なコントロールです。これは、使用中の従来のWinformTreeViewコントロールとは異なります。私は通常、Winform開発の状況に応じてこれらのコントロールを組み合わせます。しかし、全体として、DevExpressに基づくTreeListとTreeListLookupEditは比較的見栄えがします。この記事では、主に実際のWinformプロジェクトでのこれら2つのコントロールの使用と処理について紹介します。



DevExpressTreeListコントロールの使用

たとえば、メニュー管理では、メニューは一般に階層ノードであることがわかっています。直感的な表示の必要性のために、私たちは通常、ツリーリストコントロールを備えたメニューを表示します。その中で、次のインターフェイスに示すように、TreeListコントロールを使用します。



WinForm

その中で、TreeListと入力SearchControlは、インターフェースの使いやすさを向上させるために一緒に使用されます。キーワードを入力することで、ノードをフィルタリングして表示できます。

WinForm



たとえば、フィルタリングコンテンツを入力した後、以下に示すように、フィルタリングツリーリストノードにクエリを実行します。これにより、ユーザーは指定されたツリーノードをすばやくあいまい検索できます。

WinForm

一般的な理解を持って、TreeListコントロールの使用法を理解しましょう。メニューインターフェイスのデザインビューで、次のインターフェイスに示すように、ContextMenuStripの右クリックメニューコントロールを追加し、いくつかのメニュー項目を編集します。

WinForm

次に、画像コレクションのImageCollectionコントロールをドラッグし、それにいくつかのコントロール画像を追加します(この例のように、空白のままにして動的に指定することもできます)

WinForm

次のコードに示すように、ツリーリストの初期化は、一般にいくつかの機能に分けられます。1つはツリーリストの初期化、もう1つはバインディングクエリフィルタリングの処理、もう1つはデータをツリーリストにバインドすることです。

private async void FrmMenu_Load(object sender, EventArgs e) { //List information InitTree() InitSearchControl() await BindTree() }

上記では非同期操作を使用していますが、通常は非同期操作を使用する必要はありません。ここでは状況に応じて処理します。

ツリーリストを初期化するためのオペコードを以下に示します。

/// /// Initialize the tree control /// private void InitTree() { this.tree.Columns.Clear() //Add display column this.tree.Columns.Add(new TreeListColumn {FieldName = 'Id', Caption = 'Id' })//Add a hidden field to store the required ID this.tree.Columns.Add(new TreeListColumn {FieldName = 'Name', Caption = 'Menu Name', Width = 160, VisibleIndex = 0 }) //Set the hierarchy and properties of the tree control tree.KeyFieldName = 'Id' tree.ParentFieldName = 'PID' this.tree.OptionsBehavior.Editable = false this.tree.OptionsView.EnableAppearanceOddRow = true this.tree.OptionsView.EnableAppearanceEvenRow = true this.tree.OptionsDragAndDrop.DragNodesMode = DragNodesMode.None//Dragging is not allowed //Set the icon set and step-by-step icon of the tree this.tree.SelectImageList = this.imageCollection1 this.tree.CustomDrawNodeImages += (object sender, CustomDrawNodeImagesEventArgs e) => { //int maxCount = this.imageCollection1.Images.Count //var index = e.Node.Level 

ツリーリストの処理コードを初期化するために、以下に示すように、拡張関数を使用してさらに単純化することもできます。

/// /// Initialize the tree control /// private void InitTree() { this.tree.Columns.Clear() this.tree.OptionsDragAndDrop.DragNodesMode = DragNodesMode.None//Dragging is not allowed //Control extension function packaging processing this.tree.CreateColumn('Name', 'Menu Name', 160, true) this.tree.InitTree('Id', 'PID', null, false, false) //Set the icon set and step-by-step icon of the tree this.tree.SelectImageList = this.imageCollection1 this.tree.CustomDrawNodeImages += (object sender, CustomDrawNodeImagesEventArgs e) => { //int maxCount = this.imageCollection1.Images.Count //var index = e.Node.Level 

検索コントロールSearchControlを初期化するコードを以下に示します。

/// /// Achieve filtering query of tree nodes /// private void InitSearchControl() { this.searchControl1.Client = this.tree this.tree.FilterNode += (object sender, FilterNodeEventArgs e) => { if (tree.DataSource == null) return string nodeText = e.Node.GetDisplayText('Name')//Fill in FieldName as parameter if (string.IsNullOrWhiteSpace(nodeText)) return bool isExist = nodeText.IndexOf(searchControl1.Text, StringComparison.OrdinalIgnoreCase) >= 0 if (isExist) { var node = e.Node.ParentNode while (node != null) { if (!node.Visible) { node.Visible = true node = node.ParentNode } else break } } e.Node.Visible = isExist e.Handled = true } }

上記はツリーリストコントロールを初期化するためのものであり、データをそれにバインドする必要もあります。ツリーリストのメインコードは、データバインディングとアイコンバインディングです。

this.tree.SelectImageList = this.imageCollection1 this.tree.DataSource = result.Items

ただし、アイコンはデータソースから動的に構築されるため、ツリーリストコントロールに簡単に割り当てるには、コレクションに保存する必要があります。以下は完全なバインディングコードです。

/// /// Data source of binding tree /// private async Task BindTree() { var pageDto = new MenuPagedDto() var result = await MenuApiCaller.Instance.GetAll(pageDto) //Used to store the corresponding ID and index order IdIndexDict = new Dictionary() //Refresh the node picture this.imageCollection1 = new ImageCollection() this.imageCollection1.ImageSize = new Size(16, 16) if (result != null && result.Items != null) { foreach (var menuInfo in result.Items) { var image = LoadIcon(menuInfo) this.imageCollection1.Images.Add(image) //Add a picture serial number for each menu ID, easy to find if(!IdIndexDict.ContainsKey(menuInfo.Id)) { int index = this.imageCollection1.Images.Count-1//The last number IdIndexDict.Add(menuInfo.Id, index) } } } //imageCollection has changed and needs to be re-assigned to treeList this.tree.SelectImageList = this.imageCollection1 this.tree.DataSource = result.Items this.tree.ExpandAll() }

指定されたツリーノードのバインディング値を取得する必要がある場合は、次のコードに示すように、現在のFocusNodeを介してフィールド値を取得できます。

/// /// Edit list data /// private async Task EditTreeData() { string ID = string.Concat(this.tree.FocusedNode.GetValue(Id_FieldName)) if (!string.IsNullOrEmpty(ID)) { FrmEditMenu dlg = new FrmEditMenu() dlg.ID = ID dlg.OnDataSaved += new EventHandler(dlg_OnDataSaved) dlg.InitFunction(LoginUserInfo, FunctionDict)//Assign user permission information to the subform if (DialogResult.OK == dlg.ShowDialog()) { await BindTree() } } }

上記はTreeListコントロールの使用プロセスであり、主な注意はデータソースのバインドとアイコンのバインド操作です。

親の位置を調整するためにツリーリストをドラッグすることも許可している場合は、ドラッグイベントで処理できます。

this.tree.CalcNodeDragImageIndex += new DevExpress.XtraTreeList.CalcNodeDragImageIndexEventHandler(this.Tree_CalcNodeDragImageIndex) this.tree.DragDrop += new System.Windows.Forms.DragEventHandler(this.Tree_DragDrop) this.tree.DragOver += new System.Windows.Forms.DragEventHandler(this.Tree_DragOver) private void Tree_DragOver(object sender, DragEventArgs e) { TreeListNode dragNode = e.Data.GetData(typeof(TreeListNode)) as TreeListNode e.Effect = GetDragDropEffect(sender as TreeList, dragNode) } private async void Tree_DragDrop(object sender, DragEventArgs e) { TreeListNode dragNode, targetNode TreeList tl = sender as TreeList Point p = tl.PointToClient(new Point(e.X, e.Y)) dragNode = e.Data.GetData(typeof(TreeListNode)) as TreeListNode targetNode = tl.CalcHitInfo(p).Node //Update data after moving var id = string.Concat(dragNode.GetValue('Id')).ToInt64() var pid = string.Concat(targetNode.GetValue('Id')).ToInt64() await OrganizationUnitApiCaller.Instance.Move(new MoveOrganizationUnitDto() { Id = id, ParentId = pid }) await BindTree() e.Effect = DragDropEffects.None } private void Tree_CalcNodeDragImageIndex(object sender, CalcNodeDragImageIndexEventArgs e) { TreeList tl = sender as TreeList if (GetDragDropEffect(tl, tl.FocusedNode) == DragDropEffects.None) e.ImageIndex = -1 // no icon else e.ImageIndex = 1 // the reorder icon (a curved arrow) }

WinForm

DevExpressTreeListLookupEditコントロールの使用

TreeListとTreeListLookupEditは通常、ペアで表示されます。通常、親ノードを調整する必要がある場合は、このツリー型のドロップダウンリストTreeListLookupEditコントロールが関係します。

便宜上、通常、これらのドロップダウンリストのバインドを処理するカスタムコントロールを定義するため、毎回データと初期化コードをバインドする必要はありません。

WinForm

private void FunctionControl_Load(object sender, EventArgs e) { if (!this.DesignMode) { InitTree() BindTree() } } /// /// Initialize the tree /// /// private void InitTree() { this.txtMenu.Properties.ValueMember = 'Id' this.txtMenu.Properties.DisplayMember = 'Name' var tree = this.treeListLookUpEdit1TreeList tree.Columns.Clear() //Control extension function packaging processing tree.CreateColumn('Name', 'Menu Name', 160, true) tree.InitTree('Id', 'PID', null, false, false) //Set the icon set and step-by-step icon of the tree tree.SelectImageList = this.imageCollection1 tree.CustomDrawNodeImages += (object sender, CustomDrawNodeImagesEventArgs e) => { int maxCount = this.imageCollection1.Images.Count var index = e.Node.Level  MenuApiCaller.Instance.GetAll(new MenuPagedDto() { })) if (result != null && result.Items != null) { tree.DataSource = result.Items tree.ExpandAll()//Expand all } //Perform post-binding processing if (DataBinded != null) { DataBinded(null, null) } }

その中で、AsyncContext.Runは非同期関数を同期使用として扱います。通常、データバインディングの遅延や処理なしを回避するために、ユーザーコントロールで同期操作を使用します

ValueMemberとDisplayMemberを作成することにより、コンテンツを通常どおりに表示でき、必要な値の操作を後で保存できます。

this.txtMenu.Properties.ValueMember = 'Id' this.txtMenu.Properties.DisplayMember = 'Name'

TreeListLookupEditコントロールにはまだTreeListコントロールがあります。このコントロールの操作は、前述のTreeListコントロールの操作とまったく同じです。ツリーリストの方法で初期化してバインドできます。

インターフェース効果は以下の通りです。

WinForm

ツリーリストコントロールは、次のように展開されます。

WinForm

この記事はから複製されます ブログガーデン-WuHuacong