How do I update an array of labels - c#

This sounds wierd but i have no idea how to do this, despite the fact i've read lots of articles and answers about it.
this one seems to be the most clear, but unfortunately it doesn't help me.
Like this
so i have an array of labels that should be updated during the for cycles:
public const int NUM_OF_PAGES = 128;
...
int[] PEcnt = new int[NUM_OF_PAGES];
Label[] PElabels = new Label[NUM_OF_PAGES];
for (int i = 0; i < NUM_OF_PAGES; i++) // initialization
{
PEcnt[i] = 0;
PElabels[i] = new Label();
PElabels[i].Content = 0;
PElabels[i].Margin = new Thickness(50 + 80 * (i % 16), 50 + 20 * (i / 16), 0, 0);
Grid1.Children.Add(PElabels[i]);
}
...
for (int i = 0; i < NUM_OF_PAGES; i++)
{
PEcnt[i] += 2;
PElabels[i].Content = PEcnt[i];
BindingOperations.GetBindingExpressionBase(PElabels[i], Label.ContentProperty).UpdateTarget(); //trying to update
}
but this throws me "System.NullReferenceException"
hope u will help me, learning is difficult, but im trying hard

don't .UpdateTarget(); and it should be okay I believe
you don't need to get binding expressions for this, if you are using it else where do not update target here.

so first of all:
The Label.Content Property stores an object! So you can store an Integer in it without casting!
You are trying to update an BindingExpression on an NOTbinded Property!
So the way you should solve your problem, is by just NOT updating it.
Because your Label isn't using any bindings your called function returns null.
So just Store your Integer in the content property and YOLO. Here is the working code:
public const int NUM_OF_PAGES = 128;
Label[] PElabels = new Label[NUM_OF_PAGES];
...
for (int i = 0; i < NUM_OF_PAGES; i++) // initialization
{
PElabels[i] = new Label();
PElabels[i].Content = 0; //Storing your Data as int in object
PElabels[i].Margin = new Thickness(50 + 80 * (i % 16), 50 + 20 * (i / 16), 0, 0);
Grid1.Children.Add(PElabels[i]);
}
...
for (int i = 0; i < NUM_OF_PAGES; i++)
{
PElabels[i].Content = (int)PElabels[i].Content + 2; //Storing your new Data
}
SO!!!!
If you realy need to use this update binding, you have to set your content property to an Binding. To do so, you have to store your data in some property for example in the Label.DataContext. Now you need to set the Binding (pointing at the DataContext) to you Label.ContentProperty. After doing that you can update your BindingExpression and the Label will change.
Working Code here:
public const int NUM_OF_PAGES = 128;
Label[] PElabels = new Label[NUM_OF_PAGES];
...
for (int i = 0; i < NUM_OF_PAGES; i++) // initialization
{
PEcnt[i] = 0;
PElabels[i] = new Label();
PElabels[i].DataContext = 0; //Storing your Data
Binding PEcntBind = new Binding("DataContext");
PEcntBind.Source = PElabels[i];
PElabels[i].SetBinding(Label.ContentProperty, PEcntBind); //Binding to your stored Data
PElabels[i].Margin = new Thickness(50 + 80 * (i % 16), 50 + 20 * (i / 16), 0, 0);
Grid1.Children.Add(PElabels[i]);
}
...
for (int i = 0; i < NUM_OF_PAGES; i++)
{
PEcnt[i] += 2;
PElabels[i].DataContext = PEcnt[i]; //Storing your new Data
BindingExpression LabBindEx = (PElabels[i] as FrameworkElement).GetBindingExpression(Label.ContentProperty);
LabBindEx.UpdateTarget(); //Updating the Bindings
}
(Oh and by the way you have to use GetBindingExpression not GetBindingExpressionBase)

Related

C# Generating Labels Dynamically

