Receiving XAML button name in - c#

I have about 100 textboxes on a page, and each textbox has its own corresponding value in an array, each textbox has a method which is invoked when the value in the textbox is changed, and updates the corresponding elements of the array, to reflect that value it has been changed to. (In theory)
However, is there a way that you can adjust the below method, so that rather than writing it out 100 times, with a changing name "_8_8_TextChanged", and changing the values that it changes manually, and doing it so that 1 method is called by all textboxes, and the method recognises which textbox called it, and updates the relevant elements in the array?
The Method is defined below and features on the "Solver.xaml.cs" page.
private void _8_8_TextChanged(object sender, TextChangedEventArgs e)
{
int number = int.Parse(_8_8.Text);
if ((number >= 1) && (number <= 9))
{
for (int i = 0; i <= 8; i++)
{
if (i == (number - 1))
{
content[8, 8, i] = true;
}
else
{
content[8, 8, i] = false;
}
}
}
}
The XAML textbox itself is defined below and features on the "Solver.xaml" page, with its styling elements removed for simplicity.
<TextBox x:Name="_8_8" TextChanged="_8_8_TextChanged"/>

I really hope you have a good reason for using that many text boxes. In any case you can use the same event handler for all of your TextChange events, as follows.
All textboxes would be set up to use the same handler:
<TextBox x:Name="_8_8" TextChanged="_x_y_TextChanged"/>
<TextBox x:Name="_8_9" TextChanged="_x_y_TextChanged"/>
You can then update your array based on the sending text box:
private void _x_y_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox tb = (TextBox)sender;
// use the Name of the textbox to determine x, y value
string[] tmp_x_y = tb.Name.Split("_");
// you may have to adjust these indices based on how Split actually
// does its work.
int x = int.Parse(tmp_x_y[0]);
int y = int.Parse(tmp_x_y[1]);
int number = int.Parse(tb.Text);
if ((number >= 1) && (number <= 9))
{
for (int i = 0; i <= 8; i++)
{
if (i == (number - 1))
{
content[x, y, i] = true;
}
else
{
content[x, y, i] = false;
}
}
}
}
I didn't actually compile the code above, but it should give you a good starting point.

Related

How to check range in checkedlistbox c# winforms?

I have a checkeboxlist with 100 items. Obviously user can check items one by one as many as he need, but I would like to give to user option check range of items (let's say with Shift hold button). So, user check one of the items (let's say item index 5) and then press and hold shift button and check next item (index 10), so I range of the items should be checked from 5...10
I have not found anything about such implementation, looks like it doesn't exist and no one did such kind of things.
How to do it?
Keep track of your last index:
int lastIndex = -1;
In your form's constructor, wire things up:
public Form1() {
InitializeComponent();
checkedListBox1.CheckOnClick = true;
checkedListBox1.SelectedIndexChanged += CheckedListBox1_SelectedIndexChanged;
checkedListBox1.MouseDown += CheckedListBox1_MouseDown;
}
And then use these methods to change the items in the range:
private void CheckedListBox1_SelectedIndexChanged(object sender, EventArgs e) {
lastIndex = checkedListBox1.SelectedIndex;
}
private void CheckedListBox1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left && Control.ModifierKeys == Keys.Shift) {
var useIndex = Math.Max(lastIndex, 0);
var x = checkedListBox1.IndexFromPoint(e.Location);
if (x > -1 && x != useIndex) {
if (useIndex > x) {
for (int i = useIndex - 1; i > x; i--) {
checkedListBox1.SetItemChecked(i, !checkedListBox1.GetItemChecked(i));
}
} else {
for (int i = useIndex + 1; i < x; i++) {
checkedListBox1.SetItemChecked(i, !checkedListBox1.GetItemChecked(i));
}
}
}
}
}

C# How to assign i and j in 2D array when i press on a button

