How to add a scrollbar to a grid programmatically in WPF? - c#

I have the following grid in the xaml file:
<Grid x:Name="gridPMP" HorizontalAlignment="Left" Height="285" Margin="23,116,0,-330" Grid.Row="1" VerticalAlignment="Top" Width="1238"/>
That grid is filled programmatically with this code .cs:
public void loadPMPTable()
{
gridPMP.Children.Clear();
gridPMP.RowDefinitions.Clear();
gridPMP.ColumnDefinitions.Clear();
MetodosAux aux = new MetodosAux();
String s = problemName.Content.ToString();
String listaPath = "./DataSaved/" + s + "/ListaDeMateriales.txt";
String arbolPath = "./DataSaved/" + s + "/ArbolDeMateriales";
String RIPath = "./DataSaved/" + s + "/RegistroInventarios.txt";
int cols = NumValue + 1;
int rows = aux.numeroLineasFichero(listaPath) + 1;
FileStream fs = new FileStream(listaPath, FileMode.Open, FileAccess.Read);
System.IO.StreamReader file = new System.IO.StreamReader(fs);
String linea;
for (int x = 0; x < cols; x++)
{
ColumnDefinition CD = new ColumnDefinition();
if (x==0)
{
CD.Width = new System.Windows.GridLength(120);
}
else
{
CD.Width = new System.Windows.GridLength(30);
}
//CD.Width = GridLength.Auto;
gridPMP.ColumnDefinitions.Add(CD);
}
for (int y = 0; y < rows; y++)
{
RowDefinition r = new RowDefinition();
//r.Height = GridLength.Auto;
r.Height= new System.Windows.GridLength(30);
gridPMP.RowDefinitions.Add(r);
}
for (int x = 0; x < cols; x++)
{
for (int y = 0; y < rows; y++)
{
if ((y == 0) && (x == 0)) //y=row index, x=column index
{
TextBox t = new TextBox();
t.Width = 170;
t.IsReadOnly = true;
t.Text = "Elemento/Día";
t.FontWeight = FontWeights.UltraBold;
Grid.SetColumn(t, x);
Grid.SetRow(t, y);
gridPMP.Children.Add(t);
}
else if ((y == 0) && (x >= 1))
{
TextBox t = new TextBox();
t.Width = 170;
t.IsReadOnly = true;
t.Text = x.ToString();
t.FontWeight = FontWeights.UltraBold;
Grid.SetColumn(t, x);
Grid.SetRow(t, y);
gridPMP.Children.Add(t);
}
else if (x == 0)
{
TextBox t = new TextBox();
t.Width = 170;
t.IsReadOnly = true;
linea = file.ReadLine();
t.Text = linea;
t.FontWeight = FontWeights.DemiBold;
Grid.SetColumn(t, x);
Grid.SetRow(t, y);
gridPMP.Children.Add(t);
}
else
{
TextBox tb = new TextBox();
tb.PreviewTextInput += textBoxValidator;
tb.Width = 170;
tb.Text = "0";
Grid.SetColumn(tb, x);
Grid.SetRow(tb, y);
gridPMP.Children.Add(tb);
}
}
}
file.Close();
fs.Close();
}//end loadPMPTable()
The number of columns and rows change depending on the structure of some files. So when there are more than 8 rows the grid doesnt display the data because there isnt enough space. That's why I want to make the grid scrollable. How can I do this programmatically or from the xaml file? I tried it from the xaml file but I didnt get it to work.

You can put it inside a ScrollViewer:
<ScrollViewer>
<Grid x:Name="gridPMP" HorizontalAlignment="Left" Height="285" Grid.Row="1" VerticalAlignment="Top"/>
</ScrollViewer>

Related

Unable to grab values from text boxes on form

So i am trying to grab user input from my text boxes which are being printed to the screen through a loop and if Statements. When trying to print the values put into the textbox I only get one value. Here is the code for adding the textboxes to the grid:
private void InsertEasyNums()
{
int x = 70;
int y = 40;
for (int i = 0; i < 9; i++)
{
if (i == 3)
{
x = 70;
y = 160;
}
else if(i == 6)
{
x = 65;
y = 280;
}
if (easyNums[i] == '0')
{
DrawingField.SendToBack();
int panelX = x + 300;
int panelY = y + + 100;
Font newFont = new Font("Arial", 25);
Point tbLocation = new Point(panelX, panelY);
userInput[i] = new TextBox();
userInput[i].Name = "Row[i]TB";
userInput[i].Font = newFont;
userInput[i].Width = 50;
userInput[i].Location = tbLocation;
userInput[i].BorderStyle = BorderStyle.None;
userInput[i].BackColor = DefaultBackColor;
Controls.Add(userInput[i]);
DrawingField.SendToBack();
x = x + 145;
DrawingField.SendToBack();
}
else if (easyNums[i] != '0')
{
DrawingField.SendToBack();
Font drawFont = new Font("Arial", 30, FontStyle.Bold);
Brush Numbers = new SolidBrush(Color.Black);
Graphics g = DrawingField.CreateGraphics();
g.DrawString(Convert.ToString(easyNums[i]), drawFont,
Numbers, x, y);
x = x + 146;
}
}
}
Here is where I try to print the Textboxes:
foreach (Control c in DrawingField.Controls)
{
if (c is TextBox)
{
int i = 0;
TextBox txt = (TextBox)c;
string str = txt.Text;
TBValues[i] = str;
i++;
}
}
foreach (var key in TBValues)
{
MessageBox.Show(key);
}
ANSWER: I moved the declaration of userInput to the beginning of the method and looped through 9 time to give 9 textboxes then used the if statements to move them and change properties.
try to move i before the loop
int i = 0;
foreach (Control c in DrawingField.Controls)
{
if (c is TextBox)
{
TextBox txt = (TextBox)c;
string str = txt.Text;
TBValues[i] = str;
i++;
}
}
foreach (var key in TBValues)
{
MessageBox.Show(key);
}

