Click to See Complete Forum and Search --> : [2.0] Repeating, Databound Form Control Needed
wey97
Sep 25th, 2007, 09:37 AM
I have a Form on which I need to show repeating rows of data bound to a database. I can't use a datagrid because I have several rows of textboxes, with buttons, checkboxes, dropdowns, and labels associated with each row.
(If you're familiar with Microsoft Access, it's simple to design a form template for a row and you can set the controls to repeat in any layout style)
My only thought was to use the TableLayoutPanel control and create the other controls and set their values at runtime, adding a row to the panel for each record.
Is there a better way to do this?
[Edit]
I'm using 2.0 so I meant DataGridView, not DataGrid.
jmcilhinney
Sep 26th, 2007, 02:48 AM
The DataGridView allows you to embed basically any control you like in a cell, so you could use one of those. That said, the DataGrid can do this too but it's much more painful to implement.
If you don't just want straight rows as you get in a grid then you could check out the DataRepeater class in the QSS WFC library from the link in my signature.
wey97
Sep 26th, 2007, 08:08 AM
The DataGridView allows you to embed basically any control you like in a cell, so you could use one of those. That said, the DataGrid can do this too but it's much more painful to implement.
If you don't just want straight rows as you get in a grid then you could check out the DataRepeater class in the QSS WFC library from the link in my signature.
I meant DataGridView not DataGrid since I'm in 2.0. The rows have straight borders, there are just several rows of controls in each row that repeats, so it's going to be a serious pain adding and positioning them dynamically.
I have about 38 controls for each row, and they don't all have definite column boundaries, unless I can "merge" cells.
Maybe I could create a user control as my template and add the user control to the DataGridView.
jmcilhinney
Sep 26th, 2007, 08:45 AM
Did you check out the QSS DataRepeater? It basically allows you to create multiple instances of a UserControl of any configuration for multiple records.
wey97
Sep 26th, 2007, 08:47 AM
Did you check out the QSS DataRepeater? It basically allows you to create multiple instances of a UserControl of any configuration for multiple records.
I did. It looks rather awesome. Just depends if my client will allow me to use a 3rd party control or not. They can be picky at times :rolleyes:
wey97
Sep 26th, 2007, 05:04 PM
Apparently I can't use third party controls :(
So far I have MyUserControl inheriting from UserControl.
I have MyDataGridViewColumn inheriting from DataGridViewColumn and MyDataGridViewCell inheriting from DataGridViewCell.
What I don't know is what method to override in MyDataGridViewCell to output or render MyUserControl to the DataGridView.
jmcilhinney
Sep 26th, 2007, 06:05 PM
You also have to inherit your UserControl and implement the IDataGridViewEditingControl interface. Here (http://msdn2.microsoft.com/en-us/library/7tas5c80.aspx)'s an MSDN example for the DateTiePicker control.
wey97
Sep 27th, 2007, 03:45 PM
You also have to inherit your UserControl and implement the IDataGridViewEditingControl interface. Here (http://msdn2.microsoft.com/en-us/library/7tas5c80.aspx)'s an MSDN example for the DateTiePicker control.
Right, I had found this but wasn't sure if that would be the best way to do what I wanted since MyUserControl had multiple control instances instead of just one control like the DateTimePicker. I couldn't see how I could use the properties like EditingControlFormattedValue and other "value" type properties implemented by the IDataGridViewEditingControl interface. What I did for the time being is just let that refer to the primary key for the row.
Now, when the grid is displayed, obviously only the primary key value is shown in the DataGridViewCell until I double click the cell and editing begins. The user control is displayed and I see my multiple buttons, textboxes, labels, etc.
The only problem with that is I'd like to see all of the controls, all the time, not just when a row is being edited.
jmcilhinney
Sep 27th, 2007, 06:05 PM
Here's how a DataGridView works. When it is first displayed it contains no controls at all. Each cell is basically a rendered image of the cell contents. When you start editing a cell a control of the appropriate type is created, embedded in the cell and that's where you edit the data. When you end the editing session the appropriate value is pushed from the control to the underlying cell and the control is removed. That means that you now see the rendered image of the cell again. If you then start editing another cell, if the required control is of the same type then the same control will be used to edit the new cell, thus saving the time and resources it would take to create a new control.
The upshot of all this is that if you want to see all your controls in a cell when you're not editing then you have to implement your cell class to render an image of your control.
wey97
Oct 1st, 2007, 09:24 AM
Here's how a DataGridView works. When it is first displayed it contains no controls at all. Each cell is basically a rendered image of the cell contents. When you start editing a cell a control of the appropriate type is created, embedded in the cell and that's where you edit the data. When you end the editing session the appropriate value is pushed from the control to the underlying cell and the control is removed. That means that you now see the rendered image of the cell again. If you then start editing another cell, if the required control is of the same type then the same control will be used to edit the new cell, thus saving the time and resources it would take to create a new control.
The upshot of all this is that if you want to see all your controls in a cell when you're not editing then you have to implement your cell class to render an image of your control.
I inherited the cell class from DataGridViewTextBoxCell just to get things to work correctly. I tried to inherit my cell from DataGridViewCell but couldn't get the user control to show, I'm guessing because I didn't override or handle the proper methods.
Which should I inherit from and what do I override/handle to show the user control when not in edit mode?
jmcilhinney
Oct 1st, 2007, 06:05 PM
If you don't want to use the functionality of the DataGridViewTextBoxCell class then you should not inherit it. I suggest that you read the documentation for the DataGridViewCell class. It will tell you what each member is for. Just note that you will NOT be showing your UserControl in the cells when not in edit mode. The idea is that you draw an appropriate representation of your control, which may or may be exactly as it actually looks, using GDI+. It's the fact that the grid doesn't ever actually contain more than one embedded control that prevents it grinding to a halt. You need to read to learn. Go to MSDN and read about the DGV control.
wey97
Oct 2nd, 2007, 01:57 PM
If you don't want to use the functionality of the DataGridViewTextBoxCell class then you should not inherit it. I suggest that you read the documentation for the DataGridViewCell class. It will tell you what each member is for. Just note that you will NOT be showing your UserControl in the cells when not in edit mode. The idea is that you draw an appropriate representation of your control, which may or may be exactly as it actually looks, using GDI+. It's the fact that the grid doesn't ever actually contain more than one embedded control that prevents it grinding to a halt. You need to read to learn. Go to MSDN and read about the DGV control.
I had read as you suggested. All of the code and examples I found inheriting from DataGridViewCell all override the OnPaint method.
So if I have to paint it here goes:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.Drawing;
using WindowsControlLibrary1;
namespace WindowsApplication1
{
public class MyDataGridViewCell :
//System.Windows.Forms.DataGridViewTextBoxCell
System.Windows.Forms.DataGridViewCell
{
public MyDataGridViewCell(): base(){}
public override Type FormattedValueType
{
get{ return typeof(MyUserControl); }
}
public MyUserControl MyControl
{
get { return this.DataGridView.EditingControl as MyUserControl; }
}
public override Type EditType
{
get{ return typeof(MyUserControl); }
}
protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, System.ComponentModel.TypeConverter valueTypeConverter, System.ComponentModel.TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
{
value = MyControl;
return value;
}
protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{
SolidBrush cellBackground = new SolidBrush(cellStyle.BackColor);
graphics.FillRectangle(cellBackground, cellBounds);
cellBackground.Dispose();
if (MyControl != null)
{
foreach (Control c in MyControl.Controls)
{
Rectangle rt = cellBounds;
rt.X += c.Location.X;
rt.Y += c.Location.Y;
rt.Width = c.Width;
rt.Height = c.Height;
if (c is TextBox)
TextBoxRenderer.DrawTextBox(graphics, rt, c.Text, c.Font, TextBoxState.Normal);
if (c is Button)
ButtonRenderer.DrawButton(graphics, rt, c.Text, c.Font, false, PushButtonState.Normal);
if (c is Label)
TextRenderer.DrawText(graphics, c.Text, c.Font, rt.Location, c.ForeColor);
}
}
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
}
public override Type ValueType
{
get { return typeof(MyUserControl); }
}
}
}
This won't fit my needs because I want to display the exact values of all the user controls at all times like the QSS DataRepeater control you suggested.
vbforums.com
Copyright Internet.com Inc., All Rights Reserved.