How to set wpf grid rowspan programmatically? - c#

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.

Related

WPF Change the text of mulitplie textblocks using a loop

I'm trying to make my own calendar and want to initialize the days in the calendar based on the month.
XAML:
<TextBlock x:Name="day0" Grid.Column="0" Grid.Row="0" Text="0" Style="{StaticResource DayTextBlock}"/>
C#:
List<UIElement> controls = new List<UIElement>();
controls.Add(day0);
controls.Add(day1);
controls.Add(day2);
controls.Add(day3);
controls.Add(day4);
controls.Add(day5);
controls.Add(day6);
for (int i = 0; i < daysInMonth; i++)
{
day0.Text = i.ToString(); // I can change it this way but don't want to do this for all 30 days
controls[i].Text = i.ToString(); // This is more so what I want to do.
}
Thanks for any help. I'm really stuck here. If you know of a better way of going about this I'd be very open to it.
I did a similar thing in the past and I proceeded as following:
TextBlock CreateDay(int dayNumber)
{
return new TextBlock()
{
Text = dayNumber.ToString()
// Here you set you other default properties, common to all TextBlocks
};
}
TextBlock day;
for (int i = 1; i < daysInMonth; i++)
{
int position = i - 1;
day = CreateDay(i);
// The '7' is the number of columns that your grid has
Grid.SetRow(day, position / 7);
Grid.SetColumn(day, position % 7);
yourGridName.Children.Add(day);
}
Please, let me know if this worked as you wanted
Thank you for the help Filippo Ferrario. I used what you said and made this.
List<Button> buttonList = new List<Button>();
List<TextBlock> textList = new List<TextBlock>();
for (int i = 0; i < daysInMonth; i++)
{
buttonList.Add(new Button());
textList.Add(new TextBlock());
textList[i].Text = "\t" + i;
}
for (int i = 0; i < daysInMonth; i++)
{
textList[i].Style = textStyle;
buttonList[i].Style = buttonStyle;
if (column > 6)
{
column = 0;
row++;
}
Grid.SetColumn(textList[i], column);
Grid.SetColumn(buttonList[i], column);
column++;
Grid.SetRow(textList[i], row);
Grid.SetRow(buttonList[i], row);
calNum.Children.Add(buttonList[i]);
calNum.Children.Add(textList[i]);
}
This is the full code for my calendar if anyone needs it.
private void displayDays()
{
DateTime dateTime = DateTime.Now;
Month.Text = dateTime.ToString("MMMM"); //month title
DateTime startOfMonth = new DateTime(dateTime.Year, dateTime.Month, 1);
int daysInMonth = DateTime.DaysInMonth(dateTime.Year, dateTime.Month);
int dayOfWeek = Convert.ToInt32(startOfMonth.DayOfWeek.ToString("d")) + 1; //https://learn.microsoft.com/en-us/dotnet/api/system.datetime.tostring?view=net-6.0#system-datetime
List<Button> buttonList = new List<Button>();
List<TextBlock> textList = new List<TextBlock>();
for (int i = 0; i < daysInMonth; i++)
{
buttonList.Add(new Button());
textList.Add(new TextBlock());
textList[i].Text = "\t" + i;
}
//calNum is a grid I made in the XAML
calNum.ColumnDefinitions.Add(new ColumnDefinition());
calNum.ColumnDefinitions.Add(new ColumnDefinition());
calNum.ColumnDefinitions.Add(new ColumnDefinition());
calNum.ColumnDefinitions.Add(new ColumnDefinition());
calNum.ColumnDefinitions.Add(new ColumnDefinition());
calNum.RowDefinitions.Add(new RowDefinition());
calNum.RowDefinitions.Add(new RowDefinition());
calNum.RowDefinitions.Add(new RowDefinition());
calNum.RowDefinitions.Add(new RowDefinition());
calNum.RowDefinitions.Add(new RowDefinition());
int row = 0;
int column = 6;
column += dayOfWeek;
Style textStyle = this.FindResource("DayTextBlock") as Style;
Style buttonStyle = this.FindResource("DayButton") as Style;
for (int i = 0; i < daysInMonth; i++)
{
textList[i].Style = textStyle;
buttonList[i].Style = buttonStyle;
if (column > 6)
{
column = 0;
row++;
}
Grid.SetColumn(textList[i], column);
Grid.SetColumn(buttonList[i], column);
column++;
Grid.SetRow(textList[i], row);
Grid.SetRow(buttonList[i], row);
calNum.Children.Add(buttonList[i]);
calNum.Children.Add(textList[i]);
}
}

GridView cell width is always 0

I have a GridView, in which the width of each column is dynamic and changes depending on the DataSet. I need to get the width of each column, but the column/cells width is always '0', presumably because I haven't set the width property.
Is there a way around this?
here is the code:
gridResult.DataSource = dtResult;
gridResult.DataBind();
for (int i = 0; i < gridResult.Rows.Count; i++)
{
for (int j = 0; j < gridResult.Rows[i].Cells.Count; j++)
{
string encoded = gridResult.Rows[i].Cells[j].Text;
gridResult.Rows[i].Cells[j].Text = Context.Server.HtmlDecode(encoded);
}
}
GridView2.ShowHeaderWhenEmpty = true;
int tblCols = gridResult.HeaderRow.Cells.Count;
Table tbl = new Table();
TableRow tr = new TableRow();
double check = gridResult.Columns[0].ItemStyle.Width.Value;
double check2 = gridResult.Rows[0].Cells[0].Width.Value;
// TableRow tr = new TableRow();
for (int j = 0; j < tblCols; j++)
{
// Add the table to the placeholder control
TableCell td = new TableCell();
td.Text = gridResult.HeaderRow.Cells[j].Text;
td.Attributes.Add("width", gridResult.HeaderRow.Cells[j].Width + "px");
td.HorizontalAlign = HorizontalAlign.Center;
tr.Cells.Add(td);
td.BorderWidth = 1;
td.BorderColor = System.Drawing.Color.Black;
}
tbl.Rows.Add(tr);
PlaceHolder1.Controls.Add(tbl);

