I want to add a column to the GridView that will allow me to assign and display multiple values for an item.
For example, imagine you want to track the types (home, office, cell) of telephone numbers for users. Note, this is not my actual requirement. A user can have multiple telephone number types. I don't want to display two separate rows in the GridView for the same user, though. I want to display one row per user, and have the telephone types column allow the display and assignment of multiple telephone number types (e.g., home, office, cell).
A co-worker came up with the idea of creating a User Control that would contain a combobox control to allow the user to select the telephone number types in the combobox and display the selected values in a listbox below it. I specifically chose types for this example, because there's a limited, known set of them-- that's where the idea of the combobox control came in, that is, I need to choose from a limited set of choices.
I looked at the Forums blog titled, "Possible to Add a User Control a A Grid Column," at the following url:
http://www.telerik.com/community/forums/winforms/gridview/possible-to-add-a-user-control-to-a-grid-column.aspx
. . . and tried to implement the solution therein, but when I tried defining a variable of type GridViewDataColumn I got the following design-time error message:
'New' cannot be used on a class that is declared 'MustInherit'.
I also tried defining a variable of GridViewColumn, but got the same error message.
Is there a way to add a User Control to a GridView?
As a separate, but related issue, can I add a LinkLabel control to the GridView, and can the GridViewComboBoxColumn display multiple selections?
21 Answers, 1 is accepted
I've provided a solution like this in the past, but you don't really need a new column, you can simply define and use a custom editor for that kind of cells, please take a look at the example I've provided here and also this KB Article on how to add custom elements inside a cell when in design mode.
Hope this helps, if you have any other questions or comments, please let me know,
Best Regards,
Emanuel Varga
Telerik WinForms MVP
You can show multiple values in a cell by placing a list element inside. It will add an automatic scrolling when there are more items than the cell can show. Please consider the following sample:
DataTable table = new DataTable();table.Columns.Add("ID", typeof(int));table.Columns.Add("Name", typeof(string));table.Columns.Add("Phones", typeof(string));table.Rows.Add(1, "John Smith", "431-235-235\n235-255-333\n233-323-323");table.Rows.Add(2, "Tomas Wright", "431-235-235\n235-255-333");table.Rows.Add(2, "Lewis Anderson", "");this.radGridView1.DataSource = table;this.radGridView1.TableElement.RowHeight = 80;this.radGridView1.AllowAddNewRow = false;this.radGridView1.Columns.Remove("Phones");this.radGridView1.Columns.Add(new ListBoxColumn("Phones"));this.radGridView1.Columns["Name"].Width = 90;this.radGridView1.Columns["Phones"].Width = 150;public class ListBoxColumn : GridViewDataColumn{ public ListBoxColumn(string name) : base(name) { } public override Type GetCellType(GridViewRowInfo row) { if (row is GridViewDataRowInfo) { return typeof(ListBoxCell); } return base.GetCellType(row); }}public class ListBoxCell : GridDataCellElement{ RadListElement listElement; public ListBoxCell(GridViewColumn column, GridRowElement row) : base(column, row) { } protected override void CreateChildElements() { base.CreateChildElements(); listElement = new RadListElement(); this.Children.Add(listElement); } protected override void SetContentCore(object value) { listElement.Items.Clear(); if (value != null && value != DBNull.Value) { string[] phones = value.ToString().Split('\n'); foreach (string phone in phones) { listElement.Items.Add(new RadListDataItem(phone)); } } } public override bool IsCompatible(GridViewColumn data, object context) { return data.Name == "Phones" && context is GridDataRowElement; }}I hope it helps. If you need further assistance with this task, we will be glad to help.
Greetings,
Jack
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
In essence, though, I want to be able to display multiple values (listbox aspect). When I edit, I want to have a combobox control to choose one of several possible choices, when I choose the item in the combobox, that item gets added to the listbox for display.
I also thought I would need two LinkLabel controls (one that displays Done, another displays Remove), perhaps located under the listbox. Clicking on Done would close editing, and leave the listbox as the display control. Clicking on Remove while editing, removes a selected item from the listbox.
So to recap, a combobox (perhaps located at the top during editing) for adding items, listbox (located just below the combobox) for displaying items, and two link labels (Done and Remove).
Thanks for your prompt reply,
Hector
Thank you for these details. I modified my example to include link labels and a drop down list as you have required. Please consider the code below:
public class LinkItem : LightVisualElement{ static Font linkFont = new Font("Segoe UI", 9f, FontStyle.Underline); public LinkItem(string text) { this.Text = text; } protected override void InitializeFields() { base.InitializeFields(); this.Font = linkFont; this.ForeColor = Color.Blue; this.StretchHorizontally = false; this.StretchVertically = false; this.Alignment = ContentAlignment.MiddleRight; }} public class ListBoxCell : GridDataCellElement{ RadListElement listElement; LinkItem linkDone; LinkItem linkRemove; StackLayoutElement linksContainer; RadDropDownListElement dropDownListElement; public ListBoxCell(GridViewColumn column, GridRowElement row) : base(column, row) { } protected override void CreateChildElements() { base.CreateChildElements(); StackLayoutElement stack = new StackLayoutElement(); stack.Orientation = Orientation.Vertical; stack.StretchHorizontally = true; stack.StretchVertically = true; this.Children.Add(stack); dropDownListElement = new RadDropDownListElement(); dropDownListElement.Visibility = ElementVisibility.Collapsed; dropDownListElement.StretchVertically = false; stack.Children.Add(dropDownListElement); listElement = new RadListElement(); listElement.StretchVertically = true; listElement.StretchHorizontally = true; stack.Children.Add(listElement); linksContainer = new StackLayoutElement(); linksContainer.StretchVertically = false; linksContainer.StretchHorizontally = true; linksContainer.Visibility = ElementVisibility.Collapsed; stack.Children.Add(linksContainer); linkDone = new LinkItem("Done"); linksContainer.Children.Add(linkDone); linkRemove = new LinkItem("Remove"); linksContainer.Children.Add(linkRemove); } public override void UpdateInfo() { base.UpdateInfo(); if (linksContainer != null) { linksContainer.Visibility = RowInfo.IsCurrent ? ElementVisibility.Visible : ElementVisibility.Collapsed; dropDownListElement.Visibility = RowInfo.IsCurrent ? ElementVisibility.Visible : ElementVisibility.Collapsed; } } protected override void SetContentCore(object value) { listElement.Items.Clear(); if (value != null && value != DBNull.Value) { string[] phones = value.ToString().Split('\n'); foreach (string phone in phones) { listElement.Items.Add(new RadListDataItem(phone)); } } } protected override SizeF MeasureOverride(SizeF availableSize) { if (linksContainer.Visibility == ElementVisibility.Visible) { listElement.MaxSize = new System.Drawing.Size(0, (int)availableSize.Height - 40); } else { listElement.MaxSize = Size.Empty; } return base.MeasureOverride(availableSize); } public override bool IsCompatible(GridViewColumn data, object context) { return data.Name == "Phones" && context is GridDataRowElement; }}Could you please describe in detail the exact behavior and look that you want to achieve. This will help me to better understand the scenario and to assist you further.
Best wishes,
Jack
the Telerik team
Q2’11 SP1 of RadControls for WinForms is available for download (see what's new); also available is the Q3'11 Roadmap for Telerik Windows Forms controls.
Jack,
thanks for your prompt reply. I've implemented your example as you instructed to make sure I got the plumbing (or wiring) correct, before changing it to work with my actual data.
I may leave it the way you designed it, but, just in case, can the ListBoxCell be made to expand, showing the RadDropDownListElement and LinkItems only when the cell is clicked?
How can I populate the RadDropDownListElement with the list of possible choices?
Follow-up:
I presented the custom ListBoxCell to a user for review. Following is the user's commments:
The drop-down blends in to the listbox, which appears just below it. How can I provide some spacing (padding) between the drop-down and the listbox?
When the drop-down is selected, the list that drops down blends into the next data row's listbox values. Perhaps setting a different background color to the drop-down list during selection would help. What do you suggest?
Can the Done link be aligned left, while the Remove link be aligned right?
Thanks in advance,
Hector
Directly to your questions:
Yes, you can "expand" the current row by handling the CurrentRowChanged event. Consider the following code:
this.radGridView1.CurrentRowChanged += new CurrentRowChangedEventHandler(radGridView1_CurrentRowChanged);if (this.radGridView1.CurrentRow != null){ this.radGridView1.CurrentRow.Height = 100;}void radGridView1_CurrentRowChanged(object sender, CurrentRowChangedEventArgs e){ if (e.OldRow != null) { e.OldRow.Height = 23; } if (e.CurrentRow != null) { e.CurrentRow.Height = 100; }}In addition, I modified the UpdateInfo method to hide the cell content until the row becomes current:
public override void UpdateInfo(){ base.UpdateInfo(); if (linksContainer != null) { linksContainer.Visibility = RowInfo.IsCurrent ? ElementVisibility.Visible : ElementVisibility.Collapsed; dropDownListElement.Visibility = RowInfo.IsCurrent ? ElementVisibility.Visible : ElementVisibility.Collapsed; this.Children[0].Visibility = RowInfo.IsCurrent ? ElementVisibility.Visible : ElementVisibility.Collapsed; }}You can populate the RadDropDownListElement when handling the CreateChildItems event. Here is an example:
DataTable table = new DataTable();table.Columns.Add("ID", typeof(int));table.Columns.Add("Name", typeof(string));table.Rows.Add(1, "one");table.Rows.Add(2, "two");table.Rows.Add(3, "three");dropDownListElement.DisplayMember = "Name";dropDownListElement.ValueMember = "ID";dropDownListElement.DataSource = table;To add spacing, you can use the ElementSpacing property of StackLayoutElement:
StackLayoutElement stack = new StackLayoutElement();//...stack.ElementSpacing = 3;or you can add Margin in RadDropDownListElement:
dropDownListElement.Margin = new System.Windows.Forms.Padding(0, 0, 0, 4);You can customize almost every aspect of our controls by using the Visual Style Builder tool and modifying any of our existing themes. However, if you prefer to use code, you can customize the background color for the popup by using the following code:
dropDownListElement.ListElement.BackColor = Color.LightGray;dropDownListElement.ListElement.GradientStyle = GradientStyles.Solid;You can align the link buttons by adding a stretchable element between them, as demonstrated below:
linkDone = new LinkItem("Done");linksContainer.Children.Add(linkDone);LightVisualElement stretchElement = new LightVisualElement();stretchElement.StretchHorizontally = true;linksContainer.Children.Add(stretchElement);linkRemove = new LinkItem("Remove");linksContainer.Children.Add(linkRemove);I attached the modified code here for your convenience. I hope it helps.
Greetings,
Jack
the Telerik team
Q2’11 SP1 of RadControls for WinForms is available for download (see what's new); also available is the Q3'11 Roadmap for Telerik Windows Forms controls.
thanks for your prompt reply. Regarding expanding the row, I only want to expand it when the specific cell column is selected (that is, I'm editing the cell). In our example, it would be the "Phones" column.
By the way, FYI . . . I'm developing in VB.NET, so the code won't exactly help. But don't worry about converting it to VB.NET, I'm doing it while I read you code snippets.
About the Visual Style Builder (VSB) is that a separate tool (I guess I can research this on my own)? Considering we're creating the control programmatically, can I still incorporate the VSB?
Thanks in advance for your reply,
Hector
I took a look at the modified code because I wanted to find out where you placed the code that performs the following:
if(this.radGridView1.CurrentRow != null) {...} However, I did not find that (nor any of the other new code snippets) in the attached file.
Thnx,
Hector
After reviewing the new updates (spacing, background color, etc.), the user requested that i get rid of the Remove link, replacing it by adding a column to the listbox with an "x" that can be clicked on to remove the item.
I figured the solution would be to use a GridView (instead of adding a column to the listbox), so I tried adding a RadGridViewElement instead of a RadListElement. Unfortunately, I couldn't figure out how to define the columns for the RadGridViewElement. Perhaps I don't understand the relation between the RadGridViewElement and the RadGridView.
Can you help?
My first issue appeared when I changed the way I populated the dropdownlistelement. Initially, I was populating it by hardcoding the data using Columns.Add. Then I changed it to call a subroutine that calls a stored procedure in the database using a DataReader. I called the subroutine from the CreateChildElements method. Using this approach, I got the following error message: 'Invalid attempt to call FieldCount when reader is closed.'
I'm writing this from home right now so I don't have access to the code.
Any suggestions would be greatly appreciated.
Regards,
Hector
Regarding your questions:
If you want to expand the row only when clicking on a specific cell, you have to use the CurrentCellChanged event instead of CurrentRowChanged event. Here is a sample:
Private Sub radGridView1_CurrentCellChanged(sender As Object, e As CurrentCellChangedEventArgs) Handles RadGridView1.CurrentCellChanged If e.NewCell IsNot Nothing Then If e.CurrentCell IsNot Nothing AndAlso Not e.CurrentCell.RowInfo.Equals(e.NewCell.RowInfo) Then e.CurrentCell.RowInfo.Height = 23 End If If e.NewCell.ColumnInfo.Name = "Phones" Then e.NewCell.RowInfo.Height = 100 Else e.NewCell.RowInfo.Height = 23 End If ElseIf e.CurrentCell IsNot Nothing Then e.CurrentCell.RowInfo.Height = 23 End IfEnd SubYes, Visual Style Builder is a separate tool used to create or modify new themes. You cannot use it directly from your application, however you can create a theme. Please consider the following help article.
I added the code which checks whether the CurrentRow is Nothing in Form's OnLoad event after setting the data source. This code ensures that the CurrentRow will have the correct size in all cases.
You cannot use RadGridViewElement in the same way you are using RadListElement. The best option in this case is to use custom visual elements in the list box. Here is the code:
Public Class CustomListElement Inherits RadListVisualItem Private buttonX As RadButtonElement Protected Overrides ReadOnly Property ThemeEffectiveType() As Type Get Return GetType(RadListVisualItem) End Get End Property Protected Overrides Sub CreateChildElements() MyBase.CreateChildElements() buttonX = New RadButtonElement() buttonX.Alignment = ContentAlignment.MiddleRight buttonX.StretchHorizontally = False buttonX.StretchVertically = False buttonX.Text = "x" AddHandler buttonX.Click, AddressOf buttonX_Click Me.Children.Add(buttonX) End Sub Private Sub buttonX_Click(sender As Object, e As EventArgs) Dim listElement As RadListElement = Me.FindAncestor(Of RadListElement)() listElement.Items.Remove(Data) End SubEnd ClassYou should handle also the CreatingVisualItem event to replace the default visual item:
AddHandler listElement.CreatingVisualItem, AddressOf listElement_CreatingVisualItemPrivate Sub listElement_CreatingVisualItem(sender As Object, args As CreatingVisualListItemEventArgs) args.VisualItem = New CustomListElement()End SubRegarding the last issue, I am not sure what causes it. Could you please send me your application. This will help me to locate the issue and provide you with accurate support.
Greetings, Jack
the Telerik team
Q2’11 SP1 of RadControls for WinForms is available for download (see what's new); also available is the Q3'11 Roadmap for Telerik Windows Forms controls.
I will try your last suggestions shortly. However, for now, here is some information on the exception I'm getting:
InvalidOperationException was unhandled by user code
View Detail:
- InnerException: "Invalid attempt to call FieldCount when reader is closed."
- StackTrace:
at System.Data.SqlClient.SqlDataReader.get_FieldCount()
at System.Data.Common.DbEnumerator.BuildSchemaInfo()
at System.Data.Common.DbEnumerator.MoveNext()
at Telerik.WinControls.Data.RadListSource`1.BindToEnumerable()
...
Note: above is an excerpt of the StackTrace. I can provide the full StackTrace if you wish.
...
My HandleException method, showed me that the statement that caused the exception to occur is the following (from PopulateDatabaseDependentControls() method in code, see code block, below):
Me.dgBidItems.DataSource = bsBidItems
Note, I change the following statement in the CreateChildElements method:
From:
PopulateDropDownListElement__FromDatabase()
'PopulateDropDownListElement__UsingHardCodedValues() ' COMMENTED OUT; NOT CURRENTLY USED
To:
'PopulateDropDownListElement__FromDatabase() ' COMMENTED OUT; NOT CURRENTLY USED
PopulateDropDownListElement__UsingHardCodedValues()
... and it works!
FYI . . . Stored Procedure Returns data as such:
BidItemID CustomerDesc Plants DateCreated
14 TestSaveItem201108121517a PLAA, PLBB 08/12/2011
19 TestSaveItem201108121517b PLAA, PLBB, PLCC 08/18/2011
Code Excerpt:
Private Sub InitializeBidItemsDataGrid() ' called by CustomInitialization after call to InitializeComponent() in New() constructor Try With Me.dgBidItems ' Set Location, Size .Left = 6 ' X .Top = 22 ' Y: space for the Group Box Text .Height = Me.gpItems.Height - 24 .Width = Me.gpItems.Width - 12 .TableElement.RowHeight = 60 ' Disable 'Click here to add a new row' row .AllowAddNewRow = False ' Disable 'Drag a column here to group by that column' row .ShowGroupPanel = False Dim gvdCol As tlrkUI.GridViewDataColumn gvdCol = New tlrkUI.GridViewCheckBoxColumn("colSelected") gvdCol.HeaderText = ".." gvdCol.Width = 20 .Columns.Add(gvdCol) gvdCol = New tlrkUI.GridViewTextBoxColumn("BidItemID") gvdCol.HeaderText = "BidItemID" gvdCol.Width = 70 .Columns.Add(gvdCol) gvdCol = New tlrkUI.GridViewTextBoxColumn("CustomerDesc") gvdCol.HeaderText = "CustomerDesc" gvdCol.Width = 140 .Columns.Add(gvdCol) ' ' PlantsV9 ' '' comebackhere .Columns.Remove("Plants") gvdCol = New CustomGridViewColumn("Plants") gvdCol.HeaderText = "Plants" gvdCol.Width = 90 .Columns.Add(gvdCol) gvdCol = New tlrkUI.GridViewTextBoxColumn("DateCreated") gvdCol.HeaderText = "DateCreated" gvdCol.Width = 70 .Columns.Add(gvdCol) End With Catch ex As Exception HandleException(ex) End Try End Sub Private Sub PopulateDatabaseDependentControls() ' called in response to handling User Control Load event If Me.iBidHeaderID <= 0 Then Exit Sub End If Dim startTime As DateTime = DateTime.Now Try Dim cmd As New SqlCommand Dim ds As DataSet = New DataSet() Dim da As SqlDataAdapter ' [sp_APP_BidItem_Get_ByBidHeaderID] Dim sSql As String = "dbo.sp_APP_GetBidItemsByBidHeaderID" Using dbconn As New SqlConnection(sMainConnectionString) Try dbconn.Open() cmd.CommandType = CommandType.StoredProcedure cmd.Connection = dbconn cmd.CommandText = sSql cmd.Parameters.Add("@BidHeaderID", System.Data.SqlDbType.Int).Value = Me.iBidHeaderID da = New SqlDataAdapter(cmd) da.Fill(ds, "BidItems") If ds IsNot Nothing AndAlso ds.Tables IsNot Nothing AndAlso ds.Tables.Count > 0 Then ' assign data binding data soures bsBidItems = New BindingSource() bsBidItems.DataSource = ds.Tables("BidItems").DefaultView() ' * * * * * NOTE: FOLLOWING IS THE STATEMENT THAT THE EXCEPTION OCCURS ON * * * * * * Me.dgBidItems.DataSource = bsBidItems ' * * * * * NOTE: THIS IS THE STATEMENT THAT THE EXCEPTION OCCURS ON * * * * * * ' * * * * * NOTE: ABOVE IS THE STATEMENT THAT THE EXCEPTION OCCURS ON * * * * * * End If Catch sqlEx As SqlException HandleException(sqlEx) Finally End Try End Using Catch ex As Exception HandleException(ex) End Try End Sub #Region "Assign Plants Using CustomGridViewCellElement" Public Class CustomGridViewCellElement Inherits tlrkUI.GridDataCellElement Private listElement As Telerik.WinControls.UI.RadListElement Private linkDone As CustomLinkItem Private linkRemove As CustomLinkItem Private dropDownListElement As Telerik.WinControls.UI.RadDropDownListElement Private linksContainer As Telerik.WinControls.UI.StackLayoutElement Public Sub New(ByVal column As tlrkUI.GridViewColumn, ByVal row As tlrkUI.GridRowElement) MyBase.New(column, row) End Sub Protected Overrides Sub CreateChildElements() MyBase.CreateChildElements() Try Dim mainContainer As Telerik.WinControls.UI.StackLayoutElement = New Telerik.WinControls.UI.StackLayoutElement() With mainContainer .Orientation = Orientation.Vertical .StretchHorizontally = True .StretchVertically = True .ElementSpacing = 3 End With Me.Children.Add(mainContainer) dropDownListElement = New Telerik.WinControls.UI.RadDropDownListElement() With dropDownListElement .Visibility = Telerik.WinControls.ElementVisibility.Collapsed .StretchVertically = False .ListElement.BackColor = Color.PaleGoldenrod .ListElement.GradientStyle = Telerik.WinControls.GradientStyles.Solid End With mainContainer.Children.Add(dropDownListElement) listElement = New Telerik.WinControls.UI.RadListElement With listElement .StretchHorizontally = True .StretchVertically = True End With mainContainer.Children.Add(listElement) linksContainer = New tlrkUI.StackLayoutElement() With linksContainer .StretchHorizontally = True .StretchVertically = False End With linksContainer.Visibility = Telerik.WinControls.ElementVisibility.Collapsed linkDone = New CustomLinkItem("Done") linksContainer.Children.Add(linkDone) linkRemove = New CustomLinkItem("Remove") linksContainer.Children.Add(linkRemove) mainContainer.Children.Add(linksContainer) ' ' Populate DropDownListElement ' PopulateDropDownListElement__FromDatabase() 'PopulateDropDownListElement__UsingHardCodedValues() Catch ex As Exception HandleException(ex) End Try End Sub Public Overrides Sub UpdateInfo() MyBase.UpdateInfo() Try If (linksContainer IsNot Nothing) Then If RowInfo.IsCurrent Then linksContainer.Visibility = Telerik.WinControls.ElementVisibility.Visible dropDownListElement.Visibility = Telerik.WinControls.ElementVisibility.Visible Else linksContainer.Visibility = Telerik.WinControls.ElementVisibility.Collapsed dropDownListElement.Visibility = Telerik.WinControls.ElementVisibility.Collapsed End If End If Catch ex As Exception HandleException(ex) End Try End Sub Private Sub HandleException(ByVal ex As Exception, Optional ByVal bLogException As Boolean = True) If bLogException AndAlso sbLog IsNot Nothing Then modAppMain.LogException(ex, sName & "." & sSourceMethod & " Log: " & sbLog.ToString(), _ "Exception", sName, True) End If End Sub Private Sub PopulateDropDownListElement__UsingHardCodedValues() dropDownListElement.Items.Add(New tlrkUI.RadListDataItem("PLAA", 1)) dropDownListElement.Items.Add(New tlrkUI.RadListDataItem("PLBB", 2)) dropDownListElement.Items.Add(New tlrkUI.RadListDataItem("PLCC", 3)) dropDownListElement.Items.Add(New tlrkUI.RadListDataItem("PLDD", 4)) End Sub Private Sub PopulateDropDownListElement__FromDatabase() sSourceMethod = "PopulateDropDownListElement__FromDatabase" Dim sbSQL As StringBuilder = New StringBuilder("select distinct plantid, plantcode") sbSQL.Append(" from Plant") ' NOT ACTUAL SQL Dim cmd As New SqlCommand Dim reader As SqlDataReader Try Using dbconn As New SqlConnection(APP.My.Settings.dbConnOAM) Try dbconn.Open() cmd.CommandType = CommandType.Text cmd.Connection = dbconn cmd.CommandText = sbSQL.ToString() reader = cmd.ExecuteReader() If reader.HasRows Then dropDownListElement.DataSource = reader dropDownListElement.DisplayMember = "plantcode" dropDownListElement.ValueMember = "plantid" End If reader.Close() Catch sqlEx As SqlException HandleException(sqlEx) Finally End Try End Using Catch ex As Exception HandleException(ex) End Try dropDownListElement.Text = "Select a Plant" End Sub Protected Overrides Sub SetContentCore(ByVal value As Object) sSourceMethod = "SetContentCore" Try listElement.Items.Clear() If ((value IsNot Nothing) AndAlso (value IsNot DBNull.Value)) Then Dim arValues() As String = value.ToString().Split(",") For Each val As String In arValues listElement.Items.Add(New Telerik.WinControls.UI.RadListDataItem(val)) Next End If Catch ex As Exception HandleException(ex) End Try End Sub Protected Overrides Function MeasureOverride(ByVal availableSize As System.Drawing.SizeF) As System.Drawing.SizeF sSourceMethod = "MeasureOverride" Try If linksContainer.Visibility = Telerik.WinControls.ElementVisibility.Visible Then listElement.MaxSize = New System.Drawing.Size(0, System.Convert.ToInt32(availableSize.Height - 40)) Else listElement.MaxSize = Size.Empty End If Catch ex As Exception HandleException(ex) End Try Return MyBase.MeasureOverride(availableSize) End Function Public Overrides Function IsCompatible(ByVal data As Telerik.WinControls.UI.GridViewColumn, ByVal context As Object) As Boolean 'Return MyBase.IsCompatible(data, context) sSourceMethod = "IsCompatible" Try If ((data.Name = "Plants") AndAlso (TypeOf context Is Telerik.WinControls.UI.GridDataRowElement)) Then Return True End If Catch ex As Exception HandleException(ex) End Try Return False End Function End Class Public Class CustomGridViewColumn Inherits tlrkUI.GridViewDataColumn Private sName As String = "ucBidItemsList" Private sSourceMethod As String Private sbLog As StringBuilder = New StringBuilder("ucBidItemsList.CustomGridViewColumn Log:" & vbCrLf) Public Sub New(ByVal sFieldName As String) MyBase.New(sFieldName) sSourceMethod = "CustomGridViewColumn.New" sbLog.AppendLine("Reached " & sName & "." & sSourceMethod) sbLog.AppendLine(" - sFieldName: " & sFieldName) End Sub Public Overrides Function GetCellType(ByVal row As Telerik.WinControls.UI.GridViewRowInfo) As System.Type sSourceMethod = "CustomGridViewColumn.GetCellType" sbLog.AppendLine("Reached " & sName & "." & sSourceMethod) sbLog.AppendLine(" - TypeOf row: " & row.GetType().ToString) Try If (TypeOf row Is Telerik.WinControls.UI.GridViewDataRowInfo) Then sbLog.AppendLine(" before Return GetType(CustomGridViewCellElement)") Return GetType(CustomGridViewCellElement) End If If sbLog IsNot Nothing Then modAppMain.LogMessage(sbLog.ToString(), sName) End If Catch ex As Exception HandleException(ex) End Try Return MyBase.GetCellType(row) End Function Private Sub HandleException(ByVal ex As Exception, Optional ByVal bLogException As Boolean = True) 'If (ex.InnerException IsNot Nothing) Then ' MessageBox.Show(sSourceMethod & ". Exception: " & ex.Message & vbCrLf & _ ' " - - - - - - - - - - " & vbCrLf & _ ' " Inner Exception: " & vbCrLf & ex.InnerException.Message) 'Else ' MessageBox.Show(sSourceMethod & ". Exception: " & ex.Message) 'End If If bLogException AndAlso sbLog IsNot Nothing Then modAppMain.LogException(ex, sName & "." & sSourceMethod & " Log: " & sbLog.ToString(), _ "Exception", sName, True) End If End Sub End Class Private Sub dgBidItems_CurrentRowChanged(ByVal sender As Object, ByVal e As Telerik.WinControls.UI.CurrentRowChangedEventArgs) Handles dgBidItems.CurrentRowChanged If e.OldRow IsNot Nothing Then e.OldRow.Height = 40 End If If e.CurrentRow IsNot Nothing Then e.CurrentRow.Height = 120 End If End Sub #End Region
Thanks in advance for your help,
Hector
P.S. In a way I think you've answered my initial question, and the rest has been detail implementation issues. Should I mark one of the previous responses as an answer, or wait till the final solution?
In Emanuel Varga's example, he wired up the Click event handler to the RadButtonElement in the CellBeginEdit event for the GridView.
In your design where would I wire up the event handlers for the dropdownlistElement's SelectedIndexChanged event and the Done and Remove CustomLinkItem(s) Click events?
Thanks in advance for your help,
Hector
Telerik WinControls Newbie, :-)
I got rid of the CurrentRowChanged event handler, replacing it with the CurrentCellChanged event handler, and added the code which checks whether the CurrentRow is Nothing in a method called in response to the OnLoad event handler, setting the CurrentRow.Height to my default height as you suggested.
However, when the form initially appears and the data grid displays, the custom cell column displays the dropDownListElement and the listbox (displaying only the first value) for the default selected row. All other rows display just the listElement. When I select a different row, the same thing happens. FYI, I don't know if this affecta anything, but I added the following statement to set the first selection in the dropDownListElement:
dropDownListElement.Text = "Select a Plant" I want the custom cell element to expand showing all elements only when the user clicks in that specific row and column's cell (i.e., the custom cell element).
How can I limit the height of the drop-down list aspect of the dropDownListElement when the user clicks on the drop-down arrow?
How can I restore the custom cell element to display only the listElement when the user clicks or tabs away from the the custom cell element (e.g., it loses focus). This will allow me to get rid of the Done link altogether.
Regarding the exception, it seems to be a generic data binding exception caused by the SqlDataReader used in your application. I found this thread which discusses the issue.
You have to change the UpdateInfo method in the custom cell element in order to hide the cell contents when the cell is not current:
Public Overrides Sub UpdateInfo() MyBase.UpdateInfo() If linksContainer IsNot Nothing Then linksContainer.Visibility = If(RowInfo.IsCurrent, ElementVisibility.Visible, ElementVisibility.Collapsed) dropDownListElement.Visibility = If(RowInfo.IsCurrent, ElementVisibility.Visible, ElementVisibility.Collapsed) Me.Children(0).Visibility = If(IsCurrent, ElementVisibility.Visible, ElementVisibility.Collapsed) End IfEnd SubThis code will display the list element only when the cell is current.
To restrict the drop down height, you should set DropDownMinSize and DropDownMaxSize properties:
dropDownListElement.DropDownMinSize = new Size(0, 150)dropDownListElement.DropDownMaxSize = new Size(0, 150)Feel free to mark this response as an answer when all your questions are answered. If you have any other questions, do not hesitate to open new threads.
All the best,
Jack
the Telerik team
Q2’11 SP1 of RadControls for WinForms is available for download (see what's new); also available is the Q3'11 Roadmap for Telerik Windows Forms controls.
Jack,
thanks for the info on the SqlDataReader generic data binding exception. I will investigate that further at a later time.
I've managed to implement a similar fix in UpdateInfo, with the following code:
If (linksContainer IsNot Nothing) Then If RowInfo.IsCurrent AndAlso ColumnInfo.IsCurrent AndAlso (Not bChangingRowInfoHeight) Then linksContainer.Visibility = Telerik.WinControls.ElementVisibility.Visible dropDownListElement.Visibility = Telerik.WinControls.ElementVisibility.Visible Else linksContainer.Visibility = Telerik.WinControls.ElementVisibility.Collapsed dropDownListElement.Visibility = Telerik.WinControls.ElementVisibility.Collapsed End If End If I added the Boolean, bChangingRowInfoHeight, so I don't set properties to .Visible when I've set RowInfo.Height to default (minimized, only listElement Visible, height) in the the done link event handler (when I click on the Done linkItem). I'm considering whether I even need the Done link anymore.
Thanks for the info on setting the drop-down height.
Regards,
Hector
P.S. Can I get the e-mail address of your supervisor(s), so I can tell them what a great job you've done.
I am glad that I could help. Your code seems OK and will also does the job. I am not allowed to provide you with the e-mail of my supervisor here, because this is public forum thread. However, I made him aware of this thread and your feedback. If you still want to share something about our support services, please find my response in a ticket called "Add User Control to GridView Column Ticket" that you can find in Your Account.
Please do not hesitate to contact me if you have any further questions.
Greetings,
Jack
the Telerik team
Q2’11 SP1 of RadControls for WinForms is available for download (see what's new); also available is the Q3'11 Roadmap for Telerik Windows Forms controls.
I have the following Code, that draw a RadDropDownListElement in second and third row.
But when I execute, and I scrollbar the datagrid, the RadDropDownListElement is displayed in others rows?
Meanwhile if I make the grid bigger size, it's displayed normal.
Why? and how to solve it
And how to not allow write or edit in the RadDropDownListElement, but just select an item.
Private Sub RadGridView1_CellFormatting(sender As System.Object, e As Telerik.WinControls.UI.CellFormattingEventArgs) Handles RadGridView1.CellFormatting
If e.RowIndex <> -1 Then
If e.ColumnIndex = 0 Then
If e.RowIndex = 2 Then
Dim vars As New ArrayList
vars.Add("AY@12@" & 2014)
vars.Add("Semester@12@" & 1)
Dim dt = Programs.ExecuteReturnProcedure(Programs.Company.ID, "GetStudents", vars).Tables(0)
Dim cc As New RadDropDownListElement()
cc.DataSource = dt
cc.DisplayMember = "Number"
cc.ValueMember = "Id"
e.CellElement.Children.Add(cc)
ElseIf e.RowIndex = 3 Then
Dim dt As New DataTable()
dt.Columns.Add("Number")
dt.Columns.Add("Id")
Dim dr = dt.NewRow()
dr("Number") = "One"
dr("Id") = "One"
dt.Rows.Add(dr)
dr = dt.NewRow()
dr("Number") = "two"
dr("Id") = "two"
dt.Rows.Add(dr)
dt.AcceptChanges()
Dim cc As New RadDropDownListElement()
cc.DataSource = dt
cc.DisplayMember = "Number"
cc.ValueMember = "Id"
e.CellElement.Children.Add(cc)
End If
End If
End If
End Sub
Thank you for writing.
Due to the UI virtualization in RadGridView, cell elements are created only for currently visible cells and are being reused during operations like scrolling, filtering, grouping and so on. That is why you may obtain unexpected behavior like undesired style for some cells. In addition, the CellFormatting event is appropriate for customizing cell's visual design (with the appropriate reset option), not for modifying the internal cell's structure, which may lead to performance issues as well. The recommended approach for achieving the described functionality is creating custom cell. Here is a sample approach:
public Form1(){ InitializeComponent(); CustomColumn col = new CustomColumn("Column"); this.radGridView1.Columns.Add(col); for (int i = 0; i < 20; i++) { this.radGridView1.Rows.Add("item1"); } this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;}public class CustomCellElement : GridDataCellElement{ public CustomCellElement(GridViewColumn column, GridRowElement row) : base(column, row) { } RadDropDownListElement dropDown; protected override void CreateChildElements() { base.CreateChildElements(); dropDown = new RadDropDownListElement();
dropDown.DropDownStyle = RadDropDownStyle.DropDownList;
this.Children.Add(dropDown); } protected override void SetContentCore(object value) { dropDown.DataSource = new List<string>() { "item1", "item2", "item3" }; } protected override Type ThemeEffectiveType { get { return typeof(GridDataCellElement); } } public override bool IsCompatible(GridViewColumn data, object context) { GridDataRowElement rowElement = context as GridDataRowElement; return data is CustomColumn && rowElement != null && (rowElement.RowInfo.Index % 2 == 0); }}public class CustomColumn : GridViewDataColumn{ public CustomColumn(string fieldName) : base(fieldName) { } public override Type GetCellType(GridViewRowInfo row) { if (row is GridViewDataRowInfo) { if (row.Index % 2 == 0) { return typeof(CustomCellElement); } else { return typeof(GridDataCellElement); } } return base.GetCellType(row); }}However, note that our RadDropDownListElement hosts the Microsoft TextBox in its editable part when the DropDownStyle is DropDown. Using controls in grid cells may slow down the scrolling and will cause visual glitches (similar to the one demonstrated in your first screenshot). A better option would be using RadDropDownListEditor for specific cells, which can be specified in the EditorRequired event.
I hope this information helps. Should you have further questions, I would be glad to help.
Regards,
Desislava
Telerik
Reference to the subject it is stated that i am facing some issue in Radgridview. i want to insert RadialGauge in Gridview in Telerik UI winform using in Desktop App but it's not working.
it is requested that help / guidance may be provided that how to insert Radial gauge in Rad gridview in Winform.
RadGridView provides a very convenient API for creating custom cells. Thus, you can insert any element that you need, e.g. RadRadialGaugeElement. The following help article demonstrates a sample approach: https://docs.telerik.com/devtools/winforms/controls/gridview/cells/creating-custom-cells
The specific part here is that the gauge needs an XML to load its predefined layout. You can store such a file in advance and then reuse it for the gauge element in the custom cell: https://docs.telerik.com/devtools/winforms/controls/gauges/radialgauge/save-and-load-layout
I hope this information helps. If you need any further assistance please don't hesitate to contact me.
Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik
