C# - Listbox - Can the Listbox vertical height grow automatically? - c#

I want to select a number of files using OpenDialog and display them in a listbox. If I have more file paths than can fit in the listbox, I'd like the list box to automatically grow vertically to fit all of the filenames.
How can this be done, please? Thank you for your help.
foreach (string FileName in oOpenDialog.FileNames)
{
//lstbx_Box1.IntegralHeight = false; //This doesn't auto-grow the list box.
lstbx_Box1.Items.Add(Path.GetFullPath(FileName));
}

Yep you can, since the height of listbox when having a single value is 21 you can add 21 for the height of listbox when a new item is added.
foreach (string FileName in oOpenDialog.FileNames)
{
lstbx_Box1.Height += 21;
lstbx_Box1.Items.Add(Path.GetFullPath(FileName));
}

Related

How to fill 56 comboBox with loop or something

I have 56 comboBox in my program and I need to fill all of them with the same information. The fastes way that I found is creating a private function for fill the comboBox. And I put 56 times the same function.
But my question is... I can do a loop for fill this 56 comboBox?
Assuming this question is about Windows Forms. The best way to do it is probably to have the similar naming convention for all ComboBox controls you're willing to fill with the same data. Fill them with items within for-loop, adding different suffix to the control you want to find before adding data.
// Lets say you have 56 ComboBox controls with names like : cbMyComboBox_1, cbMyComboBox_2, ..., cbMyComboBox_56
for (int i = 1; i <= 56; i++)
{
ComboBox comboBox = (ComboBox)this.Controls.Find
(string.Format("cbMyComboBox_{0}", i), true)[0];
ComboBoxFill(comboBox);
}
private void ComboBoxFill(ComboBox comboBox)
{
// Fill that ComboBox with data here
}
Of course you can.
foreach (var c in Controls)
{
if (c is ComboBox)
((ComboBox)c).Text = "I'm a combobox~";
}
try adding the same class to all 56 combobox, and create a function to populate then like:
$(".class").html(value of the options);

How to Get the Index of the First Item Showing in ListView in C#

Is there any way to get the index of the first item currently showing, when the list is scrollable?
I'm making a CharMap with some extensions and just found that ListView can't contain 64k items (see code below)
for (var i = char.MinValue; i < char.MaxValue; i++)
{
var c = Convert.ToChar(i);
if (!char.IsControl(c))
lv1.Items.Add(""+c);
}
so decided to load chars when scroll is at some appropriate points (ie first/last 15%) but ListView doesn't give absolute position of the scrollbar.
It does feel a little hackish, but maybe it will do the job:
int getFirstVisibleItem(ListView lv)
{
ListViewHitTestInfo HI;
for (int i = 0; i < Math.Min(lv.ClientSize.Width, lv.ClientSize.Height); i += 3)
{
HI = lv.HitTest(i, i);
if (HI.Item != null) return HI.Item.Index;
}
return -1;
}
This does not directly help with your scrolling issue but should find the first visible Item as you have asked. If your Items have extremely weird (ie non-square) shapes you may want to change the travesal code a little..
For your requirement implement ListView with custom scrollbar. So you have more control over your scroll position. You decide when to what action based on scroll position. This might be helpful Code

C# Listview Auto Column resize by both columns and header

I need a listview to auto-resize its columns based on both width of the headers and content, and every other answer only does one or the other.
Example:
listView1.GridLines = true;
// Create three items and three sets of subitems for each item.
ListViewItem item1 = new ListViewItem("item1asdfghjkl", 0);
item1.SubItems.Add("1");
item1.SubItems.Add("2");
item1.SubItems.Add("3");
ListViewItem item2 = new ListViewItem("item2", 1);
item2.SubItems.Add("4");
item2.SubItems.Add("5");
item2.SubItems.Add("6");
ListViewItem item3 = new ListViewItem("item3", 0);
item3.SubItems.Add("7");
item3.SubItems.Add("8");
item3.SubItems.Add("9");
// Create columns for the items and subitems.
// Width of -2 indicates auto-size.
listView1.Columns.Add("Item Column", -2, HorizontalAlignment.Left);
listView1.Columns.Add("Column 2", -2, HorizontalAlignment.Left);
listView1.Columns.Add("Column 3", -2, HorizontalAlignment.Left);
listView1.Columns.Add("Column 4", -2, HorizontalAlignment.Left);
//these two lines
listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
//Add the items to the ListView.
listView1.Items.AddRange(new ListViewItem[] { item1, item2, item3 });
the note here is that no matter which (or both) resize style, something is cut off, either a header or a content.
There doesn't even seem to be a reliable way to get the display size of the content to manually resize the columns and headers.
Anton Kedrov answer here - ListView AutoResizeColumns based on both Column content and header is best one but in my case i have a listview with more than 50 columns and i update its data frequently in this case i notice listview's this.AutoResizeColumns performs much faster work so i m writing this solution also
First Method by setting with to -2
public void AutoUpdateColumnWidth(ListView lv)
{
for (int i = 0; i <= lv.Columns.Count - 1; i++) {
lv.Columns(i).Width = -2;
}
}
Second method i used (less flicker on multiple calls)
public void AutoUpdateColumnWidth(ListView lv)
{
ListViewItem nLstItem = new ListViewItem(lv.Columns(0).Text);
for (int i = 1; i <= lv.Columns.Count - 1; i++) {
nLstItem.SubItems.Add(lv.Columns(i).Text);
}
v.Items.Add(nLstItem);
lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
lv.Items.RemoveAt(nLstItem.Index);
}
This is simple (although it took me a while to figure out)...
We know that the width must be at least as great as the column headers, so that we see all of the header text. Beyond that, the width can expand larger to accommodate contents. Hence, we do the following:
Autosize the columns to header.
Iterate through the columns and set the minimum width property for each column to the current column width (which guarantees your columns will never get too small to see the header).
From now on, autosize columns by content.
EDIT: My apologies, I forgot that I was not using the standard listview, but instead the 3rd party product BetterListView (a free version is available). The standard listview columns don't appear to support minimum width. I do recommend BetterListView highly as a great alternative (much better feature set and performance).