I was asked to make a tic tac toe in windows form and i have to use 2D array
I am trying to store 1 in the array for each X and -1 for each 0
then i will add the values in each row ,column and diagonal and check if its 3 or -3
the problem is i don't know how to assign and i and j for each element in the array after i press on a corresponding button
private void storeInboard(int i, int j, object sender, EventArgs e)
{
{
if ((sender as Button).Text == "X")
board[i][j] = 1;
else if ((sender as Button).Text == "O")
board[i][j] = -1;
}
}
here i check for each column by giving its number
private bool checkCol(int col)
{
for (int i = 0; i < 3; i++)
{
rowSum += board[i][col];
if (colSum == 3 || colSum ==-3 )
return true;
else
colSum = 0;
}
return false;
}
checking for winner
private bool checkWinner()
{
return (checkCol(0) || checkCol(1) || checkCol(2) || checkDiag1() || checkDiag2() || checkRow(0) || checkRow(1) || checkRow(2));
}
here is the button click event >> its is assigned for all the buttons
private void button_click(object sender, EventArgs e)
{
if (turn)
{
(sender as Button).Text = "X";
}
else
(sender as Button).Text = "O";
turn = !turn;
turnCount++;
(sender as Button).Enabled = false;
if (checkWinner() && turnCount <=9)
MessageBox.Show("Winner !!!");
else
MessageBox.Show("Tie -.-");
so I just want to know how can i send an i and j for the event storeInboard for each button i click
thanks in advance
This question is not about arrays or some 2D stuff but binding information to winform controls.
You have several ways to do this.
1) In visual studio property panel fill buttons Tag property with an ordinal number one by one from left to right starting with zero. Left-upper button = 0, middle-upper = 1 and so on.
Then in button_click you can do something like:
var tag = int.Parse((string)((Button)sender).Tag);
int colIndex = tag % 3;
int rowIndex = tag / 3;
2) Maybe the buttons are placed in a Panel. Then you can iterate through the children of the parent panel in button_click and see if one equals to sender.
int c = 0;
foreach (var item in parentPanel.Controls)
{
if (item == sender)
break;
c++;
}
if (c<parentPanel.Controls.Count) // found
{
int colIndex = c % 3;
int rowIndex = c / 3;
}
// else -- ugh, something went wrong, maybe not only the buttons have this event
Much more solution is possible.

How can I check if column value same on every row on GridView?