Creating variables from dynamically created Text boxes and labels using C#

I am wanting to use to names assigned using .Name to input from text boxes then calculate and output to the labels.
Not sure how I can refer to these inputs as they currently have names but no assigned variables.
Sorry if I don't make much sense I am not a very proficient coder.
public partial class Form1 : Form
{
List<TextBox> Txt1 = new List<TextBox>();
public Form1()
{
InitializeComponent();
for (int i = 0; i < 4; i++)
{
for(int j = 0; j < 7; j++)
{
if (j == 0)
{
var txtbox = new TextBox();
txtbox.Location = new Point(163 + (i * 220), (36));
txtbox.Name = i + "Names";
txtbox.Text = txtbox.Name;
txtbox.Width = 40;
this.Controls.Add(txtbox);
}
else if (j>0 && j<6)
{
var extratxt = new TextBox();
extratxt.Location = new Point(163 + (i * 220), (36+ 36 * j));
extratxt.Name = i + "Input" + j;
extratxt.Text = extratxt.Name;
extratxt.Width = 70;
this.Controls.Add(extratxt);
var percentbox = new Label();
percentbox.Location = new Point(163 + (90+ i * 220), (36 + 36 * j));
percentbox.Name = i + "Percent" + j;
percentbox.Text = percentbox.Name;
percentbox.Width = 50;
this.Controls.Add(percentbox);
var gradebox = new Label();
gradebox.Location = new Point(163 + (150 + i * 220), (36 + 36 * j));
gradebox.Name = i + "Grade" + j;
gradebox.Text = gradebox.Name;
gradebox.Width = 50;
this.Controls.Add(gradebox);
}
else
{
var totals = new Label();
totals.Location = new Point(163 + (i * 220), (36 + 36 * j));
totals.Name = i + "Total";
totals.Text = totals.Name;
totals.Width = 40;
this.Controls.Add(totals);
...
}
...
}
}
}
}
Hope I understand you correctly.
Basically, your difficulty is how to access the instance stored in list of the dynamically create controls by their name, right?
Well, you can use .FirstOrDefault() to select instance with a specific property. For example,
private void Form1_Load(object sender, EventArgs e)
{
List<TextBox> tbList = new List<TextBox>();
for (int i = 0; i < 3; i++)
{
TextBox tb = new TextBox();
tb.Text = "Test" + i.ToString();
tb.Name = "TextBox" + (i + 1).ToString();
tb.Location = new Point(0, 25 * i);
tb.Tag = i;
tbList.Add(tb);
this.Controls.Add(tb);
}
var tb2 = tbList.FirstOrDefault(tb => tb.Name == "TextBox2");
if (tb2 != null)
tb2.Text = "Modified text";
var sum = tbList.Sum(tb => (int)tb.Tag);
}

C# I create a new Picturebox and now my Textboxes won't give me any values back

I'm creating a new Picturebox via code, but now my TextBoxes don't give me any values. I think they went out of focus, or their controls aren't working anymore, here's the code so far:
private void button1_Click(object sender, EventArgs e)
{
int ErrorCode = 0;
string NewName = NewPointName.Text;
int X, Y;
Application.DoEvents();
if (NewPointName.Text == "")
ErrorCode = 1;
else
for (int i = 0; i < Names + 1; i++)
{
if (PointName[i] == NewName)
ErrorCode = 2;
}
if (ErrorCode > 0)
MessageBox.Show("Error " + ErrorCode);
else
{
if (Convert.ToInt32(NewPointXBox.Text) > 60)
X = 60;
else if (Convert.ToInt32(NewPointXBox.Text) < -60)
X = -60;
else if (NewPointXBox.Text == "")
X = 0;
else
X = Convert.ToInt32(NewPointXBox.Text);
if (Convert.ToInt32(NewPointYBox.Text) > 60)
Y = 60;
else if (Convert.ToInt32(NewPointYBox.Text) < -60)
Y = -60;
else if (NewPointYBox.Text == "")
Y = 0;
else
Y = Convert.ToInt32(NewPointYBox.Text);
Punkt.GiveName(NewName, Names);
Punkt.GiveCoordinates(X, Y, Names);
PointName[Names] = NewName;
NewPointName.Text = "";
NewPointXBox.Text = "";
NewPointYBox.Text = "";
Application.DoEvents();
UpdatePoint();
CreatePoint(X, Y, NewName, Names);
Names++;
ErrorCode = 0;
NewName = "";
}
}
public void CreatePoint(int X, int Y, string name, int i)
{
int StartPointX = 450, StartPointY = 450, Factor = 7;
if (RadioG6060.Checked)
{
StartPointX = 454;
StartPointY = 449;
Factor = 7;
}
Dot[i] = new PictureBox();
this.Controls.Add(Dot[i]);
Dot[i].Name = "PB_" + name;
Dot[i].Size = new Size(10, 10);
Dot[i].Image = Image.FromFile("../Dot.png");
Dot[i].Anchor = AnchorStyles.Left;
Dot[i].Location = new Point(StartPointX, StartPointY);
Dot[i].Visible = true;
InitializeComponent();
Dot[i].BringToFront();
Dot[i].Location = new Point(Dot[i].Location.X + (X * Factor), Dot[i].Location.Y - (Y * Factor));
Application.DoEvents();
}
I think it's the this.controls.Add(Dot[i]) that throws it off, because now I can't access the text in my NewPointName textbox.
How can I focus the program back on the form or do generally anything that could activate the boxes again?
I just solved the problem, I just had to leave out the InitializeComponent(), then it worked. Turns out that if you do that, the already existing components get blocked and can't be changed in any options of themselves anymore.

