I am dynamically generating a matrix of buttons(dynamic gridSize),everything is perfect except that I am unable to get them without spaces between them.I tried but could not understand how to use margin attribute.
460 is the width and height of gridPanel over which I am adding buttons
Here is the code from my app.cs file
private void generateButtons()
{
for (int i = 0; i < gridSize; i++)
{
for (int j = 0; j < gridSize; j++)
{
buttons[i, j] = new Button();
buttons[i, j].Content = "0";
buttons[i, j].FontSize = 16;
buttons[i, j].Height = 460/gridSize;
double size = buttons[i, j].Height;
buttons[i, j].Width = 460/gridSize;
buttons[i, j].Foreground = new SolidColorBrush(Colors.Transparent);
opened[i, j] = false;
buttons[i, j].Margin = new Thickness(0 + (size * j), 0 + (size * i), 464 - (0 + (size * (j + 1))), 464 - (0 + (size * (i + 1))));
buttons[i, j].Click += new RoutedEventHandler(cell_Click);
this.gridPanel.Children.Add(buttons[i, j]);
}
}
}
Most 'input controls' (buttons, textboxes etc) on Windows Phone have default spacings equal to 6.0 or 12.0. The simple workaround is to adjust margins of button by -12.
Sugestion unrelated to the question - when you want to populate a Grid uniformally with buttons, it would be perhaps easier, to generate a desired number of rows and columns and put every button in the different cell (with button.margin always equal to -12). All sizing calculations would be done by the Grid. Like this (gridPanel is Grid).
// generate rows and columns
for (int i = 0; i < gridSize; i++)
{
gridPanel.RowDefinitions.Add(new RowDefinition());
gridPanel.ColumnDefinitions.Add(new ColumnDefinition());
}
for (int i = 0; i < gridSize; i++)
{
for (int j = 0; j < gridSize; j++)
{
buttons[i, j] = new Button
{
Content = "0",
FontSize = 16,
Foreground = new SolidColorBrush(Colors.Transparent),
// all buttons have the same margin, no calculation needed
Margin = new Thickness(-12)
};
// placing in a row and column via attached properties
buttons[i, j].SetValue(Grid.RowProperty, i);
buttons[i, j].SetValue(Grid.ColumnProperty, j);
buttons[i, j].Click += new RoutedEventHandler(cell_Click);
opened[i, j] = false;
this.gridPanel.Children.Add(buttons[i, j]);
}
}
Related
private Button[,] arrButton = new Button[10, 10];
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
arrButton[i, j] = new Button();//getting System.IndexOutOfRangeException
arrButton[i, j].Size = new Size(30, 30);
arrButton[i, j].Location = new Point(i * 30, j * 30);
arrButton[i, j].Click += new EventHandler(arrButton_Click);
this.Controls.Add(arrButton[i, j]);
}
}
this.ClientSize = new Size(300, 300);
After create, array button come up top left corner on form.
how to get array button to a place on form
#choz comment is correct, but a couple things to also consider.
Put the row value and column value in constant variables and use the variables, instead of directly using a number repeatedly.
Example:
private const ROW = 10;
private const COL = 10;
private Button[,] arrButton = new Button[ROW, COL];
...
for (int i = 0; i < ROW; i++)
{
// Change from your code -|
// |----------
// V
for (int j = 0; j < COL; j++)
{
// Create your buttons
}
}
If you are going to use constant numerals, then reference the GetUpperBound() from your array to know the last index value of each dimension.
Example:
private Button[,] arrButton = new Button[10, 10];
...
// GetUpperBound(0) = last index of rows (9 in this case)
for (int i = 0; i <= arrButton.GetUpperBound(0); i++)
{
// Change from your code -|
// |----------
// V GetUpperBound(1) = last index of columns (9 in this case)
for (int j = 0; j <= arrButton.GetUpperBound(1); j++)
{
// Create your buttons
}
}
Syntax error! Your second loop should be:
for (int j = 0; j < 10; j++)
You put "i" instead of "j",
Normally, when you get an System.IndexOutOfRangeException. The debugger error is telling you that the loop or loops you are using are counting the elements more than you specific. Check The count of elements you tinkering with.
I think you are making a mistake in inner loop. Can you please paste this and try to run:
private Button[,] arrButton = new Button[10, 10];
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)//Changed i to j
{
arrButton[i, j] = new Button();
arrButton[i, j].Size = new Size(30, 30);
arrButton[i, j].Location = new Point(i * 30, j * 30);
arrButton[i, j].Click += new EventHandler(arrButton_Click);
this.Controls.Add(arrButton[i, j]);
}
}
this.ClientSize = new Size(300, 300);
I've written code to smooth an image,it's using 3x3 averaging filter. But seem it's not working
The picture output almost black
public void Smooth(Bitmap bmpInput){
Bitmap temp;
Color c;
float sum = 0;
for (int i = 0; i < bmpInput.Width; i++)
{
for (int j = 0; j < bmpInput.Height; j++)
{
c = bmpInput.GetPixel(i, j);
byte gray = (byte)(.333 * c.R + .333 * c.G + .333 * c.B);
bmpInput.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
}
}
temp = bmpInput;
for (int i = 0; i <= bmpInput.Width - 3; i++)
for (int j = 0; j <= bmpInput.Height - 3; j++)
{
for (int x = i; x <= i + 2; x++)
for (int y = j; y <= j + 2; y++)
{
c = bmpInput.GetPixel(x,y);
sum = sum + c.R ;
}
int color = (int)Math.Round(sum/9,10);
temp.SetPixel(i + 1, j + 1, Color.FromArgb(color, color, color));
sum = 0;
}
bmpInput = temp;
}
The variable tempstill refers to the exact same bitmap. You have to assign tempto new Bitmap image and work with this. Alternatively, you can store the new pixel values in a temporary array and transfer the contents of this array back to the image afterwards.
How to set wpf grid rowspan programmatically? I am using mvvm pattern.
I have grid lines enabled and the below doesn't work:
RowDefinition row0 = new RowDefinition();
myGrid.RowDefinitions.Add(row0)
for (int i = 1; i <= RowsCount; i++)
{
RowDefinition row = new RowDefinition();
myGrid.RowDefinitions.Add(row);
TextBlock txt3 = new TextBlock();
txt3.Text = i.ToString();
txt3.FontSize = 12;
txt3.FontWeight = FontWeights.Bold;
Grid.SetRow(txt3, i);
myGrid.Children.Add(txt3);
}
ColumnDefinition column0 = new ColumnDefinition();
myGrid.ColumnDefinitions.Add(column0);
char c = 'A';
for (int i = 1; i <= ColumnsCount; i++)
{
ColumnDefinition column = new ColumnDefinition();
myGrid.ColumnDefinitions.Add(column);
TextBlock txt3 = new TextBlock();
txt3.Text = c.ToString();
txt3.FontSize = 12;
txt3.FontWeight = FontWeights.Bold;
Grid.SetColumn(txt3, i);
myGrid.Children.Add(txt3);
switch (i)
{
case 1:
for (int j = 1; j <= RowsCount; j++)
{
TextBlock txt = new TextBlock();
txt.Text = ColumnAROI[j-1].ToString();
Grid.SetRow(txt, j);
Grid.SetColumn(txt, i);
Grid.SetRowSpan(txt, 2);
// Grid.SetRowSpan(txt, TubeRowSpan[j]);
myGrid.Children.Add(txt);
}
break;
}
c++;
}
for (int j = 1; j <= RowsCount; j++)
{
TextBlock txt = new TextBlock();
txt.Text = ColumnAROI[j-1].ToString();
Grid.SetRow(txt, j);
Grid.SetColumn(txt, i);
Grid.SetRowSpan(txt, TubeRowSpan[j]);
myGrid.Children.Add(txt);
}
TubeRowSpan is an ObservableCollection of type int and defined as below. It contains all 1's except at position 2 (3rd element).
private ObservableCollection<int> _TubeRowSpan = new ObservableCollection<int>();
public ObservableCollection<int> TubeRowSpan
{
get { return _TubeRowSpan; }
set
{
if (_TubeRowSpan != value)
{
_TubeRowSpan = value;
RaisePropertyChanged(() => TubeRowSpan);
}
}
}
You'll have to post the rest of your code, notably how you're creating your row definitions. The following code creates 3 rows for each element and sets the rowspan to 2, it's easy to see from the result that it's working as expected:
int numChildren = 10;
int numRows = numChildren * 3;
for (int j = 0; j < numRows; j++)
this.myGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(30) });
for (int j = 0; j < numChildren; j++)
{
TextBlock txt = new TextBlock();
txt.Background = Brushes.AliceBlue;
txt.Text = "Row " + Convert.ToString(j);
Grid.SetRow(txt, j*3);
Grid.SetRowSpan(txt, 2);
myGrid.Children.Add(txt);
}
I suspect there's something wrong with your RowDefinitions which is causing them to collapse to a height of 0 making it look like it's not working when in fact it is. Try replacing your entire code with mine and then replace your own parts back in bit by bit.
Im trying to create a chess strategy application in c#. I have placed the panels in the form designer where they have been named panel1, panel2, ect.... I am needing to know how I can assign the panels to a 2D Array like 'chessBoardPanels[0,0]' this would allow me to actually control the backgrounds of the panels with a command like:
chessBoardPanels[0,0].Background=Color.Black;
But it says I need a some sort of object reference.
I would rather go for something like this
int numBlocks = 8;
Panel[,] chessBoardPanels = new Panel[numBlocks, numBlocks];
for (int iRow = 0; iRow < numBlocks; iRow++)
for (int iColumn = 0; iColumn < numBlocks; iColumn++)
{
Panel p = new Panel();
//set size
p.Size = new Size(50, 50);
//set back colour
p.BackColor = (iRow + (iColumn % 2)) % 2 == 0 ? Color.Black : Color.White;
//set location
p.Location = new Point(50 * iRow, 50 * iColumn);
chessBoardPanels[iRow, iColumn] = p;
this.Controls.Add(p);
}
This would allow you to create the Panels on the fly, without having to create them in the designer.
You will however have to work on a formula to handle the spacing for you.
EDIT
I have also added an example of how to space/set the panel blocks.
The syntax for creating such 2D array would be:
Panel[,] chessBoardPanels = new Panel[8, 8];
chessBoardPanels[0, 0] = panel1;
chessBoardPanels[0, 1] = panel2;
chessBoardPanels[0, 2] = panel3;
//...
chessBoardPanels[0, 7] = panel8;
chessBoardPanels[1, 0] = panel9;
//...
I kept a bool in my loop for the creation of my board to determine whether to use black or white as the background color. Before setting each field you must initiate the array (usually a two-dimensional one):
this.Fields = new PieceButton[Board.Size, Board.Size];
board = new Board(this);
for (int i = 0; i < Board.Size; i++)
{
for (int j = 0; j < Board.Size; j++)
{
this.Fields[i, j] = new PieceButton(even ? white : black, i, j);
this.Fields[i, j].Size = fieldSize;
this.Fields[i, j].Location = new Point(
i * PieceSize + widthOffset,
(Board.Size - j - 1) * PieceSize + heightOffset);
Fields[i, j].MouseDown += this.Piece_MouseDown;
this.Controls.Add(Fields[i, j]);
even = !even;
}
even = !even;
}
I want to draw 16*64 matrix, each one containing a:
Microsoft.VisualBasic.PowerPacks.OvalShape.
I used this:
List<Microsoft.VisualBasic.PowerPacks.OvalShape> ovalShape =
new List<Microsoft.VisualBasic.PowerPacks.OvalShape>();
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 64; j++)
{
OvalShape ovl = new OvalShape();
ovl.Width = 20;
ovl.Height = 20;
ovl.FillStyle = FillStyle.Solid;
ovl.FillColor = Color.Green;
ovalShape.Add(ovl);
}
}
How can I show it in the Window?
Creating a separate container for each shape is not required. Also you can skip the additional container list for the shapes. So you could use this very compact code.
var ovalShapes = new Microsoft.VisualBasic.PowerPacks.ShapeContainer()
{
Dock = DockStyle.Fill,
Margin = new Padding(0),
Padding = new Padding(0),
};
for (int i = 0; i < 16; i++)
for (int j = 0; j < 64; j++)
ovalShapes.Shapes.Add(
new Microsoft.VisualBasic.PowerPacks.OvalShape()
{
Width = 20,
Height = 20,
FillStyle = Microsoft.VisualBasic.PowerPacks.FillStyle.Solid,
FillColor = Color.Green,
Location = new Point(20 * i, 20 * j),
});
this.Controls.Add(ovalShapes);
From MSDN:
An OvalShape control cannot be displayed directly on a form or
container control; it must be contained in a ShapeContainer object.
After you initialize an OvalShape, you will have to set its Parent
property either to an existing ShapeContainer or to a new instance of
ShapeContainer.
Try to set Location and add your controls to the Form:
List<Microsoft.VisualBasic.PowerPacks.OvalShape> ovalShape = new List<Microsoft.VisualBasic.PowerPacks.OvalShape>();
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 64; j++)
{
OvalShape ovl = new OvalShape();
ovl.Width = 20;
ovl.Height = 20;
ovl.FillStyle = FillStyle.Solid;
ovl.FillColor = Color.Green;
ovl.Location = new Point(ovl.Width*i, ovl.Height*j);
ovalShape.Add(ovl);
}
}
foreach(OvalShape os in ovalShape)
{
Microsoft.VisualBasic.PowerPacks.ShapeContainer shapeContainer = new Microsoft.VisualBasic.PowerPacks.ShapeContainer();
Control c = new Control();
shapeContainer.Parent = c;
os.Parent = shapeContainer;
myForm.Controls.Add(c);
}
First simplify
int totalCount = 1024; //16*64
const int shapeWidth =20;
const int shapeHeight = 20;
for (int j = 0; j < totalCount; j++)
{
OvalShape ovl = new OvalShape();
ovl.Width = shapeWidth;
ovl.Height = shapeHeight;
ovl.FillStyle = FillStyle.Solid;
ovl.FillColor = Color.Green;
ovalShape.Add(ovl);
}
After pickup your drawing area and decide how much shapes per row you would like to have.
So some hypothetical code could look like this:
int shapesPerRowCount = 5;
int yPos = 0;
for(int i=0;i<ovalShape.Count;i++)
{
if(i % shapesPerRowCount == 0) //reach end of the row, so offset Y position by Height
yPos += shapeHeight;
int xPos = i*shapeWidth;
DrawShapeAtPos(ovalShape[i], xPos, yPos); //some special function that draws the shape
}
A very generic code, but just to provide you an idea.
If it's not what you're searching for, please clarify.