I have a grid view with 10 rows.
After clicking on a button I would like to check and make sure each cell value are the same or not under the firstname column of gridview.
If all the cell values are same then call the changeCellValues() method. If any cell value is different then MessageBox.Show("You cant use your method");
private void button1_Click(object sender, EventArgs e)
{
string x;
string y;
x = dataGridView1.Rows[0].Cells[1].Value.ToString();
for (int i = 0; i < 11; i++)
{
y = dataGridView1.Rows[i].Cells[1].Value.ToString();
if (x == y) continue;
MessageBox.Show("You cant use your method");
}
}
How can I check if column value same on every row on GridView?
If you have 10 rows, change i < 11 to i < 10 and start i from 1 because you already get the first row's value and store it into x.Your way seems correct but instead of displaying the messagebox inside of the loop, you can use something like this:
x = dataGridView1.Rows[0].Cells[1].Value.ToString();
bool control = true;
for (int i = 1; i < 10; i++)
{
y = dataGridView1.Rows[i].Cells[1].Value.ToString();
if (x != y) { control = false; break; }
}
if(!control) MessageBox.Show("You cant use your method");
else changeCellValues();
Alternative using LINQ... grab everything in the column "firstname", remove duplicates using Distinct, and then count the number of unique names. (If you have more than 1 unique name, they're not all the same.)
var isSameName = dataGridView1.Rows.Cast<DataGridViewRow>()
.Select(x => Convert.ToString(x.Cells["firstname"].Value))
.Distinct().Count() == 1;
if (!isSameName)
{
MessageBox.Show("You cant use your method");
return;
}
changeCellValues();

Global array not being accessed correctly

Below is my current code:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public int[] trialArray = new int[10];
public int trialCounter = -1;
private void button1_Click(object sender, EventArgs e)
{
bool button1Click = true;
if (button1Click == true)
{
ITIpanel.Visible = true;
for (int i = 0; i < trialArray.Length; i++) { trialArray[i] = -1; } // Set default value through array
int counter = 0;
Random rnd = new Random();
while (counter < 10 / 2)
{ // Red trials, fill half array
int index = rnd.Next(0, 10 - 1);
if (trialArray[index] == -1) { trialArray[index] = 1; ++counter; } //if unchanged value, change it
}
while (counter < 10)
{
int index = rnd.Next(0, 10);
if (trialArray[index] == -1) { trialArray[index] = 2; ++counter; }
}
}
}
private void ITIpanel_Paint(object sender, PaintEventArgs e)
{
if (ITIpanel.Visible == true)
{
trialCounter += 1;
timer1.Enabled = true;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
ITIpanel.Visible = false;
timer1.Enabled = false;
if (trialArray[trialCounter] == 1) { redstimPanel.Visible = true; }
else { bluestimPanel.Visible = true;}
if (trialCounter == 9) { Application.Exit(); }
}
public int counter = 0;
public event EventHandler Clicked5TimesEvent;
private void OnClicked5TimesEvent()
{ if (Clicked5TimesEvent != null) { Clicked5TimesEvent(this, EventArgs.Empty); } }
private void bluestimPanel_MouseDown(object sender, EventArgs e)
{
//FR requirement
counter++; if (counter % 5 == 0) { redstimPanel.Visible = false; ITIpanel.Visible = true; }
}
private void redstimPanel_MouseDown(object sender, EventArgs e)
{
//FR requirement
counter++; if (counter % 5 == 0) { redstimPanel.Visible = false; ITIpanel.Visible = true; }
}
}
}
As you can see, I am attempting to make a global array with 10 items. On the button click the 10 items are supposed to be altered such that half contain the value 1 and the other half contain the value 2.
Then, on the timer tick, depending on the value in the trialCounter, which determines the part of the array to be accessed, it should display either the redstimPanel or the bluestimPanel.
Therefore, if the 'trialCounter' is equal to 8, and 8 in the TrialArray is equal 1, the 'redstimPanel' should become Visible. Alternatively, if 8 in the 'TrialArray' is equal to 2, the 'bluestimPanel' should become Visible.
This, however, is not working as I would like it to. Thus, there are clearly some issues with my code. Do you all have any suggestions?
You never reset counter, or have the second loop (the one setting the 2s) be the full array.
There is also an error with the random number, rnd.Next(a,b) a - lower bound (inclusive), b - upper bound (exclusive). So it should be rnd.Next(0,10); so you have a chance of populating the last array position.
while (counter < 10 / 2) { // Red trials, fill half array
int index = rnd.Next(0, 10);
if (trialArray[index] == -1) { trialArray[index] = 1; ++counter; } //if unchanged value, change it
}
//Counter on the first loop here is already 5 (it exited the previous loop)
//So allow it to get to 10, and populate the FULL array.
while (counter < 10) {
int index = rnd.Next(0, 10);
if (trialArray[index] == -1) { trialArray[index] = 2; ++counter; }
}
Allow me to give you some tips and some explanations regarding your code:
First of all, you probably wanted that local button1Click variable to know later on whether the button has been clicked or not. For that to work, you should place it outside that function, otherwise it's never going to be used, and will be true with every button click, something like this:
bool button1Click = false;
private void button1_Click(object sender, EventArgs e)
{
if (!button1Click)
{
When you have a condition, you want the code to decide, whether an expression is true or false you may omit the part "== true" because it doesn't add anything new.
You have two whiles. Your idea was to run the counter until 5, with the first piece of code, and then from 5 to 10 the second piece of code. Now let me try to explain what is actually going on. The counter will go on until 5 filling 1s at random indices. Then at 5, the expression in the while will become false and it breaks out from the loop. Since the second while has the very same expression, it simply avoids it and goes on. One of the many solutions would be to have an if in the loop like this:
while (counter < 10)
{
if (counter<5)
{
// fill red
}
else
{
// fill blue
}
}
The way you fill up the values in your array. Have you thought about what's going to happen when the same index will be generated several times? It means it'll overwrite the previous value while certain index will remain -1.

WPF TextBox ScrollToLine not updating if visible

I have a Navigation-bar in my program that allows you to navigate the different sections in my TextBox, but the problem I have is that this doesn't work if the Text I am scrolling to is already visible on the screen.
Like in this example, if I try to jump from Section 1 to Section 3, it won't work as it's already visible.
But, in this example if I jump to Section 3, it works fine as it's not already visible.
The scrolling function I use is very simple:
if (nLine > 0 && nLine <= textBox.LineCount)
textBox.ScrollToLine(nLine - 1);
I hope that someone can shed some light on an alternative solution that allows me to scroll even if the text is already visible.
Edit: Added solution.
This is a code snippet from my project.
private static void ScrollToLineCallback(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
var textBox = (TextBox)target;
int newLineValue;
if (Int32.TryParse(e.NewValue.ToString(), out newLineValue))
{
if (newLineValue > 0 && newLineValue <= textBox.LineCount) // Validate
{
textBox.ScrollToLine(newLineValue - 1); // Scroll to Line
// Check and see if we are at the line we want.
if (textBox.GetFirstVisibleLineIndex() <= newLineValue && textBox.GetLastVisibleLineIndex() >= newLineValue)
{
// If not lets move to the desired location
int newLineCorrectionValue = newLineValue - textBox.GetFirstVisibleLineIndex() - 2; // How much further do we need to scroll down?
for (int i = 0; i < newLineCorrectionValue; i++)
{
textBox.LineDown(); // Scroll down
}
}
}
}
}
You could use GetCharacterIndexFromLineIndex to get the index of the beginning of the desired line and then set the CaretIndex to that value.
Because I don't really know, what you are trying to achieve, another possibility is to use LineUp and LineDown in conjunction with GetFirstVisibleLineIndex and GetLastVisibleLineIndex.
private void TextBoxGotoLine(
TextBox textbox1,
int linenum)
{
var target_cpos = textbox1.GetCharacterIndexFromLineIndex(linenum);
var target_char_rect = textbox1.GetRectFromCharacterIndex(target_cpos);
var first_char_rect = textbox1.GetRectFromCharacterIndex(0);
textbox1.ScrollToVerticalOffset(
target_char_rect.Top -
first_char_rect.Top
);
}
I found out if Wrapping is enabled its more complications:
private void TextBoxGotoLine(TextBox textbox1, int linenum)
{
// int Linenum is the Absolute Line, not including
// effect of Textbox Wrapping.
if (textbox1.TextWrapping == TextWrapping.Wrap)
{
// If textbox Wrapping is on, we need to
// Correct the Linenum for Wrapping which adds extra lines
int cidx = 0;
bool found = false;
int ln = 0;
char[] tmp = textbox1.Text.ToCharArray();
for (cidx = 0; cidx < tmp.Length; cidx++)
{
if (tmp[cidx] == '\n')
{
ln++;
}
if (ln == linenum)
{
found = true;
break;
}
}
if (!found)
return;
linenum = textbox1.GetLineIndexFromCharacterIndex(cidx+1);
}
// Non-Wrapping TextBox
var target_cpos = textbox1.GetCharacterIndexFromLineIndex(linenum);
var target_char_rect = textbox1.GetRectFromCharacterIndex(target_cpos);
var first_char_rect = textbox1.GetRectFromCharacterIndex(0);
textbox1.ScrollToVerticalOffset(target_char_rect.Top - first_char_rect.Top);
}

Categories

Resources