Referencing buttons with numbers - c#

Is there a way to reference buttons using a numerical value in C#? I am trying to manipulate the text on buttons using one reusable method. Here is my current coding:
One button click method (there are a total of 16):
private void Card1_Click(object sender, EventArgs e)
{
buff = CardClick(1);
if (buff != null)
{
Card1.Text = buff;
}
}
And the reusable method (the code does have holes, it's in development):
private string CardClick(int card)
{
guesses[g++] = card; //alternate g
if ((guesses[0] != null) && (guesses[1] != null))
{
//Reset Card guesses[0]
//Reset Card guesses[1]
return null;
}
else
{
if (card > 8)
{
return map[2, card];
}
else
{
return map[1, card];
}
}

You can also use Controls.Find() to get a reference to your desired button based on its name:
int i = 1;
Control[] matches = this.Controls.Find("Card" + i.ToString(), true);
if (matches.Length > 0 && matches[0] is Button)
{
Button btn = (Button)matches[0];
// ... do something with "btn" ...
btn.PerformClick();
}

You can use an array of buttons
Button[] buttonArray = new Button[10];

You can get all the buttons from your form by Type and then extract an array:
public Button[] AllButtons()
{
var buttons = new List<Button>();
foreach (var control in this.Controls)
{
if (control.GetType() == typeof(Button))
buttons.Add((Button)control);
}
return buttons.ToArray();
}

Related

Need to link two button texts to eachother?

I have two table layout panels with 26 buttons each. I need to link the two button texts to each other. I have two Lists containing one language for one set of buttons and another language for another set of buttons. I tried to link the two lists together in order to set their translations but it didnt work. So for example if you click on one button the text "Hello" will show and another button "Salut". If its a match they must either disappear.
Random random = new Random();
List<string> EngBasicPhrases = new List<string>()
{
"Hello", "How are you?", "Hot", "Thank you", "Welcome",
"Let's go", "My name is...", "Cold", "Good luck",
"Congratulations", "Bless you","I forgot","Sorry","I'm fine",
"It's no problem","Don't worry","Here it is","What?","Of course",
"Boy","Girl","Man","Woman","Friend","Almost","Late"
};
List<string> FrBasicPhrases = new List<string>()
{
"Salut","Ca va?","Chaud", "Merci", "Bienvenu", "Allons-y","Je m'appelle","Du froid",
"Bonne chance","Felicitations","A vos souhaits","J'ai oublie","Desole","Je vais bien",
"Ce n'est pas grave","Ne t'en fais pas","Voila","Comment?","Bien sur","Un garcon","Une fille",
"Un home","Une femme","Un ami","Presque","En retard"
};
Button firstClicked, secondClicked;
public Game()
{
InitializeComponent();
AssignWordsToSquares();
EngBasicPhrases.AddRange(FrBasicPhrases);
}
private void Button_Click(object sender, EventArgs e)
{
if (firstClicked != null && secondClicked != null)
return;
Button clickedButton = sender as Button;
if (clickedButton == null)
return;
if (clickedButton.ForeColor == Color.Black)
return;
if(firstClicked == null)
{
firstClicked = clickedButton;
firstClicked.ForeColor = Color.Black;
return;
}
secondClicked = clickedButton;
secondClicked.ForeColor = Color.Black;
CheckForWinner1();
if (firstClicked.Text == secondClicked.Text)
{
firstClicked = null;
secondClicked = null;
}
else
timer1.Start();
}
private void CheckForWinner1()
{
Button button1;
for (int i = 0; i < tableLayoutPanel1.Controls.Count; i++)
{
button1 = tableLayoutPanel1.Controls[i] as Button;
if (button1 != null && button1.ForeColor == button1.BackColor)
return;
}
MessageBox.Show("Congratulations!");
}
private void Button_Click2(object sender, EventArgs e)
{
if (firstClicked != null && secondClicked != null)
return;
Button clickedButton = sender as Button;
if (clickedButton == null)
return;
if (clickedButton.ForeColor == Color.Black)
return;
if (firstClicked == null)
{
firstClicked = clickedButton;
firstClicked.ForeColor = Color.Black;
return;
}
secondClicked = clickedButton;
secondClicked.ForeColor = Color.Black;
CheckForWinner2();
if (firstClicked.Text == secondClicked.Text)
{
firstClicked = null;
secondClicked = null;
}
else
timer1.Start();
}
private void CheckForWinner2()
{
Button button2;
for (int i = 0; i < tableLayoutPanel2.Controls.Count; i++)
{
button2 = tableLayoutPanel2.Controls[i] as Button;
if (button2 != null && button2.ForeColor == button2.BackColor)
return;
}
MessageBox.Show("Congratulations!");
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
firstClicked.ForeColor = firstClicked.BackColor;
secondClicked.ForeColor = secondClicked.BackColor;
firstClicked = null;
secondClicked = null;
}
private void AssignWordsToSquares()
{
Button button1 = button2;
int randomNumber;
for (int i = 0; i < tableLayoutPanel1.Controls.Count; i++)
{
if (tableLayoutPanel1.Controls[i] is Button)
button1 = (Button)tableLayoutPanel1.Controls[i];
else
continue;
randomNumber = random.Next(0, EngBasicPhrases.Count);
button1.Text = EngBasicPhrases[randomNumber];
EngBasicPhrases.RemoveAt(randomNumber);
}
for (int i = 0; i < tableLayoutPanel2.Controls.Count; i++)
{
if (tableLayoutPanel2.Controls[i] is Button)
button2 = (Button)tableLayoutPanel2.Controls[i];
else
continue;
randomNumber = random.Next(0, FrBasicPhrases.Count);
button2.Text = FrBasicPhrases[randomNumber];
FrBasicPhrases.RemoveAt(randomNumber);
}
}
Ok, so you seem to have two lists to use for ordinal comparison. So, you don't really need to match the words, but the indexes of both lists. That makes sense. But, then it all gets confusing.
Your code does the following right now:
Create a list of English phrases
Create a list of French phrases
Start form
loop through English panel buttons
add a random English phrase to a button in control panel
remove phrase from English list
loop through French panel buttons
add a random French phrase to a button in control panel
remove phrase from French list
Add all remaining French phrases to the list of remaining English phrases (this step seems unnecessary either way)
So now you have your form loaded. If you have less buttons in your panels than you have words in your list, you might have ended up with words in either panel that cannot be matched.
Now you run into this:
private void Button_Click2(object sender, EventArgs e)
{
[...]
if (firstClicked.Text == secondClicked.Text)
{
firstClicked = null;
secondClicked = null;
}
[...]
this is the only place I see an attempt to compare the values of the button. But, by this point there is no way they'll ever match. "Hello" is a string that will never match "Salut" for example. And, since the lists are no longer intact, they can't be used to help match them. Other wise you could just find phrases in their respective lists and check if indexes match.
To allow this, you need to change how you add the button text in your code. Instead of using the list directly create an array from your list. Something like this:
string[] phrases= EngBasicPhrases.ToArray();
for (int i = 0; i < tableLayoutPanel1.Controls.Count; i++)
{
if (tableLayoutPanel1.Controls[i] is Button)
button1 = (Button)tableLayoutPanel1.Controls[i];
else
continue;
randomNumber = random.Next(0, phrases.Count - 1);
button1.Text = phrases[randomNumber];
phrases.RemoveAt(randomNumber);
}
phrases= FrBasicPhrases.ToArray();
for (int i = 0; i < tableLayoutPanel2.Controls.Count; i++)
{
if (tableLayoutPanel2.Controls[i] is Button)
button2 = (Button)tableLayoutPanel2.Controls[i];
else
continue;
randomNumber = random.Next(0, phrases.Count);
button2.Text = phrases[randomNumber];
phrases.RemoveAt(randomNumber);
}
There are some other problems in how you're working with the variables and attempting to use colors to determine state of the button, or infer meaning. But, I'll let you work through those. I recommend using breakpoints and stepping through the code to see the state of your variables and intercept events.
I'd use Dictionary. I would link values like this:
button1.Text == dict[button2.Text]

How to transfer data from a to b Listview

I store in dictionary all the values of listView in dictionary-value and store its index in dictionary-keys at form load.
I am using dictionary as a medium of index storage for corresponding transferred listitems.
Now i transfer from a to b on a button click (a listview is full and b is empty) then i do again transfer the same element from b to a on another button click. It is now appended at last when i do back to b->a transfer. But i want it to append on same index on which it was before transferring to a->b.
I mean when i do b->a transfer then it must go to same index where it used to stay before
My code is this (please correct me where i am wrong and please give me a solution)
private void Form1_Load(object sender, EventArgs e)
{
//storing data in dictionary
}
private void button1_Click(object sender, EventArgs e)
{
MoveSelectedItems(listView1, listView2,0);
}
private void button2_Click(object sender, EventArgs e)
{
MoveSelectedItems(listView2, listView1,1);
}
private void MoveSelectedItems(ListView source, ListView target, int flag)
{
ListViewItem temp = source.SelectedItems[0];
source.Items.Remove(temp);
if(flag==0)//called when i do a->b
{
target.Items.Add(temp);
}
else
{
int index=getIndex(temp);
target.Items.Insert(index, temp);
}
}
private int getIndex(ListViewItem temp)
{
int index = 0;
if (dictList.ContainsValue(temp.Text))
{
foreach (KeyValuePair<int, string> pair in dictList)
if (temp.Text.Equals(pair.Value))
{
index=Convert.ToInt32(pair.Key);
return index;
}
}
return index;
}
What you actually need is, after taking the desired index from the dictionary, to search the items currently in the list view and find the actual insert position.
There are different way you can do that, here is one using binary search:
else
{
foreach (ListViewItem item in source.SelectedItems)
{
ListViewItem lvItem = item.Clone() as ListViewItem;
int index = dictList[item.Text];
// Insert at appropriate position based on index value
if (index == 0) // Always first
target.Items.Insert(0, lvItem);
else if (index == dictList.Count - 1) // Always last
target.Items.Add(lvItem);
else
{
// Binary search the current target items
int lo = 0, hi = target.Items.Count - 1;
while (lo <= hi)
{
int mid = lo + (hi - lo) / 2;
if (index < dictList[target.Items[mid].Text])
hi = mid - 1;
else
lo = mid + 1;
}
// Here lo variable contains the insert position
target.Items.Insert(lo, lvItem);
}
source.Items.Remove(item);
}
}
EDIT: Here is a [mcve] proving that it works:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace Samples
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var form = new Form();
var splitView = new SplitContainer { Dock = DockStyle.Fill, Parent = form, Orientation = Orientation.Vertical };
var listView1 = new ListView { Dock = DockStyle.Fill, Parent = splitView.Panel1, View = View.List };
var listView2 = new ListView { Dock = DockStyle.Fill, Parent = splitView.Panel2, View = View.List };
var buttonPanel = new Panel { Dock = DockStyle.Bottom, Parent = form };
var button1 = new Button { Parent = buttonPanel, Left = 16, Top = 8, Text = ">" };
var button2 = new Button { Parent = buttonPanel, Left = button1.Right + 16, Top = 8, Text = "<" };
buttonPanel.Height = button1.Height + 16;
var dictList = new Dictionary<string, int>
{
{ "first", 0 },
{ "second", 1 },
{ "third", 2 },
{ "fourth", 3 },
{ "fifth", 4 },
{ "sixth", 5 },
{ "seventh", 6 },
};
foreach (var item in dictList)
listView1.Items.Insert(item.Value, item.Key);
Action<ListView, ListView, int> MoveSelectedItems = (ListView source, ListView target, int flag) =>
{
while (source.SelectedItems.Count > 0)
{
var item = source.SelectedItems[0];
source.Items.Remove(item);
if (flag == 0)
{
target.Items.Add(item);
}
else
{
int index = dictList[item.Text];
// Insert at appropriate position based on index value
if (index == 0) // Always first
target.Items.Insert(0, item);
else if (index == dictList.Count - 1) // Always last
target.Items.Add(item);
else
{
// Binary search the current target items
int lo = 0, hi = target.Items.Count - 1;
while (lo <= hi)
{
int mid = lo + (hi - lo) / 2;
if (index < dictList[target.Items[mid].Text])
hi = mid - 1;
else
lo = mid + 1;
}
// Here lo variable contains the insert position
target.Items.Insert(lo, item);
}
}
}
};
button1.Click += (sender, e) => MoveSelectedItems(listView1, listView2, 0);
button2.Click += (sender, e) => MoveSelectedItems(listView2, listView1, 1);
Application.Run(form);
}
}
}
You can add a ListViewItemComparer to the list view. Like this.
public class ListViewItemComparer : IComparer
{
public int Compare(object x, object y)
{
return (((ListViewItem)x).Index > ((ListViewItem)y).Index ? 1 : -1);
}
}
And then in MoveSelectedItems:
this.listView1.ListViewItemSorter = new ListViewItemComparer();
Good luck.