How to set wpf grid rowspan programmatically?

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.

WPF - Set Images to Grid

I am trying to set images to a grid I gave created, I am a noob, so please don't get mad at my coding :). I was wondering if there is a way to say set image to grid row 1, grid row 2, etc. I am trying to make a whack a mole game.
private void PopulateGrid()
{
double NumofImages = TUtils.GetIniInt(Moleini, "NumPictures", "pictures", 8);
int ImageSize = TUtils.GetIniInt(Moleini, "ImageSize", "imageSize", 50);
int ImageBorderSize = TUtils.GetIniInt(Moleini, "ImageBorder", "imageBorder", 2);
double NumberOfColumns = TUtils.GetIniInt(Moleini, "NumRowsColumns", "columnNum", 4);
// More Columns than Rows \\
if (NumberOfColumns > NumofImages)
{
MessageBox.Show("There is something wrong with the .ini file.");
Window1.Close();
}
// Math - Get Necessary Variables \\
int ColumnSize = (ImageSize + (4 * ImageBorderSize));
int RowSize = (ImageSize + (4 * ImageBorderSize));
int NumberofRows = (int)Math.Ceiling(NumofImages / NumberOfColumns);
int MainWindowWidth = (TUtils.ToInt(NumberOfColumns.ToString(), 4) * ColumnSize) + 15;
int MainWindowHeight = (NumberofRows * RowSize) + 35;
// Set Window Size \\
Window1.Width = MainWindowWidth;
Window1.Height = MainWindowHeight;
// Create Grid \\
Window1.Content = grid_Main;
grid_Main.Height = MainWindowHeight;
grid_Main.Width = MainWindowWidth;
// Grid Properties \\
for (int i = 0; i < NumberofRows; i++)
{
ColumnDefinition newColumn = new ColumnDefinition();
newColumn.Width = new GridLength(ColumnSize, GridUnitType.Pixel);
grid_Main.ColumnDefinitions.Add(newColumn);
}
for (int i = 0; i < NumberofRows; i++)
{
RowDefinition Row = new RowDefinition();
Row.Height = new GridLength(RowSize, GridUnitType.Pixel);
grid_Main.RowDefinitions.Add(Row);
}
// Fill Grid \\
int RowCount = 0;
int ColumnCount = 0;
for (int i = 0; i < NumofImages; i++)
{
grid_Main.Children.Add(grid_Main);
if (RowCount < NumberofRows)
{
if (ColumnCount < NumberOfColumns)
{
Console.WriteLine("ColumnCount: " + ColumnCount.ToString());
Grid.SetRow(grid_Main, ColumnCount);
Grid.SetColumn(grid_Main, ColumnCount);
ColumnCount++;
}
else
{
RowCount++;
ColumnCount = 0;
Grid.SetRow(grid_Main, ColumnCount);
Grid.SetColumn(grid_Main, ColumnCount);
ColumnCount++;
Console.WriteLine("RowCount: " + RowCount.ToString());
}
}
else
{
break;
}
}
}
...
private Image CreateImage(int ImageNum)
{
// Gets/Sets Necessary Variables \\
double ImageHeight = ImageSize * 0.7;
// Initialize Image \\
System.Windows.Controls.Image newImage = new Image();
// Image Properties \\
newImage.Width = ImageSize;
newImage.Height = ImageHeight;
// Define Name and Content \\
newImage.Name = "Image_" + ImageNum;
String ImageFunction = TUtils.GetIniString(Moleini, "Image" + ImageNum, "PictureFile", Root + "mole2.png");
if (File.Exists(ImageFunction))
{
newImage.Source = new BitmapImage(new Uri(ImageFunction));
}
else
{
MessageBox.Show("Cannot find " + ImageFunction + ".", "Please fix the ini file");
}
return newImage;
}

Categories