How to clear or update the content of an element in a grid in WPF

I have a WPF window with a grid with 2 rows and some columns with text and buttons, then when I click a button the code adds some rows and populates them with random textblocks and images via for loops. For example, the method I call to add a TextBlock with text s in the (i,j) cell of the grid is
public void createTextBlock(int i, int j, string s)
{
TextBlock tb = new TextBlock();
//Properties
tb.Foreground = Brushes.Navy;
tb.FontFamily = new FontFamily("Century Gothic");
tb.FontSize = 16;
tb.FontWeight = FontWeights.UltraBold;
tb.TextWrapping = TextWrapping.Wrap;
tb.VerticalAlignment = VerticalAlignment.Center;
tb.HorizontalAlignment = HorizontalAlignment.Center;
tb.Text = s;
//Add to the Grid
MyGrid.Children.Add(tb);
Grid.SetRow(tb, i);
Grid.SetColumn(tb, j);
}
and the method to add an image is similar. The problem is that when I click again, new textblocks and images are added above the old ones and I don't know how to update the content or clear it before adding another.
It is puzzling because the code (before adding rows) checks if the rows are more than 2, and if this is the case it clears all the exceeding rows:
if (MyGrid.RowDefinitions.Count > 2)
{
MyGrid.RowDefinitions.RemoveRange(2, MyGrid.RowDefinitions.Count-2);
}
but somehow this is not sufficient to clear their content... how can I do it?
EDIT (to clarify):
To add rows I use something like this (a little different because there is a switch call but it does not modify the essence)
public void createGrid(int n)
{
//remove rows if present
if (MyGrid.RowDefinitions.Count > 2)
{
MyGrid.RowDefinitions.RemoveRange(2, MyGrid.RowDefinitions.Count-2);
}
//permutation
int[] permutation = shuffle(deck.Count);
for (int i = 2; i < n + 2; i++)
{
RowDefinition row = new RowDefinition();
MyGrid.RowDefinitions.Add(row);
row.Height = new GridLength(200, GridUnitType.Pixel);
//add image
createImage(i, 0, deck[permutation[i - 2]].ImmPath);
//add textblock in center column with text chosen
//from a jagged array
createTextBlock(i, 1, value[0][i-2]);
//add textblock in right column
createTextBlock(i, 2, deck[permutation[i - 2]].Meaning);
}
So the idea is not to add new rows every time but to update the exsisting ones (or add them if needs be, createGrid can be called with different values for n). So I came up with the idea to wipe out the rows exceeding the first 2 (which contains the title and buttons) every time I call that method and add only the needed ones. This is the reason for the first check and RemoveRange.
Assuming you know the row and column of the control you want to remove you could do this
foreach (UIElement control in MyGrid.Children)
{
if (Grid.GetRow(control) == row && Grid.GetColumn(control) == col)
{
MyGrid.Children.Remove(control);
break;
}
}
The problem is this
It is puzzling because the code (before adding rows) checks if the
rows are more than 2, and if this is the case it clears all the
exceeding rows
If you are including items that you want to show below the current items, you need to increase the number of RowDefinitions instead of maintain the same.

Datagridview.SelectedCells order

I'm working on a C# application that contains a lot of DataGridViews which are empty. The user has to fill them with copy/pasted data from excel. What I do is the following:
int i = 0;
string s = Clipboard.GetText();
// Separate lines
string[] lines = Regex.Split(s, "\r\n");
foreach (string line in lines)
{
// Separate each cell
string[] cells = line.Split('\t');
foreach (string cell in cells)
{
// If we selected as many cells as copied
if (dataGridView.SelectedCells.Count == (lines.Length-1)*(cells.Length))
{
dataGridView.SelectedCells[i].Value = cell;
i++;
}
}
}
The problem is that if I copy something like this (on excel):
1 2 3
4 5 6
My datagridview will look like:
6 4 2
5 3 1
I don't really know what to do to fix this...
Thanks in advance
Convert your clipboard data to a 2-dimensional array. Remember length of each dimension.
Iterate through the selected cells and find the top-left and bottom-right cells. From that you can determine it is of the right size.
Using a double loop, map your clipboard data from array position directly to cell coordinate (not using selected cells) using the topleft cell coordinate as an offset.
Alternatively, rather than a 2 dimensional array, you could create a List of a small class/struct containing the properties Row, Col and Value. Then just iterate through that rather than the double loop.
Replace
dataGridView.SelectedCells[i].Value = cell;
with
dataGridView.SelectedCells[(dataGridView.SelectedCells.Count-1) - i].Value = cell;

Categories

Resources