I am trying to build this exact same example using a custom server control. Everything seems to be working fairly well other than being able to get the value back after submit from the combo box.
Here is the code for the server control...
Here is how I'm putting it on a page...
This is the javascript on the page... (and I know for sure that all the control ID's are correct and getting the control it should)
This is my aspx page's code behind....
On first page load, I do get the selected text to response write correctly, but when I select something different from the treeview and click the submit button, I don't get the different value, I just get the same one. I'm thinking this has something to do with the javascript block below. If I put "_treeView.NodeClick += _treeView_NodeClick;" in the CreateChildControls() function, it works, but it causes postback every time the node is selected, and it's one postback behind with the correct value...Any ideas?
Here is the code for the server control...
| using System; |
| using System.Collections.Generic; |
| using System.Linq; |
| using System.Text; |
| using System.Web.UI; |
| using System.Web.UI.HtmlControls; |
| using System.Web.UI.WebControls; |
| using LO.Persistence; |
| using LO.Persistence.Services; |
| using Telerik.Web.UI; |
| using LO.Extensions; |
| using LO.Web.ComponentModel; |
| namespace LO.Web.UI.Controls |
| { |
| [BindingProperty("SelectedValue")] |
| public class OComboSelector : CompositeControl, IOControl |
| { |
| #region Properties |
| private RadComboBox _comboBox; |
| private RadTreeView _treeView; |
| private OLabel _label; |
| private bool _isPropertyChanged; |
| private bool _isSelectedValueChanged; |
| public T GetSelectedValue<T>() where T : IEntity, new() |
| { |
| if (_comboBox == null) |
| { |
| return ConvertExtension.ConvertTo<T>(string.Empty); |
| } |
| return ConvertExtension.ConvertTo<T>(_comboBox.SelectedValue); |
| } |
| public string SelectedText |
| { |
| get { return ViewState.GetValue("SelectedText", String.Empty); } |
| set |
| { |
| EnsureChildControls(); |
| RadTreeNode node = GetNodeByText(_treeView.Nodes, value); |
| if (node != null) |
| { |
| node.Selected = true; |
| _comboBox.Items[0].Text = value; |
| _comboBox.Items[0].Selected = true; |
| _comboBox.Text = value; |
| _comboBox.SelectedValue = node.Value; |
| ViewState["SelectedValue"] = node.Value; |
| ViewState["SelectedText"] = value; |
| OnSelectedValueChanged(new RadTreeNodeEventArgs(node)); |
| } |
| } |
| } |
| public string SelectedValue |
| { |
| get { return ViewState.GetValue("SelectedValue", String.Empty); } |
| set |
| { |
| EnsureChildControls(); |
| RadTreeNode node = GetNodeByValue(_treeView.Nodes, value); |
| if (node != null) |
| { |
| node.Selected = true; |
| _comboBox.Items[0].Text = node.Text; |
| _comboBox.Items[0].Selected = true; |
| _comboBox.Text = node.Text; |
| _comboBox.SelectedValue = node.Value; |
| ViewState["SelectedValue"] = value; |
| ViewState["SelectedText"] = node.Text; |
| OnSelectedValueChanged(new RadTreeNodeEventArgs(node)); |
| } |
| } |
| } |
| public override void DataBind() |
| { |
| _treeView.DataBind(); |
| base.DataBind(); |
| } |
| public String EmptyMessage |
| { |
| get { EnsureChildControls(); return _comboBox.EmptyMessage; } |
| set { EnsureChildControls(); _comboBox.EmptyMessage = value; } |
| } |
| public String DataFieldID |
| { |
| get { EnsureChildControls(); return _treeView.DataFieldID; } |
| set { EnsureChildControls(); _treeView.DataFieldID = value; } |
| } |
| public String DataTextField |
| { |
| get { EnsureChildControls(); return _treeView.DataTextField; } |
| set { EnsureChildControls(); _treeView.DataTextField = value; } |
| } |
| public String DataValueField |
| { |
| get { EnsureChildControls(); return _treeView.DataValueField; } |
| set { EnsureChildControls(); _treeView.DataValueField = value; } |
| } |
| public String DataFieldParentID |
| { |
| get { EnsureChildControls(); return _treeView.DataFieldParentID; } |
| set { EnsureChildControls(); _treeView.DataFieldParentID = value; } |
| } |
| public bool AutoPostBack |
| { |
| get { EnsureChildControls(); return _comboBox.AutoPostBack; } |
| set { |
| EnsureChildControls(); |
| _comboBox.AutoPostBack = value; |
| if (value == true) |
| { |
| _treeView.NodeClick += _treeView_NodeClick; |
| } |
| } |
| } |
| public object DataSource |
| { |
| get { EnsureChildControls(); return _treeView.DataSource; } |
| set { EnsureChildControls(); _treeView.DataSource = value; } |
| } |
| public bool Required |
| { |
| get { return ViewState.GetValue("Required", false); } |
| set { ViewState["Required"] = value; } |
| } |
| public bool ReadOnly |
| { |
| get { return ViewState.GetValue("ReadOnly", false); } |
| set { ViewState["ReadOnly"] = value; } |
| } |
| public string LabelID |
| { |
| get { return ViewState.GetValue("LabelID", string.Empty); } |
| set { ViewState["LabelID"] = value; } |
| } |
| public OLabel Label |
| { |
| get |
| { |
| if (_label == null) |
| { |
| _label = ControlUtil.FindLabel(this); |
| } |
| return _label; |
| } |
| } |
| public string Property |
| { |
| get { return ViewState.GetValue("Property", string.Empty); } |
| set { ViewState["Property"] = value; } |
| } |
| public bool IsPropertyChanged |
| { |
| get { return _isPropertyChanged; } |
| } |
| public bool IsSelectedValueChanged |
| { |
| get { return _isSelectedValueChanged; } |
| } |
| public IEntity BindingSource |
| { |
| get; |
| set; |
| } |
| public string SecurityKey |
| { |
| get { return ViewState.GetValue("SecurityKey", string.Empty); } |
| set { ViewState["SecurityKey"] = value; } |
| } |
| #endregion |
| #region Events |
| public event EventHandler<RadTreeNodeEventArgs> SelectedValueChanged; |
| public void OnSelectedValueChanged(RadTreeNodeEventArgs e) |
| { |
| EventHandler<RadTreeNodeEventArgs> handler = SelectedValueChanged; |
| if (handler != null) handler(this, e); |
| _isSelectedValueChanged = true; |
| } |
| public event EventHandler<PropertyChangedEventArgs> PropertyChanged; |
| private void OnPropertyChanged(PropertyChangedEventArgs e) |
| { |
| EventHandler<PropertyChangedEventArgs> handler = PropertyChanged; |
| if (handler != null) handler(this, e); |
| _isPropertyChanged = true; |
| } |
| #endregion |
| #region Methods |
| private RadTreeNode GetNodeByValue(RadTreeNodeCollection nodes, string value) |
| { |
| EnsureChildControls(); |
| RadTreeNode returnNode = null; |
| foreach (RadTreeNode node in nodes) |
| { |
| if (node.Value == value) |
| { |
| returnNode = node; |
| break; |
| } |
| if (node.Nodes.Count > 0) |
| { |
| node.Expanded = true; |
| returnNode = GetNodeByValue(node.Nodes, value); |
| } |
| } |
| return returnNode; |
| } |
| private RadTreeNode GetNodeByText(RadTreeNodeCollection nodes, string value) |
| { |
| EnsureChildControls(); |
| RadTreeNode returnNode = null; |
| foreach (RadTreeNode node in nodes) |
| { |
| if (node.Text == value) |
| { |
| returnNode = node; |
| break; |
| } |
| if (node.Nodes.Count > 0) |
| { |
| node.Expanded = true; |
| returnNode = GetNodeByText(node.Nodes, value); |
| } |
| } |
| return returnNode; |
| } |
| protected override void CreateChildControls() |
| { |
| _comboBox = new RadComboBox { ID = "InternalComboBox", Width = Width }; |
| _treeView = new RadTreeView { ID = "TreeView" }; |
| RadComboBoxItem container = new RadComboBoxItem(); |
| HtmlGenericControl panel = new HtmlGenericControl("div"); |
| Controls.Add(_comboBox); |
| _comboBox.Items.Add(container); |
| container.Controls.Add(panel); |
| panel.Controls.Add(_treeView); |
| panel.ID = "itemTemplate"; |
| _comboBox.OnClientDropDownOpened = "_onClientDropDownOpenedHandler"; |
| _treeView.OnClientNodeClicking = "_nodeClicking"; |
| base.CreateChildControls(); |
| } |
| protected override void Render(HtmlTextWriter writer) |
| { |
| base.Render(writer); |
| } |
| private void _treeView_NodeClick(object sender, RadTreeNodeEventArgs e) |
| { |
| SelectedValue = ((RadTreeView)sender).SelectedNode.Value; |
| OnSelectedValueChanged(e); |
| } |
| public void Bind() |
| { |
| DataBindingUtil.Bind(this, "SelectedValue"); |
| } |
| public void Unbind() |
| { |
| DataBindingUtil.Unbind(this, "SelectedValue"); |
| } |
| protected override void OnInit(EventArgs e) |
| { |
| base.OnInit(e); |
| } |
| #endregion |
| } |
| } |
Here is how I'm putting it on a page...
| <lo:OComboSelector runat="server" ID="testing" /> |
This is the javascript on the page... (and I know for sure that all the control ID's are correct and getting the control it should)
| <script type="text/javascript"> |
| function _nodeClicking(sender, args) { |
| var comboBox = $find("ctl00_ctl00_PageContentPlaceHolder_LeftContentPlaceHolder_eventForm_testing_InternalComboBox"); |
| var node = args.get_node(); |
| comboBox.set_text(node.get_text()); |
| comboBox.trackChanges(); |
| comboBox.get_items().getItem(0).set_value(node.get_value()); |
| comboBox.commitChanges(); |
| comboBox.hideDropDown(); |
| } |
| function _stopPropagation(e) { |
| if (!e) { |
| e = window.event; |
| } |
| e.cancelBubble = true; |
| } |
| function _onClientDropDownOpenedHandler(sender, eventArgs) { |
| var tree = sender.get_items().getItem(0).findControl("ctl00_ctl00_PageContentPlaceHolder_LeftContentPlaceHolder_eventForm_testing_InternalComboBox_i0_TreeView"); |
| var selectedNode = tree.get_selectedNode(); |
| if (selectedNode) { |
| selectedNode.scrollIntoView(); |
| } |
| } |
| var templatedd = document.getElementById("ctl00_ctl00_PageContentPlaceHolder_LeftContentPlaceHolder_eventForm_testing_InternalComboBox_i0_itemTemplate"); |
| templatedd.onclick = _stopPropagation; |
| </script> |
This is my aspx page's code behind....
| protected void Page_Load(object sender, EventArgs e) |
| { |
| if (!IsPostBack) |
| { |
| testing.DataSource = toolTypes; |
| testing.DataTextField = "Name"; |
| testing.DataValueField = "ToolTypeID"; |
| testing.DataBind(); |
| testing.SelectedValue = "29"; |
| } |
| testing.EmptyMessage = "Please select something"; |
| Response.Write(testing.SelectedText); |
| } |
On first page load, I do get the selected text to response write correctly, but when I select something different from the treeview and click the submit button, I don't get the different value, I just get the same one. I'm thinking this has something to do with the javascript block below. If I put "_treeView.NodeClick += _treeView_NodeClick;" in the CreateChildControls() function, it works, but it causes postback every time the node is selected, and it's one postback behind with the correct value...Any ideas?
comboBox.trackChanges();
comboBox.get_items().getItem(0).set_value(node.get_value());
comboBox.commitChanges();
comboBox.get_items().getItem(0).set_value(node.get_value());
comboBox.commitChanges();