I have got the below code to generate labels using for loop, however there is a problem with the for loop, if the productList has 4 items, it generates 1 label instead of 4. I can't figure out what the problem is.
List<models.Car> carList = carController.getCars();
for (int i = 0; i < carList.Count; i++)
{
List<models.Product> productList = productController.getProducts(carList[i].Model);
for (int j = 0; j < productList.Count; j++)
{
productLabels.Add(new Label());
var productLabelsPoint = new System.Drawing.Point(200, 40 + i * 50);
(productLabels[j] as Label).Location = productLabelsPoint;
(productLabels[j] as Label).Size = new System.Drawing.Size(150, 15);
(productLabels[j] as Label).Text = productList[j].Title;
this.Tab.TabPages["tab1"].Controls.Add((productLabels[j] as Label));
}
}
This only relies on i, not on j:
System.Drawing.Point productLabelsPoint = new System.Drawing.Point(200, 40 + i * 50);
So you might be drawing the labels one on top of the other.
In which case, you'd need to add j into the mix, for example like this:
System.Drawing.Point productLabelsPoint = new System.Drawing.Point(200, 40 + i * 50 + j * 50);
I would also change the way you are referencing the label. (I can't tell from the context if what you are doing is okay or not, as it depends how that productLabels variables has been instantiated.)

Listbox not removing values in c# GUI

The user basically enters a number of hex values into a textbox separated by commas eg. AA,1B,FF. These are then displayed in a listbox box. if the number of hex values in the textbox exceeds the size to transfer defined by the user, the listbox only displays the this number of values or if the size to transfer is bigger that adds zero values to the listbox.
this works fine until you enter a value with a zero in front of it such as AA,BB,CC,DD,EE,0F, if sizeToTransfer = 2, the listbox should display 0xAA and 0xBB. but instead it only removes the 0F value?
I'm pretty new to programming so it may be something obvious I'm missing any help would be appreciated.
private void WriteSPI1_Click(object sender, EventArgs e)
{
string hexstring = textbox1.Text;
HexValues.Items.Clear();
string[] hexarray = hexstring.Split((",\r\n".ToCharArray()), StringSplitOptions.RemoveEmptyEntries);
byte[] hexbytes = new byte[hexarray.Length];
uint num = Convert.ToUInt32(hexarray.Length);
for (int j = 0; j < hexarray.Length; j++)
{
hexbytes[j] = Convert.ToByte(hexarray[j], 16);
Hexlist.Add(hexbytes[j]);
writebuff = Hexlist.ToArray();
x = writebuff[j].ToString("X2");
HexValues.Items.Add("0x" + x);
}
if (hexarray.Length > sizeToTransfer)
{
diff = num - sizeToTransfer;
for (i = 0; i < diff+1; i++)
{
HexValues.Items.Remove("0x" + x);
}
}
else
{
diff = sizeToTransfer - num;
for (i = 0; i < diff; i++)
{
HexValues.Items.Add("0x00");
}
}
}
CHANGE
for (int j = 0; j < sizeToTransfer; j++)
{
hexbytes[j] = Convert.ToByte(hexarray[j], 16);
Hexlist.Add(hexbytes[j]);
writebuff = Hexlist.ToArray();
x = writebuff[j].ToString("X2");
HexValues.Items.Add("0x" + x);
}
WITH
for (int j = 0; j < hexarray.Length; j++)
{
hexbytes[j] = Convert.ToByte(hexarray[j], 16);
Hexlist.Add(hexbytes[j]);
writebuff = Hexlist.ToArray();
x = writebuff[j].ToString("X2");
HexValues.Items.Add("0x" + x);
}
and remove the if stantment that follow

Image Manipulation using Average Kernel

Ive been working on a code that takes an image, turns it into grayscale, and then does image manipulation depending on which button is pressed. When a button is pressed (ex. Average 3x3, Prewitt 5x5), it calls a 2D Multiplication function, which loops over the grayscale image, while looping over the kernel, adding all the values in the matrix. If any value is over 255, it sets it to 255. Then using the SetPixel on a temporary bitmap variable, which is finally put into the picturebox. When i run the program, I select an image and it shows it (as grayscale), but after choosing one of the filters, the program freezes for around 30 seconds, and then nothing changes, no filter is applied. Ive tried debugging and i cant seem to locate what the problem is!
EDIT: The initial question has been solved( I had to refresh the picturebox for the new image to show properly.
But i am facing another problem here with regards to the prewitt kernel.
i get this error
"Additional information: Value of '-6' is not valid for 'red'. 'red' should be greater than or equal to 0 and less than or equal to 255."
And i am not sure what to change in my code to fix this.
Initializing:
public partial class Form1 : Form
{
private Image img;
Bitmap grayscaleimage;
double[][] AVGKernel = new double[11][];
double[][] PrewittKernel = new double[11][];
int[] AVGKernal1DH = new int[11];
int[] AVGKernal1DV = new int[11];
Bitmap tempBitmap;
public Form1()
{
InitializeComponent();
for (int i = 0; i < 11; i++)
{
AVGKernel[i] = new double[11];
PrewittKernel[i] = new double[11];
for (int j = 0; j < 11; j++)
{
AVGKernel[i][j] = 0;
PrewittKernel[i][j] = 0;
AVGKernal1DH[j] = 0;
AVGKernal1DV[j] = 0;
}
}
}
The open button and turning the picture into grayscale:
private void OpenImageButton(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
this.img = Image.FromFile(openFileDialog.FileName);
grayscaleimage = new Bitmap(img);
int rgb;
Color c;
for (int y = 0; y < grayscaleimage.Height; y++)
for (int x = 0; x < grayscaleimage.Width; x++)
{
c = grayscaleimage.GetPixel(x, y);
rgb = (int)((c.R + c.G + c.B) / 3);
grayscaleimage.SetPixel(x, y, Color.FromArgb(rgb, rgb, rgb));
}
this.pictureBox1.BackgroundImage = grayscaleimage;
pictureBox1.BackgroundImageLayout = ImageLayout.Zoom;
}
}
an example of the many buttons available:
private void button5_Click(object sender, EventArgs e)
{
AVGKernel[0][0] = 1; AVGKernel[0][1] = 1; AVGKernel[0][2] = 1; AVGKernel[0][3] = 1; AVGKernel[0][4] = 1;
AVGKernel[1][0] = 1; AVGKernel[1][1] = 1; AVGKernel[1][2] = 1; AVGKernel[1][3] = 1; AVGKernel[1][4] = 1;
AVGKernel[2][0] = 1; AVGKernel[2][1] = 1; AVGKernel[2][2] = 1; AVGKernel[2][3] = 1; AVGKernel[2][4] = 1;
AVGKernel[3][0] = 1; AVGKernel[3][1] = 1; AVGKernel[3][2] = 1; AVGKernel[3][3] = 1; AVGKernel[3][4] = 1;
AVGKernel[4][0] = 1; AVGKernel[4][1] = 1; AVGKernel[4][2] = 1; AVGKernel[4][3] = 1; AVGKernel[4][4] = 1;
kernal2DMultiplication(AVGKernel, 5);
this.pictureBox1.BackgroundImage = tempBitmap;
}
Prewitt 5x5 kernel
private void button13_Click(object sender, EventArgs e)
{
PrewittKernel[0][0] = 2; PrewittKernel[0][1] = 1; PrewittKernel[0][2] = 0; PrewittKernel[0][3] = -1; PrewittKernel[0][4] = -2;
PrewittKernel[1][0] = 2; PrewittKernel[1][1] = 1; PrewittKernel[1][2] = 0; PrewittKernel[1][3] = -1; PrewittKernel[1][4] = -2;
PrewittKernel[2][0] = 2; PrewittKernel[2][1] = 1; PrewittKernel[2][2] = 0; PrewittKernel[2][3] = -1; PrewittKernel[2][4] = -2;
PrewittKernel[3][0] = 2; PrewittKernel[3][1] = 1; PrewittKernel[3][2] = 0; PrewittKernel[3][3] = -1; PrewittKernel[3][4] = -2;
PrewittKernel[4][0] = 2; PrewittKernel[4][1] = 1; PrewittKernel[4][2] = 0; PrewittKernel[4][3] = -1; PrewittKernel[4][4] = -2;
kernal2DMultiplication(PrewittKernel, 5);
this.pictureBox1.BackgroundImage = tempBitmap;
this.pictureBox1.Refresh();
}
and finally, the function being called:
private void kernal2DMultiplication(double[][] kernel, int size)
{
tempBitmap = grayscaleimage;
double nrgb = 0;
for (int i = 0; i < grayscaleimage.Width - size / 2; i++)
{
for (int j = 0; j < grayscaleimage.Height - size / 2; j++)
{
if (i >= size / 2 && j >= size / 2)
{
for (int k = 0; k < size; k++)
for (int l = 0; l < size; l++)
nrgb += grayscaleimage.GetPixel(i + k - (size / 2), j + l - (size / 2)).R * kernel[k][l];
nrgb = nrgb / (size * size);
if (nrgb > 255)
nrgb = 255;
tempBitmap.SetPixel(i, j, Color.FromArgb((int)nrgb, (int)nrgb, (int)nrgb));
}
}
}
}
The problem is that you are modifying the BackgroundImage bitmap in-place rather than copying, modifying the copy, and then setting the copy to be the BackgroundImage:
this.pictureBox1.BackgroundImage = grayscaleimage; // initially
tempBitmap = grayscaleimage;
// Make changes to tempBitmap
this.pictureBox1.BackgroundImage = tempBitmap; // actually still the same pointer
The BackgroundImage setter is not forcing a redraw of the control in this case. To force this yourself, call Refresh():
this.pictureBox1.Refresh();
To improver performance, look into replacing multiple calls to SetPixel with a single call to LockBits. See e.g. here.

Dynamic UI, Loop not working correctly

Here is the code I'm using
It's supposed to create labels for each module name entered by a user and all the assessment names for that module under it. Should work with any number of modules and assessments. The problem is that it only shows assessments for the last module displayed.
dat.Modules and dat.Assessments are arraylists, each of them holds 4 elements with info about a module or an assessments, that is why i divide the count by 4.
private void testingButton_Click(object sender, EventArgs e)
{
int pos1 = 50;
int pos2 = 150;
int modLength = dat.Modules.Count;
modLength = modLength / 4;
int assessLength = 0;
int arrayData = 0;
int displayCount = 0;
for (int i = 0; i < modLength; i++)
{
this.moduleLabels.Add(new Label());
System.Drawing.Point pLabel1 = new System.Drawing.Point(50, pos1);
(moduleLabels[i] as Label).Location = pLabel1;
(moduleLabels[i] as Label).Size = new System.Drawing.Size(100, 13);
(moduleLabels[i] as Label).Text = dat.Modules[arrayData].ToString();
tabPage5.Controls.Add((moduleLabels[i] as Label));
String asd = dat.Modules[arrayData + 2].ToString();
Console.WriteLine(asd);
assessLength = int.Parse(asd);
pos2 = pos1 + 25;
for (int y = 0; y < assessLength; y++)
{
this.assessLabels.Add(new Label());
System.Drawing.Point pLabel2 = new System.Drawing.Point(70, pos2);
(assessLabels[y] as Label).Location = pLabel2;
(assessLabels[y] as Label).Size = new System.Drawing.Size(250, 13);
(assessLabels[y] as Label).Text = dat.Assessments[displayCount + 1].ToString() + " weights " + dat.Assessments[displayCount+2].ToString() +"%, Enter your mark:";
textboxComputer.Add(new TextBox());
System.Drawing.Point pText1 = new System.Drawing.Point(400, pos2);
(textboxComputer[y] as TextBox).Location = pText1;
(textboxComputer[y] as TextBox).Size = new System.Drawing.Size(20, 20);
tabPage5.Controls.Add(assessLabels[y] as Label);
tabPage5.Controls.Add(textboxComputer[y] as TextBox);
pos2 = pos2 + 25;
displayCount = displayCount + 4;
}
pos1 = pos2+25;
arrayData = arrayData + 4;
}
}
this is an example of what it displays
http://dc540.4shared.com/download/YI8IENYI/tsid20120501-211723-cbc785f9/asd.jpg
The first two modules should have their assessments listed. The first one doesn't display any. For Java it only displays the last one, out of 3 total for that module. And for the last Module "Another Module" it displays all assessments.
For each increment of i, y starts at 0. You then add new labels to assessLabels, but attempt to access the one you added by using assessLabels[y] which would usually yield the labels created for the previous value of i. This causes labels created for the first module to be reused by the next, and so forth.
A quick solution is not to use assessLabels[y] but assessLabels[assessLabels.Count - 1].
A better solution is to create a local variable for the labels, set their properties, and then add them to the list:
for (int y = 0; y < assessLength; y++)
{
Label assessLabel = new Label();
assessLabel.Location = ...;
// etc.
tabPage5.Controls.Add(assessLabel);
assessLabels.Add(assessLabel);
}
This would also remove the need to continuously cast the ArrayList members and unneeded access to the list.
PS. If assessLabels only contains objects of type Labels, consider using a List<Label> instead.

Finding objects by their name

I was wondering how could I select objects which were created during programs runtime.
Each object has its unique name. How could I select that object by its name?
Example names:
"mapPart_0_0"
"mapPart_0_1"
"mapPart_0_2"
etc.
It's a windows form project. In c#.
Creation of those objects:
private void addBoxes()
{
for (int a = 0; a < 25; a++)
{
for (int b = 0; b < 10; b++)
{
MyCustomPictureBox box = new MyCustomPictureBox();
box.Location = new Point(b * 23 + 5, a * 23 + 5);
box.Image = new System.Drawing.Bitmap("tiles/0.png");
box.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
box.Size = new Size(24, 24);
box.Name = "mapPart_" + a + "_" + b;
box.Click += new EventHandler(boxClickAdd);
box.oFile = "0";
panel1.Controls.Add(box);
}
}
}
I would suggest to simply put the objects in a System.Collections.Generic.Dictionary<string, your object type> list. It provides the exact functionality you are seeking if I understand the question correctly.

Categories