how to access a dynamically generated textbox in a form from other parts of the program?

i currently have a form which i dynamically created a 2D array of textboxes, buttons etc. i just found out my other parts of the program cannot access to the textboxes i created? is there a way i can do it?
my codes goes something like:
public Form1()
{
int column = 4;
System.Windows.Forms.TextBox[,] textbox = new System.Windows.Forms.TextBox[column, row];
for (int i = 0; i < column; i++)
{
for (int j = 0; j < row; j++)
{
textbox[i, j] = new System.Windows.Forms.TextBox();
textbox[i, j].Size = new Size(80, 20);
textbox[i, j].Name = "textbox_" + i + "_" + j;
textbox[i, j].Location = new System.Drawing.Point((i * 80) + 20, (j * 20) + 30);
textbox[i, j].Visible = true;
Controls.Add(textbox[i, j]);
}
}
/////fill the textboxes with data//////
}
i cannot access the textbox outside the method, how can i do it? can you provide some working coded? i am still relatively new to c#, thank you very much
You could add a class level property just like
public class Form1
{
public System.Windows.Forms.TextBox[,] textbox { get; set; }
public Form1()
{
int column = 4;
textbox = new System.Windows.Forms.TextBox[column, row];
for (int i = 0; i < column; i++)
{
for (int j = 0; j < row; j++)
{
textbox[i, j] = new System.Windows.Forms.TextBox();
textbox[i, j].Size = new Size(80, 20);
textbox[i, j].Name = "textbox_" + i + "_" + j;
textbox[i, j].Location = new System.Drawing.Point((i * 80) + 20, (j * 20) + 30);
textbox[i, j].Visible = true;
Controls.Add(textbox[i, j]);
}
}
}
}
Then you can simply do like
Form1 myForm = GetMyForm();
System.Windows.Forms.TextBox[,] theTextboxArray = myForm.textbox;
Surely you can't access them with textbox_i_j where i & j are numerals with intellisense because its not supported but you can get them like this
TextBox GetTB(string name)
{
return ( Controls.FindControl(name) as TextBox );
}
Declare int column = 4;
System.Windows.Forms.TextBox[,] textbox = new System.Windows.Forms.TextBox[column, row];
outside of Form1 constructor. Your code should look like:
int column = 4;
System.Windows.Forms.TextBox[,] textbox;
public Form1()
{
textbox = new System.Windows.Forms.TextBox[column, row];
for (int i = 0; i < column; i++)
{
for (int j = 0; j < row; j++)
{
textbox[i, j] = new System.Windows.Forms.TextBox();
textbox[i, j].Size = new Size(80, 20);
textbox[i, j].Name = "textbox_" + i + "_" + j;
textbox[i, j].Location = new System.Drawing.Point((i * 80) + 20, (j * 20) + 30);
textbox[i, j].Visible = true;
Controls.Add(textbox[i, j]);
}
}
/////fill the textboxes with data//////
}
i have search the net for answers while i wait for some smart people to answer my questions. i use a dictionary to retrieve the text box, goes something like this:
Get a Windows Forms control by name in C#
//declaration
Dictionary <String, System.Windows.Forms.TextBox> dictionaryTextBox = new Dictionary<string, System.Windows.Forms.TextBox>();
// creation of array
System.Windows.Forms.TextBox[,] textbox = new System.Windows.Forms.TextBox[column, row];
for (int i = 0; i < column; i++)
{
for (int j = 0; j < row; j++)
{
textbox[i, j] = new System.Windows.Forms.TextBox();
textbox[i, j].Size = new Size(80, 20);
textbox[i, j].Name = "textbox_" + i + "_" + j;
textbox[i, j].Location = new System.Drawing.Point((i * 80) + 20, (j * 20) + 30);
textbox[i, j].Visible = true;
Controls.Add(textbox[i, j]);
//new added
dictionaryTextBox.Add (textbox[i, j].Name, textbox[i, j]);
}
}
// retrieval
System.Windows.Forms.TextBox retrieve = dictionaryTextBox["textbox_3_3"];
retrieve.Text = "apple";

How to add a matrix of OvalShapes to the window?

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.

How to create list of checkboxes with scroll?

I'm trying this code:
arrList = new List<CheckBox>();
for (int j = 0; j < 20; j++)
{
CheckBox check = new CheckBox();
arrList.Add(check);
}
CheckBox[] cb = arrList.ToArray();
for (int i = 0; i < 20; i++)
{
cb[i].Text = "sometext";
cb[i].Location = new System.Drawing.Point(10, 15 + i * 20);
cb[i].BackColor = System.Drawing.Color.Silver;
cb[i].Name = "somename";
cb[i].Size = new System.Drawing.Size(59, 17);
cb[i].Checked = true;
groupBox1.Controls.Add(cb[i]);
}
How can I add a vertical scroll bar there? (maybe I should use something instead of groupbox?)
You could use a Panel control and set it's AutoScroll property to True

Categories