This is a migrated thread and some comments may be shown as answers.

Add User Control to GridView Column

21 Answers 1203 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Hector
Top achievements
Rank 1
Hector asked on 06 Oct 2011, 05:37 PM

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

Sort by
0
Emanuel Varga
Top achievements
Rank 1
answered on 07 Oct 2011, 08:54 AM
Hello Hector,

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
0
Jack
Telerik team
answered on 07 Oct 2011, 05:06 PM
Hi Hector,

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 >>

0
Hector
Top achievements
Rank 1
answered on 10 Oct 2011, 03:34 PM
Firstly, let me thank both Emanuel and Jack. I think I need a combination of the two solutions, though. First, I need the listbox aspect that Jack provided for displaying the values, but then I also need the custom editor aspect that Emanual provided. I'm not sure, however, how to combine the two. I'm going to give it a try.

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
0
Accepted
Jack
Telerik team
answered on 11 Oct 2011, 03:07 PM
Hello 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.

0
Hector
Top achievements
Rank 1
answered on 12 Oct 2011, 04:19 PM

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

 

0
Jack
Telerik team
answered on 13 Oct 2011, 12:09 PM
Hello 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.

0
Hector
Top achievements
Rank 1
answered on 13 Oct 2011, 03:08 PM
Jack,

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
0
Hector
Top achievements
Rank 1
answered on 13 Oct 2011, 03:32 PM
Jack,

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
0
Hector
Top achievements
Rank 1
answered on 13 Oct 2011, 06:12 PM

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?

0
Hector
Top achievements
Rank 1
answered on 14 Oct 2011, 12:05 AM
I changed my application to use the actual data.

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

0
Jack
Telerik team
answered on 14 Oct 2011, 12:18 PM
Hello 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 If
End Sub

Yes, 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 Sub
End Class

You should handle also the CreatingVisualItem event to replace the default visual item:
AddHandler listElement.CreatingVisualItem, AddressOf listElement_CreatingVisualItem
Private Sub listElement_CreatingVisualItem(sender As Object, args As CreatingVisualListItemEventArgs)
     args.VisualItem = New CustomListElement()
End Sub

Regarding 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.

0
Hector
Top achievements
Rank 1
answered on 14 Oct 2011, 02:40 PM
Jack,

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?

0
Hector
Top achievements
Rank 1
answered on 14 Oct 2011, 02:55 PM
Jack,

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, :-)


 

0
Hector
Top achievements
Rank 1
answered on 14 Oct 2011, 08:17 PM

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.

0
Jack
Telerik team
answered on 18 Oct 2011, 01:48 PM
Hi Hector,

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 If
End Sub

This 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.

0
Hector
Top achievements
Rank 1
answered on 18 Oct 2011, 03:10 PM

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.

0
Jack
Telerik team
answered on 20 Oct 2011, 12:54 PM
Hello Hector,

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.

0
Rawad
Top achievements
Rank 2
answered on 27 Jun 2014, 11:58 AM
Dear

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
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 02 Jul 2014, 10:46 AM
Hello Rawad,

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
 
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
 
0
shah
Top achievements
Rank 1
answered on 21 Oct 2019, 04:11 AM
Dear sir,
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.
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 23 Oct 2019, 08:27 AM
Hello, Shah,      

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

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
GridView
Asked by
Hector
Top achievements
Rank 1
Answers by
Emanuel Varga
Top achievements
Rank 1
Jack
Telerik team
Hector
Top achievements
Rank 1
Rawad
Top achievements
Rank 2
Dess | Tech Support Engineer, Principal
Telerik team
shah
Top achievements
Rank 1
Share this question
or