How to check Mouse Out of TabPage in C# Winform?

I want to check the mouse leave of tab area of TabPage. but its not working properly. sometimes I get the messagebox sometimes not.
TabPage mouseTab = null;
void tabControl1_MouseMove(object sender, MouseEventArgs e) {
TabPage checkTab = null;
for (int i = 0; i < tabControl1.TabPages.Count; ++i) {
if (tabControl1.GetTabRect(i).Contains(e.Location)) {
checkTab = tabControl1.TabPages[i];
}
}
if (checkTab == null && mouseTab != null) {
mouseTab = null;
MessageBox.Show("MouseLeave");
} else if (checkTab != null) {
if (mouseTab == null || !checkTab.Equals(mouseTab)) {
mouseTab = checkTab;
}
}
}

How to Show AutoComplete Programmatically without entering a text

C# TextBox
AutoCompleteCustomSource has a List<string>,
AutoCompleteMode = Suggest.
I can see the List when I type a Letter.
How to show entire list without Typing a Letter Programmatically? This must be done while the User presses the Down Arrow Key in the TextBox.
Is there any Win32 API Available?
My Solution
I refined a Better Solution.
Add a ListBox Control to the form and make it as Visible = false
int curSelIndex = -1;
The below given Code will be executed Form_Load Event.
txtEmpId.AutoCompleteCustomSource.AddRange(EmpIds.ToArray());
lstAutoComplete.Items.Clear();
lstAutoComplete.Items.AddRange(EmpIds.ToArray());
txtEmpId.KeyDown += (ks, ke) =>
{
if (!(ke.KeyCode == Keys.Down ||
ke.KeyCode == Keys.Up ||
ke.KeyCode == Keys.Enter))
{
lstAutoComplete.Visible = false;
return;
}
ke.Handled = true;
if (ke.KeyCode == Keys.Enter)
{
if (lstAutoComplete.Visible)
{
var str = lstAutoComplete.SelectedItem + "";
// Process the Selected Item and set to TextBox.
}
}
if (!lstAutoComplete.Visible && txtEmpId.Focused)
{
var loc = txtEmpId.Location;
loc.Y += txtEmpId.Height;
lstAutoComplete.Location = loc;
lstAutoComplete.Size = txtEmpId.Size;
lstAutoComplete.Height = 100;
lstAutoComplete.SelectedIndex = 0;
curSelIndex = 0;
lstAutoComplete.Visible = true;
}
else if(lstAutoComplete.Visible && txtEmpId.Focused)
{
if (ke.KeyCode == Keys.Down)
{
curSelIndex++;
if (curSelIndex >= lstAutoComplete.Items.Count)
curSelIndex = lstAutoComplete.Items.Count - 1;
if (lstAutoComplete.Items.Count > 0)
lstAutoComplete.SelectedIndex = curSelIndex;
}
else if (ke.KeyCode == Keys.Up)
{
curSelIndex--;
if (curSelIndex < 0)
curSelIndex = 0;
if (lstAutoComplete.Items.Count > 0)
lstAutoComplete.SelectedIndex = curSelIndex;
}
}
};
txtEmpId.Leave += (ls, le) => lstAutoComplete.Visible = false;
I didn't find any API for your problem, so I just make a my own suggestion box by using ListBox to show when the Down Arrow Key is pressed, when you do other operation, it disappeares. I hope it is useful to you. code sample is bellow:
//string datasource
List<string> strList = null;
//suggestion listbox
ListBox sugBox = null;
public FrmTextSuggest()
{
InitializeComponent();
//setting the textbox control
strList = new List<string>()
{
"USA",
"England",
"China",
"Japan",
"Korea",
"India",
"France",
"Canada"
};
var autoCollection = new AutoCompleteStringCollection();
autoCollection.AddRange(strList.ToArray());
this.txtCountry.AutoCompleteCustomSource = autoCollection;
this.txtCountry.AutoCompleteMode = AutoCompleteMode.Suggest;
this.txtCountry.AutoCompleteSource = AutoCompleteSource.CustomSource;
//register the Down Arrow Key event
this.txtCountry.KeyDown += new KeyEventHandler(txtCountry_KeyDown);
}
void txtCountry_KeyDown(object sender, KeyEventArgs e)
{
//show the your own suggestion box when pressing down arrow and the text box is empty
if (e.KeyCode == Keys.Down && txtCountry.Text.Trim().Equals(""))
{
sugBox = new ListBox();
//define the box
sugBox.Width = txtCountry.Width;
Point p = txtCountry.Location;
p.Y += txtCountry.Height;
sugBox.Location = p;
sugBox.Items.AddRange(strList.ToArray());
//copy the value to the textbox when selected index changed.
sugBox.SelectedIndexChanged += new EventHandler(sugBox_SelectedIndexChanged);
//show box
if (sugBox.Items.Count > 0)
{
sugBox.SelectedIndex = 0;
this.Controls.Add(sugBox);
sugBox.Focus();
}
}
//remove and hide your own suggestion box when other operation
else
{
if (sugBox != null && this.Controls.Contains(sugBox))
{
this.Controls.Remove(sugBox);
sugBox.Dispose();
sugBox = null;
}
}
}
void sugBox_SelectedIndexChanged(object sender, EventArgs e)
{
string selText = this.sugBox.SelectedItem.ToString();
if (!string.IsNullOrEmpty(selText))
{
this.txtCountry.Text = selText;
}
}
here is my result of test:

C# WPF How do i change the content to a random button?

I am trying to make a Tic Tac Toe game in Silverlight that can be played in 1 player mode.
So for that after clicking on any button and change it's content to "X" or "O" i need to change the content of a random button.
I've tried making a list of all buttons and getting a random value:
public List<string> avail = new List<string>() { "button1", "button2", "button3", "button4", "button5", "button6", "button7", "button8", "button9" };
public string Ran()
{
Random b1 = new Random();
int index = b1.Next(avail.Count);
if (index > 0)
return avail[index];
else
return null;
}
but i don't know how to make my random string a Button so i can call the following method:
public void buttonchange(Button b)
{
if (b.Content.ToString() == "")
if (x == true)
{
x = false;
b.Content = "X";
}
else
{
x = true;
b.Content = "O";
}
if(b.Name!=null)
avail.Remove(b.Name);
}
Any ideas?
thank you!
Make a list of button references instead:
public List<Button> avail = new List<Button>() { button1, button2, button3, button4, button5, button6, button7, button8, button9 };
public Button Ran()
{
Random b1 = new Random();
int index = b1.Next(avail.Count);
if (index > 0) {
return avail[index];
} else {
return null;
}
}
public void buttonchange(Button b)
{
if(b != null) {
if (b.Content.ToString() == "") {
b.Content = x ? "X" : "O";
x = !x;
}
avail.Remove(b);
}
}
Not sure why the button with index zero isn't to be used, though...

Categories

Resources