I have message is too long to fit in the column. I have table with four columns my fourth column is "Message" which has string long string and it doesnot fit in columnwidth. I want to Make the text in column as Warp so that all the text is visible to the user.
ListViewItem lv = new ListViewItem();
lv.Text = det_view.filename;
lv.SubItems.Add(det_view.number.ToString());
lv.SubItems.Add(det_view.Date_Time.ToString());
lv.SubItems.Add(det_view.Message); // here the string too long and need wrap the message
listView1.Items.Add(lv);
Regards
Short of having your listviewitems ownerdrawn, you might have a look at ObjectListView. It will wordwrap just fine and may suite your needs.
If You feel some license problems with ObjectListView, you can use native .Net ListView.
It can also wordwrap in view=Details and setting smallImageList
(with picture height = 32 or more).
You may try Better ListView component, which supports multi-line items with varous text wrapping and trimming methods:
Here is a class inheriting from ListView that will grow your row height to fit the text in a column. I believe the default will not word break. So you would need to implement wordbreak if that's something you want.
class WordWrapListView : ListView
{
private const int LVM_FIRST = 0x1000;
private const int LVM_INSERTITEMA = (WordWrapListView.LVM_FIRST + 7);
private const int LVM_INSERTITEMW = (WordWrapListView.LVM_FIRST + 77);
private Graphics graphics;
public WordWrapListView()
{
this.graphics = this.CreateGraphics();
base.View = View.Details;
this.AutoSizeRowHeight = true;
}
//overriding WndProc because there are no item added events
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
// Detect item insert and adjust the row size if necessary based on the text
// add in LVM_DELETEITEM and LVM_DELETEALLITEMS and reset this.rowHeight if you want to reduce the row height on remove
case WordWrapListView.LVM_INSERTITEMA:
case WordWrapListView.LVM_INSERTITEMW:
{
ListViewItem lvi = this.Items[this.Items.Count - 1];
for (int i = 0; i< lvi.SubItems.Count; ++i)
{
ListViewItem.ListViewSubItem lvsi = lvi.SubItems[i];
string text = lvsi.Text;
int tmpHeight = 0;
int maxWidth = this.Columns[i].Width;
SizeF stringSize = this.graphics.MeasureString(text, this.Font);
if (stringSize.Width > 0)
{
tmpHeight = (int)Math.Ceiling((stringSize.Width / maxWidth) * stringSize.Height);
if (tmpHeight > this.rowHeight)
{
this.RowHeight = tmpHeight;
}
}
}
}
break;
default:
break;
}
base.WndProc(ref m);
}
private void updateRowHeight()
{
//small image list hack
ImageList imgList = new ImageList();
imgList.ImageSize = new Size(this.rowHeight, this.rowHeight);
this.SmallImageList = imgList;
}
[System.ComponentModel.DefaultValue(true)]
public bool AutoSizeRowHeight { get; set; }
private int rowHeight;
public int RowHeight
{
get
{
return this.rowHeight;
}
private set
{
//Remove value > this.rowHeight if you ever want to scale down the height on remove item
if (value > this.rowHeight && this.AutoSizeRowHeight)
{
this.rowHeight = value;
this.updateRowHeight();
}
}
}
// only allow details view
[Browsable(false), Bindable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)]
public new View View
{
get
{
return base.View;
}
set
{
}
}
}
May not be what you need but my solution was to switch to the build-in DataGridView control.
Related
I have a dictionary of buttons and also an null variable button. When you click on an button from the dictionary, we get the values that should be sent to an empty variable.
public static Button selectedfigure=null;
public Dictionary<(int x, int y), Button> _Panels = new Dictionary<(int x, int y), Button>();
public void Fillboard()
{
for (int x = 0; x < 8; x++)
{
for (int y = 0; y < 8; y++)
{
_Panels[(x, y)] = new Button()
{
Height = 64,
Width = 64,
Location = new Point(x * 64, y * 64),
BackColor = CalculateBackColor(x,y),
BackgroundImage = CalculateBackimage(x,y)
};
Controls.Add(_Panels[(x, y)]);
}
}
}
Your question is about how to interact with Mouse events on your "board". The answer is to subscribe to Mouse events like Click for each control you add. Your code is using a normal Button but will be much simpler if you make a custom class that inherits Button or preferably PictureBox and this way each instance keeps track of its own X-Y, color, and image.
Also, instead of using a Dictionary lookup and setting Location properties yourself, you might try an 8x8 TableLayoutPanel for the board, then iterate all its 8 columns and rows with methods that take column and row as arguments.
The mouse events can be subscribed to in the addSquare method.
private void addSquare(int column, int row)
{
var color = ((column + row) % 2) == 0 ? Color.White : Color.Black;
var square = new Square
{
BackColor = color,
Column = column,
Row = row,
Size = new Size(80, 80),
Margin = new Padding(0),
Padding = new Padding(10),
Anchor = (AnchorStyles)0xf,
SizeMode = PictureBoxSizeMode.StretchImage,
};
tableLayoutPanel.Controls.Add(square, column, row);
// Hook the mouse events here
square.Click += onSquareClicked;
square.MouseHover += onSquareMouseHover;
}
Before and after iterating the TableLayoutPanel with addSquare
Changing the value of the Square.Piece property will choose an image from a resource file.
private void initImage(int column, int row)
{
var square = (Square)tableLayoutPanel.GetControlFromPosition(column, row);
if (square.BackColor == Color.Black)
{
switch (row)
{
case 0:
case 1:
case 2:
square.Piece = Piece.Black;
break;
case 5:
case 6:
case 7:
square.Piece = Piece.Red;
break;
default:
square.Piece = Piece.None;
break;
}
}
}
Before and after iterating the TableLayoutPanel with initImage
Mouse event handlers are simple now:
private void onSquareMouseHover(object sender, EventArgs e)
{
var square = (Square)sender;
_tt.SetToolTip(square, square.ToString());
}
private void onSquareClicked(object sender, EventArgs e)
{
var square = (Square)sender;
MessageBox.Show($"Clicked: {square}");
}
ToolTip _tt = new ToolTip();
The Square class is uncomplicated, just a few lines of code.
class Square : PictureBox // Gives more visual control than Button
{
public int Column { get; internal set; }
public int Row { get; internal set; }
Piece _piece = Piece.None;
public Piece Piece
{
get => _piece;
set
{
if(!Equals(_piece, value))
{
_piece = value;
switch (_piece)
{
case Piece.None:
Image = null;
break;
case Piece.Black:
Image = Resources.black;
break;
case Piece.Red:
Image = Resources.red;
break;
}
}
}
}
public override string ToString() =>
Piece == Piece.None ?
$"Empty {BackColor.Name} square [column:{Column} row:{Row}]" :
$"{Piece} piece [column:{Column} row:{Row}]";
}
enum Piece { None, Black, Red };
Edited (in response to Jeremy's excellent suggestion)
Where and how to call the methods to initialize the board:
public MainForm()
{
InitializeComponent();
// Board is a TableLayoutPanel 8 x 8
tableLayoutPanel.AutoSize = true;
tableLayoutPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
// Add squares
IterateBoard(addSquare);
// Add pieces
IterateBoard(initImage);
}
void IterateBoard(Action<int, int> action)
{
for (int column = 0; column < 8; column++)
{
for (int row = 0; row < 8; row++)
{
action(column, row);
}
}
}
I don't know exactly which is your problem. I think you need know which button is pressed in your matrix.
You can add the controls in the same way but instead the use of _Panels dictionary, you can use Tag property of button to store a Point with the x,y coordinates:
for (int x = 0; x < 8; x++)
{
for (int y = 0; y < 8; y++)
{
var button = new Button
{
Height = 64,
Width = 64,
Location = new Point(x * 64, y * 64),
BackColor = CalculateBackColor(x,y),
BackgroundImage = CalculateBackimage(x,y),
Tag = new Point(x, y)
};
button.Click += OnButtonClick;
Controls.Add(button);
}
}
In the click event handler of the button:
private void OnButtonClick(object sender, EventArgs e)
{
var button = (Button)sender;
var point = (Point)button.Tag;
// Here you have x,y coordinates of clicked button
}
I wrote one project. I used DataGridViewAutoFilter library for filtering. But I have problem.
For filtering Drop-Down Filter List for a DataGridView Column Header Cell size(width) are very small. It come automatic size.
How to resize Drop-Down Filter List for a DataGridView Column Header Cell for filtering?
private void dataGridView1_BindingContextChanged(object sender, EventArgs e)
{
if (dataGridView1.DataSource == null) return;
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
col.HeaderCell = new DataGridViewAutoFilterColumnHeaderCell(col.HeaderCell);
}
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
}
I found the solution : We must change SetDropDownList properties : DataGridViewColumnHeader.cs in DataGridViewAutoFilter.dll.İt is open source.
private void SetDropDownListBoxBounds()
{
Debug.Assert(filters.Count > 0, "filters.Count <= 0");
// Declare variables that will be used in the calculation,
// initializing dropDownListBoxHeight to account for the
// ListBox borders.
Int32 dropDownListBoxHeight = 6; // You must change!!!!!
Int32 currentWidth = 0;
Int32 dropDownListBoxWidth = 0;
Int32 dropDownListBoxLeft = 0;
// For each formatted value in the filters dictionary Keys collection,
// add its height to dropDownListBoxHeight and, if it is wider than
// all previous values, set dropDownListBoxWidth to its width.
using (Graphics graphics = dropDownListBox.CreateGraphics())
{
foreach (String filter in filters.Keys)
{
SizeF stringSizeF = graphics.MeasureString(
filter, dropDownListBox.Font);
dropDownListBoxHeight += (Int32)stringSizeF.Height;
currentWidth = (Int32)stringSizeF.Width;
if (dropDownListBoxWidth < currentWidth)
{
dropDownListBoxWidth = currentWidth;
}
}
}
// Increase the width to allow for horizontal margins and borders.
dropDownListBoxWidth += 40; //You must change !!!
// Constrain the dropDownListBox height to the
// DropDownListBoxMaxHeightInternal value, which is based on
// the DropDownListBoxMaxLines property value but constrained by
// the maximum height available in the DataGridView control.
if (dropDownListBoxHeight > DropDownListBoxMaxHeightInternal)
{
dropDownListBoxHeight = DropDownListBoxMaxHeightInternal;
// If the preferred height is greater than the available height,
// adjust the width to accommodate the vertical scroll bar.
dropDownListBoxWidth += SystemInformation.VerticalScrollBarWidth;
}
// Calculate the ideal location of the left edge of dropDownListBox
// based on the location of the drop-down button and taking the
// RightToLeft property value into consideration.
if (this.DataGridView.RightToLeft == RightToLeft.No)
{
dropDownListBoxLeft = DropDownButtonBounds.Right -
dropDownListBoxWidth + 1;
}
else
{
dropDownListBoxLeft = DropDownButtonBounds.Left - 1;
}
// Determine the left and right edges of the available horizontal
// width of the DataGridView control.
Int32 clientLeft = 1;
Int32 clientRight = this.DataGridView.ClientRectangle.Right;
if (this.DataGridView.DisplayedRowCount(false) <
this.DataGridView.RowCount)
{
if (this.DataGridView.RightToLeft == RightToLeft.Yes)
{
clientLeft += SystemInformation.VerticalScrollBarWidth;
}
else
{
clientRight -= SystemInformation.VerticalScrollBarWidth;
}
}
// Adjust the dropDownListBox location and/or width if it would
// otherwise overlap the left or right edge of the DataGridView.
if (dropDownListBoxLeft < clientLeft)
{
dropDownListBoxLeft = clientLeft;
}
Int32 dropDownListBoxRight =
dropDownListBoxLeft + dropDownListBoxWidth + 1;
if (dropDownListBoxRight > clientRight)
{
if (dropDownListBoxLeft == clientLeft)
{
dropDownListBoxWidth -=
dropDownListBoxRight - clientRight;
}
else
{
dropDownListBoxLeft -=
dropDownListBoxRight - clientRight;
if (dropDownListBoxLeft < clientLeft)
{
dropDownListBoxWidth -= clientLeft - dropDownListBoxLeft;
dropDownListBoxLeft = clientLeft;
}
}
}
// Set the ListBox.Bounds property using the calculated values.
dropDownListBox.Bounds = new Rectangle(dropDownListBoxLeft,
DropDownButtonBounds.Bottom, // top of drop-down list box
dropDownListBoxWidth, dropDownListBoxHeight);
}
/// <summary>
/// Gets the actual maximum height of the drop-down list, in pixels.
/// The maximum height is calculated from the DropDownListBoxMaxLines
/// property value, but is limited to the available height of the
/// DataGridView c`enter code here`ontrol.
I am adding Rectangle from grid cell values that is being entered by user directly in grid rows. When i modify value of specific column say Thickness i.e Height then then it increases Height of selected row rectangle but it doesnt rearrange all rectangle below it exactly after the selected row rectangle.
In xaml.cs
public class MyLayer : INotifyPropertyChanged
{
public string Thickness { get; set; }
public string OffsetRight { get; set; }
public string OffsetLeft { get; set; }
public string Material { get; set; }
public string MaterialPopup { get; set; }
public Rectangle rectangle { get; set; }
public GlassRectangle GlassRectangle { get; set; }
public MaterialLayer()
{
GlassRectangle = new GlassRectangle();
}
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
add { }
remove { }
}
}
public class GlassRectangle
{
public Rectangle Rectangle { get; set; }
public double Top = 0;
public GlassRectangle()
{
Rectangle = new Rectangle();
}
}
private void gridInner_CellValueChanged(object sender, DevExpress.Xpf.Grid.CellValueChangedEventArgs e)
{
string cellValue = string.Empty;
MyLayer currentLayer = ((MyLayer)(e.Row));
if (e.Column.HeaderCaption.ToString() == "Thickness")
{
cellValue =(e.Value.ToString());
//there is alredy a rectangle - means this is edit mode
if (currentLayer.rectangle != null)
{
currentLayer.rectangle.Height = Convert.ToDouble(cellValue);
currentLayer.rectangle.Stroke = new SolidColorBrush(Color.FromRgb(0, 255, 0));
}
//else this is insert mode
else
{
currentLayer.rectangle = CreateRectangle(cellValue);
}
}
}
protected Rectangle CreateRectangle(string cellval)
{
Rectangle newrect = new Rectangle();
newrect.Stroke = Brushes.Red;
newrect.StrokeThickness = 1;
if (cellval.ToString().Contains("."))
{
newrect.Height = Convert.ToDouble(cellval) * 100;
}
else
{
newrect.Height = Convert.ToDouble(cellval);
}
newrect.Width = width;
Canvas.SetLeft(newrect, 100);
double canvasTop = 0.0;
if (canvasboard.Children.Count > 0)
{
var lastChildIndex = canvasboard.Children.Count - 1;
var lastChild = canvasboard.Children[lastChildIndex] as FrameworkElement;
if (lastChild != null)
//lastChild.Height-1: so that it come extactly on existing if set to +1 it comes below first rectangle
canvasTop = Canvas.GetTop(lastChild) + lastChild.Height - 1;
}
Canvas.SetTop(newrect, canvasTop);
val = val + 1;
newrect.Tag = val;
canvasboard.Children.Add(newrect);
//rectangle = rect;
foreach (UIElement ui in canvasboard.Children)
{
if (ui.GetType() == typeof(Rectangle))
{
itemstoremove.Add(ui);
}
}
return newrect;
}
NEW EVENT Method:
private void gridMaterialInner_CellValueChanged(object sender, DevExpress.Xpf.Grid.CellValueChangedEventArgs e)
{
string cellValue = string.Empty;
string cellOldValue = string.Empty;
MyLayer currentLayer = ((MyLayer)(e.Row));
if (e.Column.HeaderCaption.ToString() == "Thickness")
{
//current cell value
cellValue =(e.Value.ToString());// GetRowCellValue(e.RowHandle, gridMaterialInner.Columns["LastName"]).ToString();
//there is alredy a rectangle - means this is edit mode
double currentheight = 0.0;
double oldht = 0.0;
// old cell value
if (e.OldValue != null)
{
cellOldValue = (e.OldValue.ToString());
}
if (currentLayer.rectangle != null)
{
if (cellValue.ToString().Contains("."))
{
currentheight = Convert.ToDouble(cellValue) * 100;
}
else
{
currentheight = Convert.ToDouble(cellValue) * 100;
}
if (cellOldValue.ToString().Contains("."))
{
oldht = Convert.ToDouble(cellOldValue) * 100;
}
else if(cellOldValue!=string.Empty)
{
oldht = Convert.ToDouble(cellOldValue) * 100;
}
currentLayer.rectangle.Height = currentheight;
currentLayer.rectangle.Stroke = new SolidColorBrush(Color.FromRgb(0, 255, 0));
//Refresh();
//Get the index of selected row
int layerIndex = materialBindlist.IndexOf(currentLayer);
for(int i = layerIndex; i < materialBindlist.Count-1; i++)
{
//set the top position of all other rectangles that are below selected rectangle/row
//(Current-Old)+Top
Canvas.SetTop(materialBindlist[i + 1].rectangle, (currentheight - oldht) + materialBindlist[i + 1].GlassRectangle.Top);
//Canvas.SetTop(materialBindlist[i].rectangle, (currentheight - oldht) + materialBindlist[i + 1].GlassRectangle.Top);
}
}
//else this is insert mode
else
{
//MaterialLayer object
currentLayer.rectangle = CreateRectangle(cellValue);
//store Top & Rectangle object in GlassRectangle class which is referenced in MaterialLayer class
currentLayer.GlassRectangle.Rectangle = currentLayer.rectangle;
currentLayer.GlassRectangle.Top = canvasTop;
}
}
}
This create rectangle one after other like Stacked item on canvas. But when i modify the value of Thickness column which is Height of Rectangle it reflects on canvas but the Other Rectangle below must appear after the Changed Height of current rectangle.
Note: I cant use WrapPanel in my application. Just to modify existing code using Canvas.
Help Appreciated!
Modified For Loop in CellChange Event:
int layerIndex = materialBindlist.IndexOf(currentLayer);
for(int i = layerIndex; i < materialBindlist.Count-1; i++)
{
//set the top position of all other rectangles that are below selected rectangle/row
//(Current-Old)+Top
double top=Convert.ToDouble((currentHeight - oldHeight) + materialBindlist[i + 1].GlassRectangle.Top);
Canvas.SetTop(materialBindlist[i + 1].rectangle,top);
materialBindlist[i + 1].GlassRectangle.Top = top;
}
What you're looking for can be done even with a Canvas however you should really consider using something like an ItemsControl for this.
Solution when forced to use Canvas:
private void Refresh() {
for (int i = 1; i < canvasboard.Children.Count; ++i) {
var currentElement = canvasboard.Children[i] as FrameworkElement;
var previousElement = canvasboard.Children[i - 1] as FrameworkElement;
if (currentElement == null || previousElement == null)
return;
var requiredTop = Canvas.GetTop(previousElement) + previousElement.Height - 1;
if (Math.Abs(Canvas.GetTop(currentElement) - requiredTop) > 0.0)
Canvas.SetTop(currentElement, requiredTop);
}
}
Now call this function "after" you change the size of an existing element in the Canvas and it will re-position the elements accordingly to suit the new dimension. In your code, it would be called from the gridInner_CellValueChanged(...) function after you set the new height in "edit" mode.
What you should try to do:
If your able to persuade whoever you need to and get to use something like an ItemsControl, this will be so much simpler.
say a rough example:
xaml could be:
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
with Items declared as public ObservableCollection<Rectangle> Items { get; set; } in code.
Now your Add() function could just be:
private void Add() {
var rect = new Rectangle {
Stroke = Brushes.Red,
StrokeThickness = 1,
Height = Convert.ToDouble(txtheight.Text),
Width = 100
};
Items.Add(rect);
}
and as for updates when your editing existing control's that would be automatic in this case. There is no hard-coded positioning as the Layout container takes care of all that mess for you.
You can ofcourse switch the Items collection type to your own custom control type MyLayer and with it implementing INPC, changes would still continue to be automatic. You'd have to define a DataTemplate now to get your Item to be rendered but that's like 3 lines of work in just xaml.
You can also just work of the Items property directly when needing to tweak an exisiting control than having to reference the ItemsControl in code-behind. Binding's should take care of the updates to the view automatically.
Modified for loop in Cell Change Event:
int layerIndex = materialBindlist.IndexOf(currentLayer);
for(int i = layerIndex; i < materialBindlist.Count-1; i++)
{
//set the top position of all other rectangles that are below selected rectangle/row
//(Current-Old)+Top
double top=Convert.ToDouble((currentHeight - oldHeight) + materialBindlist[i + 1].GlassRectangle.Top);
Canvas.SetTop(materialBindlist[i + 1].rectangle,top);
materialBindlist[i + 1].GlassRectangle.Top = top;
}
it works now..!Thanks to all!
I have a hidden control which contains a textbox control and I want to set the text property of the textbox but i get an NullReferenceException. However if I show the control, set the value and then hide it then i get no exception.
miStatus1.Show();
miStatus1.ioItem1.popIoItem(caseState);
miStatus1.Hide();
However this feels like a really unclean and not very elegant way to do it. And i'm seeing some flickering because i have to do this to 4 controls with up to 8 textboxes on each.
Is there any way to set the text propery of the textboxes while the control is hidden? Or is it perhaps a better idea to populate my textboxes when showing the control? And will this slow down my application as it needs to populate everytime the control is shown?
popIoItem - code
public void popIoItem(object obj){
if (ioType == 1)
{
tb.Text = (string)obj;
}
}
My interface
I'm trying to create the menu to the right and on each pressing of the categories the menus slide up/down and i hide/show the proper user control with the textboxes and other io-elements.
More code
When one of the boxes to the left is click'ed the following method is run:
public void openMenu(int caseNum)
{
caseDB.casesDataTable chosenCase;
chosenCase = _casesAdapter.GetDataByID(caseNum);
string caseName = "";
int caseOwner = -1;
DateTime caseDate = DateTime.Today;
string caseDesc = "";
int caseState = -1;
foreach (caseDB.casesRow casesRow in chosenCase)
{
if (!casesRow.IscaseNameNull())
caseName = casesRow.caseName;
if (!casesRow.IscaseCreatedByNull())
caseOwner = casesRow.caseCreatedBy;
if (!casesRow.IscaseCreatedNull())
caseDate = casesRow.caseCreated;
if (!casesRow.IscaseDescNull())
caseDesc = casesRow.caseDesc;
if (!casesRow.IscaseStateNull())
caseState = casesRow.caseState;
}
int caseJobs = (int)_jobsAdapter.JobCount(caseNum);
string caseStateStr = Enum.GetName(typeof(caseState), caseState);
caseInfoMenu1.popMenu(caseName, caseOwner, caseDate, caseDesc,caseJobs,caseStateStr);
}
The caseInfoMenu is the right menu. It consists of some drawing and mouse logic that draws the menu and handles hit-detection. Besides this it contains 4 user controls, one for each of the vertical tabs.
public void popMenu(string caseName, int caseOwner ,DateTime caseDate, string caseDesc, int caseJobs, string caseState)
{
marked = 0;
miGeneral1.Show();
miEconomy1.Hide();
miStatus1.Hide();
miHistory1.Hide();
miGeneral1.ioItem1.popIoItem(caseName);
miGeneral1.ioItem2.popIoItem(caseOwner.ToString());
miGeneral1.ioItem3.popIoItem(caseDate.ToShortDateString());
miGeneral1.ioItem4.popIoItem(caseJobs.ToString());
miGeneral1.ioItem5.popIoItem(caseDesc.ToString());
//miStatus1.ioItem1.popIoItem(caseState);
//This is commented out because it makes the application crash. However if I show miStatus1, set the value and hide it, it does not crash.
this.Invalidate();
}
Inside each of these user controls I have io-items user controls which essentially draws a blue box and puts a control in front of if ie. the textbox.
public partial class ioItem : UserControl
{
public int ioType { get; set; }
public int ioPadding { get; set; }
RichTextBox tb;
public ioItem()
{
InitializeComponent();
}
public void popIoItem(object obj){
if (ioType == 1)
{
tb.Text = (string)obj;
}
}
private void ioItem_Load(object sender, EventArgs e)
{
switch (ioType)
{
case 1:
tb = new RichTextBox();
tb.Location = new System.Drawing.Point(ioPadding, ioPadding);
tb.Name = "textbox";
tb.Size = new Size(this.Size.Width - (ioPadding * 2), this.Size.Height - (ioPadding * 2));
tb.BorderStyle = BorderStyle.None;
tb.Visible = true;
tb.BackColor = Color.FromArgb(255, 184, 198, 208);
tb.Font = new Font("Microsoft Sans Serif", 7);
this.Controls.Add(tb);
break;
case 2:
historyCtrl hiCtrl = new historyCtrl();
hiCtrl.Location = new Point(0,0);
hiCtrl.Size = new Size(this.Width, this.Height);
hiCtrl.Name = "history";
hiCtrl.Visible = true;
hiCtrl.BackColor = Color.FromArgb(255, 184, 198, 208);
this.Controls.Add(hiCtrl);
break;
default:
goto case 1;
}
}
}
Try checking the code with debugger..May be there is something other going on there? NullReference means that you try to do something with object that doesn't exist. Show/Hide just set Visible property of the control to true/false in normal situation(without custom overload/changes of Control class).
So i figured out what was wrong. The problem was something else than what I initially expected. The reason why it didn't work was because I created my textbox controls in the Load_event. When I tried to set the value of the text property of the textbox controls they hadn't been created yet. The reason why I had created the user controls containing the textboxes this way was in order to make it easy to drag them into the screen in the Designer. I found this discussion 'UserControl' constructor with parameters in C#, which showed me another way of doing it and now it works.
I have a datagridview that is docked and anchored with a panel on a Winform. When I resize the form, the datagridview resizes as expected, but the columns do not resize to fit the datagridview. Instead, I am left with the background colour of the Datagridview.
How can I get the columns to grow with the control?
Thanks.
You could always use the AutoSizeColumnsMode property
This property lets you configure the control so that column widths are automatically adjusted either to fill the control or to fit cell contents. Size adjustments occur in fill mode whenever the width of the control changes.
There's a lot more information on the MSDN page for this.
You can set AutoSizeMode property of one of the columns to be Fill. Then this column will always resize itself to fill all the available space not used by other columns.
private void dataGrid_SizeChanged(object sender, EventArgs e)
{
ResizeGridColumns();
}
private void ResizeGridColumns()
{
//get sum of non-resizable columns width
int diffWidth = 0;
foreach (DataGridViewColumn col in this.dataGrid.Columns)
{
if (col.Resizable == DataGridViewTriState.False && col.Visible) diffWidth += col.Width;
}
//calculate available width
int totalResizableWith = this.dataGrid.Width - diffWidth;
//resize column width based on previous proportions
this.dataGrid.ColumnWidthChanged -= new DataGridViewColumnEventHandler(dataGrid_ColumnWidthChanged);
for (int i = 0; i < this.colWidthRaport.Count; i++)
{
try
{
if (this.dataGrid.Columns[i].Resizable != DataGridViewTriState.False && this.dataGrid.Columns[i].Visible)
{
this.dataGrid.Columns[i].Width = (int)Math.Floor((decimal)totalResizableWith / this.colWidthRaport[i]);
}
}
catch { }
}
this.dataGrid.ColumnWidthChanged += new DataGridViewColumnEventHandler(dataGrid_ColumnWidthChanged);
}
private void dataGrid_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
{
CalculateGridColWidthsRaport();
}
/// <summary>Calculates the proportions between grid width and column width</summary>
private void CalculateGridColWidthsRaport()
{
//get sum of non-resizable columns width
int diffWidth = 0;
int colWidthsSum = 0;
foreach (DataGridViewColumn col in this.dataGrid.Columns)
{
if (col.Visible)
{
colWidthsSum += col.Width;
if (col.Resizable == DataGridViewTriState.False) diffWidth += col.Width;
}
}
colWidthsSum += 24;
//calculate available with
int totalResizableWith = colWidthsSum - diffWidth;// this.dataGrid.Width - diffWidth;
if (this.ParentForm.WindowState == FormWindowState.Maximized)
{
totalResizableWith = this.dataGrid.Width - diffWidth;
}
//calculate proportions of each column relative to the available width
this.colWidthRaport = new List<decimal>();
foreach (DataGridViewColumn col in this.dataGrid.Columns)
{
this.colWidthRaport.Add((decimal)totalResizableWith / (decimal)col.Width);
}
}