1. My editor is confined to the size of the cell and it needs to be much larger than that
2. When I attempt to data bind the control nothing is displayed.
Sample code:
public
class
TreeEditor : BaseGridEditor
{
protected
override
RadElement CreateEditorElement ()
{
RadTreeViewElement treeViewElement =
new
RadTreeViewElement ();
//BindData (treeViewElement); // This doesn't work
LoadData (treeViewElement); // This displays data
return
treeViewElement;
}
private
static
void
BindData(RadTreeViewElement treeViewElement)
{
List<NodeData> Nodes =
new
List<NodeData>();
NodeData root =
new
NodeData() { ID = 0 };
root.Children.Add(
new
NodeData() { ID = 1 });
root.Children.Add(
new
NodeData() { ID = 2 });
Nodes.Add(root);
treeViewElement.DataSource = Nodes;
treeViewElement.DisplayMember =
"ID\\ID"
;
treeViewElement.ChildMember =
"Nodes\\Children"
;
}
private
static
void
LoadData (RadTreeViewElement treeViewElement)
{
RadTreeNode root = treeViewElement.Nodes.Add (
"Root"
);
root.Nodes.Add (
"First"
, 1);
root.Nodes.Add (
"Second"
, 1);
}
public
override
object
Value
{
get
{
RadTreeViewElement editor = (RadTreeViewElement)
this
.EditorElement;
if
(editor.SelectedNode ==
null
)
return
string
.Empty;
return
editor.SelectedNode.ToString ();
}
set
{
//TODO: ?
}
}
}
14 Answers, 1 is accepted
Thank you for writing.
I have prepared a sample code snippet demonstrating an approach how to implement custom editor with RadTreeView. In order avoid difference in rows height when the editor is active, the custom tree view editor is placed in a popup:
public
Form1()
{
InitializeComponent();
this
.radGridView1.EditorRequired += radGridView1_EditorRequired;
this
.radGridView1.CellEditorInitialized += radGridView1_CellEditorInitialized;
GridViewComboBoxColumn comboColumn =
new
GridViewComboBoxColumn(
"Description"
);
comboColumn.FieldName =
"Description"
;
comboColumn.DisplayMember =
"Description"
;
comboColumn.ValueMember =
"Description"
;
comboColumn.DataSource = accounts1.Concat(accounts2).ToList();
this
.radGridView1.Columns.Add(comboColumn);
this
.radGridView1.AutoGenerateColumns =
false
;
List<Account> items =
new
List<Account>();
foreach
(Account a
in
accounts1.Concat(accounts2).ToList())
{
items.Add(
new
Account(a.AccountID, a.Description));
}
this
.radGridView1.DataSource = items;
}
private
void
radGridView1_CellEditorInitialized(
object
sender, GridViewCellEventArgs e)
{
TreeEditor editor = e.ActiveEditor
as
TreeEditor;
if
(editor !=
null
)
{
TreeEditorElement treeElement = editor.EditorElement
as
TreeEditorElement;
treeElement.TreeView.BindingContext =
this
.radGridView1.BindingContext;
treeElement.TreeView.DataSource = accountTypes;
treeElement.TreeView.DisplayMember =
"Title\\Description"
;
treeElement.TreeView.ChildMember =
"AccountTypes\\Accounts"
;
treeElement.TreeView.FullRowSelect =
true
;
treeElement.TreeView.SelectedNodes.Clear();
string
text =
this
.radGridView1.CurrentCell.Value +
""
;
foreach
(RadTreeNode n
in
treeElement.TreeView.Nodes)
{
RadTreeNode selected = GetNodeByName(n, text);
if
(selected !=
null
)
{
selected.Current =
true
;
selected.Selected =
true
;
selected.Expanded =
true
;
if
(selected.Level > 0)
{
selected.Parent.Expanded =
true
;
}
}
}
}
}
private
static
RadTreeNode GetNodeByName(RadTreeNode n,
string
t)
{
RadTreeNode foundNode =
null
;
if
(n.Text == t)
{
foundNode = n;
}
else
{
foreach
(RadTreeNode node
in
n.Nodes)
{
foundNode = GetNodeByName(node, t);
if
(foundNode !=
null
)
{
break
;
}
}
}
return
foundNode;
}
void
radGridView1_EditorRequired(
object
sender, EditorRequiredEventArgs e)
{
if
(
this
.radGridView1.CurrentColumn.Name ==
"Description"
)
{
e.EditorType =
typeof
(TreeEditor);
}
}
public
class
TreeEditor: BaseGridEditor
{
public
override
object
Value
{
get
{
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
SelectedTreeNodeCollection treeNodes = treeElement.TreeView.SelectedNodes;
StringBuilder sb =
new
StringBuilder();
foreach
(RadTreeNode node
in
treeNodes)
{
sb.AppendFormat(
"{0}"
, node.Text);
}
return
sb.ToString();
}
set
{
string
text = ((GridComboBoxCellElement)
this
.OwnerElement).Value +
""
;
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
foreach
(RadTreeNode n
in
treeElement.TreeView.Nodes)
{
RadTreeNode selected = GetNodeByName(n, text);
if
(selected !=
null
)
{
selected.Selected =
true
;
}
}
}
}
public
override
void
BeginEdit()
{
base
.BeginEdit();
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
treeElement.Button.DropDownButtonElement.DropDownMenu.PopupElement.MinSize =
new
Size(300, 300);
treeElement.Button.ShowDropDown();
}
protected
override
RadElement CreateEditorElement()
{
return
new
TreeEditorElement();
}
private
RadTreeNode FindTreeNode(RadTreeNode node,
string
value)
{
if
(node.Text == value)
{
return
node;
}
foreach
(RadTreeNode subNode
in
node.Nodes)
{
RadTreeNode found = FindTreeNode(subNode, value);
if
(found !=
null
)
{
return
found;
}
}
return
null
;
}
}
public
class
TreeEditorElement: RadHostItem
{
public
TreeEditorElement() :
base
(
new
RadDropDownButton())
{
this
.Button.Items.Add(
new
TreeMenuItem());
this
.TreeView.MultiSelect =
true
;
TreeView.Nodes.Add(
new
RadTreeNode(
"Root"
));
TreeView.Nodes[0].Nodes.Add(
new
RadTreeNode(
"Item 1"
));
TreeView.Nodes[0].Nodes.Add(
new
RadTreeNode(
"Item 2"
));
TreeView.ExpandAll();
}
public
RadDropDownButton Button
{
get
{
return
(RadDropDownButton)
this
.HostedControl;
}
}
public
RadTreeView TreeView
{
get
{
return
(RadTreeView)((RadMenuHostItem)
this
.Button.Items[0]).HostedControl;
}
}
}
public
class
TreeMenuItem: RadMenuHostItem
{
public
TreeMenuItem() :
base
(
new
RadTreeView())
{
}
protected
override
SizeF MeasureOverride(SizeF availableSize)
{
base
.MeasureOverride(availableSize);
return
new
SizeF(100, 300);
}
}
public
class
Account
{
public
int
AccountID {
get
;
set
; }
public
string
Description {
get
;
set
; }
public
Account()
{
}
public
Account(
int
accountID,
string
description)
{
this
.AccountID = accountID;
this
.Description = description;
}
}
public
class
AccountType
{
public
int
AccountTypeID {
get
;
set
; }
public
string
Title {
get
;
set
; }
public
List<Account> Accounts {
get
;
set
; }
public
AccountType(
int
accountTypeID,
string
title, List<Account> accounts)
{
this
.AccountTypeID = accountTypeID;
this
.Title = title;
this
.Accounts = accounts;
}
}
static
List<Account> accounts1 =
new
List<Account>()
{
new
Account(1,
"Rent Expence description 1"
),
new
Account(2,
"Rent Expence description 2"
)
};
static
List<Account> accounts2 =
new
List<Account>()
{
new
Account(1,
"Investment Income description 1"
),
new
Account(2,
"Investment Income description 2"
)
};
List<AccountType> accountTypes =
new
List<AccountType>()
{
new
AccountType(1,
"Expence"
,accounts1),
new
AccountType(2,
"Income "
,accounts2),
};
I hope this information helps. Should you have further questions, I would be glad to help.
Regards,
Desislava
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
Thank you for writing back.
The drop down is displayed as the RadTreeView is placed in a RadMenuHostItem inside a RadHostItem. You can deal with the undesired behavior that when pressing Enter key the popup is closed, but the editor is still active. Here is the modified code snippet for the TreeEditor class:
public
class
TreeEditor: BaseGridEditor
{
//some other code
public
override
void
BeginEdit()
{
base
.BeginEdit();
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
treeElement.Button.DropDownButtonElement.DropDownMenu.PopupElement.MinSize =
new
Size(300, 300);
treeElement.Button.ShowDropDown();
treeElement.Button.DropDownClosed += Button_DropDownClosed;
}
public
override
bool
EndEdit()
{
bool
result =
base
.EndEdit();
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
treeElement.Button.DropDownClosed -= Button_DropDownClosed;
return
result;
}
private
void
Button_DropDownClosed(
object
sender, EventArgs e)
{
RadDropDownButton ddButton = sender
as
RadDropDownButton;
if
(ddButton !=
null
)
{
RadGridView grid = ddButton.Parent
as
RadGridView;
if
(grid !=
null
)
{
grid.EndEdit();
}
}
}
//some other code
}
I hope this information helps. If you have any additional questions, please let me know.
Regards,
Desislava
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
Thank you for writing back.
In order to force the RadTreeView to accept MouseWheel messages for scrolling, you need to focus the TreeEditorElement.TreeView in the TreeEditor.BeginEdit event. Afterwards, you should cancel the TreeEditorElement.Button.DropDownButtonElement.DropDownMenu.DropDownClosing event in order to keep the popup opened while scrolling. You can use a flag to indicate whether the drop-down should be closed. Here is just a an example demonstrating how to close the popup when selecting a node:
public
override
void
BeginEdit()
{
base
.BeginEdit();
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
treeElement.TreeView.Focus();
isSelected =
false
;
treeElement.Button.DropDownButtonElement.DropDownMenu.DropDownClosing -= DropDownMenu_DropDownClosing;
treeElement.Button.DropDownButtonElement.DropDownMenu.DropDownClosing += DropDownMenu_DropDownClosing;
treeElement.TreeView.SelectedNodeChanged -= TreeView_SelectedNodeChanged;
treeElement.TreeView.SelectedNodeChanged += TreeView_SelectedNodeChanged;
}
bool
isSelected =
false
;
private
void
TreeView_SelectedNodeChanged(
object
sender, RadTreeViewEventArgs e)
{
isSelected =
true
;
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
treeElement.Button.DropDownButtonElement.DropDownMenu.ClosePopup(RadPopupCloseReason.Mouse);
}
private
void
DropDownMenu_DropDownClosing(
object
sender, RadPopupClosingEventArgs args)
{
RadDropDownButtonPopup popup = sender
as
RadDropDownButtonPopup;
if
(popup !=
null
&& !isSelected)
{
args.Cancel =
true
;
}
}
I hope this information helps. If you have any additional questions, please let me know.
Regards,
Dess
Telerik
Thank you for writing back.
In order to accomplish this task, you would need to handle the DropDownClosed event of the Button element and in the handler call the EndEdit method of the grid. Please see my code snippet below:
public
override
void
BeginEdit()
{
base
.BeginEdit();
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
//more code
treeElement.Button.DropDownClosed += Button_DropDownClosed;
}
private
void
Button_DropDownClosed(
object
sender, EventArgs e)
{
RadDropDownButton ddButton = sender
as
RadDropDownButton;
if
(ddButton !=
null
)
{
RadGridView grid = ddButton.Parent
as
RadGridView;
if
(grid !=
null
)
{
grid.EndEdit();
}
}
}
I hope this helps. Should you have further questions please do not hesitate to write back.
Regards,
Hristo Merdjanov
Telerik
I can't get this to work with the mouse wheel changes. Using the code below blanks out the cell when I select an item on the tree
public
class
TreeEditor : BaseGridEditor
{
public
override
object
Value
{
get
{
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
SelectedTreeNodeCollection treeNodes = treeElement.TreeView.SelectedNodes;
StringBuilder sb =
new
StringBuilder();
foreach
(RadTreeNode node
in
treeNodes)
{
sb.AppendFormat(
"{0}"
, node.Text);
}
return
sb.ToString();
}
set
{
string
text = ((GridComboBoxCellElement)
this
.OwnerElement).Value +
""
;
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
}
}
public
override
void
BeginEdit()
{
base
.BeginEdit();
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
treeElement.Button.DropDownButtonElement.DropDownMenu.PopupElement.MinSize =
new
Size(300, 300);
treeElement.Button.ShowDropDown();
//mouse wheel changes-
treeElement.TreeView.Focus();
isSelected =
false
;
treeElement.Button.DropDownButtonElement.DropDownMenu.DropDownClosing -= DropDownMenu_DropDownClosing;
treeElement.Button.DropDownButtonElement.DropDownMenu.DropDownClosing += DropDownMenu_DropDownClosing;
treeElement.TreeView.SelectedNodeChanged -= TreeView_SelectedNodeChanged;
treeElement.TreeView.SelectedNodeChanged += TreeView_SelectedNodeChanged;
// end mouse wheel
treeElement.Button.DropDownClosed += Button_DropDownClosed;
}
private
bool
isSelected;
private
void
TreeView_SelectedNodeChanged(
object
sender, RadTreeViewEventArgs e)
{
isSelected =
true
;
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
treeElement.Button.DropDownButtonElement.DropDownMenu.ClosePopup(RadPopupCloseReason.Mouse);
RadGridView grid = e.TreeView.Parent
as
RadGridView;
if
(grid !=
null
)
{
grid.EndEdit();
}
}
private
void
DropDownMenu_DropDownClosing(
object
sender, RadPopupClosingEventArgs args)
{
RadDropDownButtonPopup popup = sender
as
RadDropDownButtonPopup;
if
(popup !=
null
&& !isSelected)
{
args.Cancel =
true
;
}
}
private
void
Button_DropDownClosed(
object
sender, EventArgs e)
{
RadDropDownButton ddButton = sender
as
RadDropDownButton;
if
(ddButton !=
null
)
{
RadGridView grid = ddButton.Parent
as
RadGridView;
if
(grid !=
null
)
{
grid.EndEdit();
}
}
}
protected
override
RadElement CreateEditorElement()
{
return
new
TreeEditorElement();
}
}
Thank you for writing back.
Closing the dropdown before editing the cell does not pass properly the selected value. I am sending you attached my modified project, allowing scrolling inside the tree and node selection.
I hope that it would fit your scenario. Should you have further questions please do not hesitate to write back.
Regards,
Hristo Merdjanov
Telerik
Thanks for your continued help. When I run your project the popup tree closes when I use my scroll wheel.
This has been going on for a while so to review I need a combination of all these behaviors.
- Click on cell -> tree pops up on first click
- Scroll mouse wheel -> scrolls pop up tree
- Click on tree item -> tree is closed and cell is filled. No drop down button displayed
I believe all of issues have been addressed in this thread but I can't figure out how to make them all work at the same time.
Note- In order to run the solution I had to remove the "Source" directory from the project and in VS right clicked on the project and chose Telerik UI For Winforms/Convert To Telerik Windows Form Application.
Also I added extra data to make the mouse scrolling more obvious-
static
List<Account> accounts1 =
new
List<Account>()
{
new
Account(1,
"Rent Expence description 1"
),
new
Account(2,
"Rent Expence description 1"
),
new
Account(3,
"Rent Expence description 1"
),
new
Account(4,
"Rent Expence description 1"
),
new
Account(5,
"Rent Expence description 1"
),
new
Account(6,
"Rent Expence description 1"
),
new
Account(7,
"Rent Expence description 1"
),
new
Account(8,
"Rent Expence description 1"
),
};
static
List<Account> accounts2 =
new
List<Account>()
{
new
Account(1,
"Investment Income description 1"
),
new
Account(2,
"Investment Income description 2"
),
new
Account(3,
"Investment Income description 1"
),
new
Account(4,
"Investment Income description 1"
),
new
Account(5,
"Investment Income description 1"
),
new
Account(6,
"Investment Income description 1"
),
new
Account(7,
"Investment Income description 1"
),
new
Account(8,
"Investment Income description 1"
),
new
Account(9,
"Investment Income description 1"
)
};
Thank you for writing back.
I am sending you attached the sample project which I believe addresses all of the features you would like to implement.
Besides the project, I am also sending you a gif file showing the result on my end.
I hope this helps. Should you have further questions please do not hesitate to write back.
Regards,
Hristo Merdjanov
Telerik
Sorry but this is not doing everything correctly. It does not scroll with the mouse wheel. In your gif I see you are clicking and dragging the scroll bars.
If I apply Dess's solution from June 08 to your latest project (link and new code shown below), scrolling with the mousewheel works but I need the window to close when clicking outside the popup or when the escape button is pressed as it did before adding these changes. Now it will only close when clicking on the tree.
http://www.telerik.com/forums/problems-implementing-a-custom-treeview-grid-editor#HcsEPKPbXUmdDY6CPANs-Q
public
override
void
BeginEdit()
{
base
.BeginEdit();
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
treeElement.Button.Visible =
false
;
treeElement.TreeView.Focus();
treeElement.TreeView.SelectedNodeChanged -= TreeView_SelectedNodeChanged;
treeElement.TreeView.SelectedNodeChanged += TreeView_SelectedNodeChanged;
// begin mouse wheel changes
isSelected =
false
;
treeElement.Button.DropDownButtonElement.DropDownMenu.DropDownClosing -= DropDownMenu_DropDownClosing;
treeElement.Button.DropDownButtonElement.DropDownMenu.DropDownClosing += DropDownMenu_DropDownClosing;
}
bool
isSelected =
false
;
private
void
DropDownMenu_DropDownClosing(
object
sender, RadPopupClosingEventArgs args)
{
RadDropDownButtonPopup popup = sender
as
RadDropDownButtonPopup;
if
(popup !=
null
&& !isSelected)
{
args.Cancel =
true
;
}
}
private
void
TreeView_SelectedNodeChanged(
object
sender, RadTreeViewEventArgs e)
{
isSelected =
true
;
// end mouse wheel changes
TreeEditorElement treeElement =
this
.EditorElement
as
TreeEditorElement;
((RadDropDownButton)treeElement.HostedControl).DropDownButtonElement.PerformClick();
treeElement.Button.DropDownButtonElement.DropDownMenu.ClosePopup(RadPopupCloseReason.Mouse);
}
Thank you for writing back.
I extended the sample project to include the custom solution regarding the scrolling behavior. The popup now closes when the Esc key is pressed and also if you click somewhere outside of the editor.
Besides the project I am also sending you a gif file showing the result on my end.
I hope this helps. Should you have further questions please do not hesitate to write back.
Regards,
Hristo Merdjanov
Telerik