so i i hade 10x10 grid with pics and i want to swap by drag and drop and i actually cant get
the imgages the targeted and the selected in order to make the spaw
i made all from view model code
in the evens the sender is a grid and the e is DragEventArgs
public MainViewModel()
{
GameGrid = new Grid { AllowDrop = true };
GameGrid.DragOver += GameGrid_DragOver;
GameGrid.Drop += GameGrid_Drop;
for (int row = 0; row < 10; row++)
{
GameGrid.RowDefinitions.Add(new RowDefinition());
for (int col = 0; col < 10; col++)
{
if (row == 0)
GameGrid.ColumnDefinitions.Add(new ColumnDefinition());
var image = new Image { Source = logic.GetImage(), CanDrag = true, AllowDrop = true };
Grid.SetRow(image, row);
Grid.SetColumn(image, col);
GameGrid.Children.Add(image);
}
}
}
private void GameGrid_DragOver(object sender, Windows.UI.Xaml.DragEventArgs e)
{
e.AcceptedOperation = DataPackageOperation.Move;
}
private async void GameGrid_Drop(object sender, Windows.UI.Xaml.DragEventArgs e)
{
if (logic.IsValidSwap(selected, selected))
{
}
}
// but i cant get the imeges to send the func is validswap
Instead of assigning in the event to the grid:
GameGrid.DragOver += GameGrid_DragOver;
GameGrid.Drop += GameGrid_Drop;
It should be assigned to each image inside the for loop:
image.Drop += GameGrid_Drop;
image.DragOver += GameGrid_DragOver;
And than the sender will be the image—you can know the col and row and make switches.
Related
I am making a N*M size SUDOKU game. Every number are on a button.
When the program start all button is empty and I would like if I click to a button it is make a little panel on it with buttons for each number to choose one.
private void adatB_Click(object sender, EventArgs e)
{
Button button = sender as Button;
int[] hely = button.Tag.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(Int32.Parse).ToArray();
Panel szamok = new Panel
{
Location = MousePosition,
Size = new Size(100, 100)
};
Controls.Add(szamok);
TableLayoutPanel minitabla = new TableLayoutPanel
{
Dock = DockStyle.Fill,
ColumnCount = szorzat,
RowCount = szorzat,
};
for (int i = 0; i < szorzat; i++)
{
minitabla.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
minitabla.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
}
szamok.Controls.Add(minitabla);
Button[,] szamokB = new Button[meret[0], meret[1]];
int d = 1;
for (int i = 0; i < meret[0]; i++)
{
for (int j = 0; j < meret[1]; j++)
{
szamokB[i, j] = new Button();
szamokB[i, j].Tag= hely[0]+","+hely[1];
szamokB[i, j].Text = d.ToString();
szamokB[i, j].Dock = DockStyle.Fill;
szamokB[i, j].Click += szamokB_Click;
minitabla.Controls.Add(szamokB[i, j], i, j);
d++;
}
}
}
private void szamokB_Click(object sender, EventArgs e)
{
Button button = sender as Button;
int[] hely = button.Tag.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(Int32.Parse).ToArray();
adatB[hely[0], hely[1]].Text = button.Text;
}
The problem with it when I click a button the pane isn't created.
meret[0] variable is the N, meret[1] is M, adatB is the arry of buttons with the positons in tag.
And If I choosed the number how can I close that panel?
First of all, you should calculate the mouseposition correctly.
From MSDN:
Gets the position of the mouse cursor in screen coordinates.
You should use something like this:
Location = new Point(MousePosition.X - this.Location.X, MousePosition.Y - this.Location.Y)
You will probably need this, to bring your panel to the front:
Controls.Add(szamok);
szamok.BringToFront();
To close the panel you can store the chooser panel and you can remove it from the controls later, use something like this:
public partial class Form1 : Form
{
private Panel myPanel = null;
private void adatB_Click(object sender, EventArgs e)
{
...
Panel szamok = new Panel
{
Location = new Point(MousePosition.X - this.Location.X, MousePosition.Y - this.Location.Y),
Size = new Size(100, 100)
};
if (this.myPanel != null)
{
this.Controls.Remove(this.myPanel);
}
this.myPanel = szamok;
Controls.Add(szamok);
szamok.BringToFront();
...
}
private void szamokB_Click(object sender, EventArgs e)
{
if (this.myPanel != null)
{
this.Controls.Remove(this.myPanel);
this.myPanel = null;
}
...
}
}
I have a stackpanel that I have dynamically added buttons to, based on a 2D array defined elsewhere. So essentially it builds a grid of buttons, but added as children of the stackpanel. What I need to be able to do, is specify a child button based on column and row number. Here's the Stackpanel.
<StackPanel Name="myArea" HorizontalAlignment="Center" VerticalAlignment="Center"/>
And here's some of the code in question.
Grid values = new Grid();
values.Width = 320;
values.Height = 240;
values.HorizontalAlignment = HorizontalAlignment.Center;
values.VerticalAlignment = VerticalAlignment.Center;
int x = valueBoard.GetLength(0);
int y = valueBoard.GetLength(1);
for (int i = 0; i < x; i++)
{
ColumnDefinition col = new ColumnDefinition();
values.ColumnDefinitions.Add(col);
}
for (int j = 0; j < y; j++)
{
RowDefinition row = new RowDefinition();
values.RowDefinitions.Add(row);
}
for (int i = 0; i < x; i++) for (int j = 0; j < y; j++)
{
Button button = new Button();
button.Content = "";
button.Click += ButtonClick;
button.MouseRightButtonUp += RightClick;
Grid.SetColumn(button, i);
Grid.SetRow(button, j);
values.Children.Add(button);
}
myArea.Children.Add(values);
So now, on click of a button, I want to hide all adjacent buttons in the grid. Here's my click event:
private void ButtonClick(object sender, RoutedEventArgs e)
{
int col = Grid.GetColumn((Button)sender);
int row = Grid.GetRow((Button)sender);
Button source = e.Source as Button;
source.Visibility = Visibility.Hidden;
}
How would I, in ButtonClick, hide the neighbor buttons with the col and row values? Is there some sort of getter or setter than I can feed those values into and edit the neighbor's Visibility property?
try the following:
private void ButtonClick(object sender, RoutedEventArgs e)
{
int col = Grid.GetColumn((Button)sender);
int row = Grid.GetRow((Button)sender);
Button source = e.Source as Button;
source.Visibility = Visibility.Hidden;
Grid pGrid = source.Parent as Grid;
if (pGrid == null) throw new Exception("Can't find parent grid.");
for (int i = 0; i < pGrid.Children.Count; i++) {
Button childButton = pGrid.Children[i] as Button;
if(childButton == null) continue;
int childCol = Grid.GetColumn(childButton);
int childRow= Grid.GetRow(childButton);
if(Math.Abs(childCol - col) < 2 && Math.Abs(childRow - row) < 2) childButton.Visibility = Visibility.Hidden;
}
}
this iterates through your children and if it is type of Button it will check, if the row and column is next to your Source and will hide it.
Is there a best practice way to color rows based on row data? I currently have this:
if (dt.Rows.Count > 0)
{
//Finally Add DataTable into DataGridView
dataGridView1.DataSource = dt;
dataGridView1.Columns["File_Name"].Width = 240;
dataGridView1.Columns["Create_Date"].Width = 130;
//dataGridView1.Sort(dataGridView1.Columns["Create_Date"], ListSortDirection.Descending);
dataGridView1.Rows[0].Cells[0].Selected = false;
for (int y = 0; y < unreadList.Count; y++)
{
if ( unreadList[y] == 1 )
dataGridView1.Rows[y].DefaultCellStyle.BackColor = Color.LightPink;
}
}
To clarify, unreadList is an array where a 1 represents that index matched some string on that row index.
But when RowFilter is used etc, the colors vanish. Is there anything to handle this, including if the columns are sorted? My index method will not work after a sort either.
You can do your coloring in the CellFormatting/RowPostPaint events to keep coloring after a filter/sort.
private void gridView_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
for (int y = 0; y < unreadList.Count; y++)
{
if (unreadList[y] == 1)
dataGridView1.Rows[y].DefaultCellStyle.BackColor = Color.LightPink;
}
}
private void gridItems_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.CellStyle.BackColor != Color.LightPink) //This will color every other row green - as an example.
e.CellStyle.BackColor = Color.LightGreen;
}
There is a DataGridView (readonly) and datasource some items are boolean.
The DataGridView render common checkbox for these items and I would like to use some nice tick image. Can I replace the default checkbox rendering with my custom image?
for (int i = 0; i < dataGridView.Rows.Count; i++)
{
int cellsCount = dataGridView.Rows[i].Cells.Count;
for (int j = 0; j < cellsCount; j++)
{
var cells = dataGridView.Rows[i].Cells;
object value = cells[j].Value;
if (value is bool)
{
bool b = (bool)value;
if (b)
{
cells[j].Style.BackColor = Color.LightGreen;
//TODO - add some pretty image of tick
}
else
{
cells[j].Style.BackColor = Color.Orange;
//TODO - add some pretty image of red cross (cancel icon)
}
}
}
}
I do it with some manipulate in previous solution:
private void grdServices_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
DataGridViewImageColumn img = new DataGridViewImageColumn();
img.Name = "img";
img.HeaderText = "CheckOut";
img.ReadOnly = true;
int number_of_rows = grdServices.RowCount;
if (number_of_rows > 0)
{
grdServices.Columns.Add(img);
for (int i = 0; i < number_of_rows; i++)
{
if (bool.Parse(grdServices.Rows[i].Cells[27].Value.ToString()) == true)
{
grdServices.Rows[i].Cells["img"].Value = (System.Drawing.Image)Properties.Resources.yes;
}
else
{
grdServices.Rows[i].Cells["img"].Value = (System.Drawing.Image)Properties.Resources.no;
}
}
}
}
}
have you tried putting image to the cell value?
dataGridView1.Rows[i].Cells[j].Value=new Bitmap("tickImg.png");
Hi I have a small winforms program that will soon develop into something more. The program has 2 panels panel1 and panel2 these panels are populated dynamically with some form controls. the first panel is populated with combo-boxes and the second with a grid of buttons. What I want to achieve is to be able to disable the right button depending on what the user selects from the combobox. Each column of the grid represent a day of the week and the combobox will be used to disable the wanted day by selecting it from the list if you like.
To do this statically is straight forward, however my program will soon expand so that it can handle a large database so that's why I am doing this dynamically. Basically this is where I'm stuck at the moment I want to simply disable the right button.
Below is the interface that i have so far:
And this is my code if any help:
public Form1()
{
InitializeComponent();
}
Button[] btn = new Button[2];
ComboBox[] cmb = new ComboBox[1];
private void Form1_Load(object sender, EventArgs e)
{
placeRows();
}
public void createColumns(int s)
{
for (int i = 0; i < btn.Length; ++i)
{
btn[i] = new Button();
btn[i].SetBounds(40 * i, s, 35, 35);
btn[i].Text = Convert.ToString(i);
panel1.Controls.Add(btn[i]);
}
for (int i = 0; i < cmb.Length; ++i)
{
cmb[i] = new ComboBox();
cmb[i].SelectedIndexChanged += new EventHandler(cmb_SelectedIndexChanged);
cmb[i].Text = "Disable";
cmb[i].Items.Add("Monday");
cmb[i].Items.Add("Tuesday");
cmb[i].SetBounds(40 * i, s, 70, 70);
panel2.Controls.Add(cmb[i]);
}
}
void cmb_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox senderCmb = (ComboBox)sender;
if (senderCmb.SelectedIndex == 1)
{
//MessageBox.Show("Tuesday");
btn[1].Enabled = false;
}
}
public void placeRows()
{
for (int i = 0; i < 80; i = i + 40)
{
createColumns(i);
}
}
}
Alternative 1
Every control has a Tag property.
You can set the Tag property of your buttons to represent the column they are in.
When a selection is made in the combo box, simply search through all buttons, and enable or disable the button based on whether each button's Tag property matches the selected text in the combo box.
Alternative 2
Create a
Dictionary<string, List<Button>> buttonMap;
where the key is the value representing the column ("Tuesday") and the value is a list of buttons with that tag. When creating the buttons initially, also populate that dictionary.
If you go with Alternative 2, you'll have to remember the previously selected value of the checkbox so you can re-enable buttons that are no longer disabled.
If you have lots of buttons, you may find that Alternative 2 is noticeably faster.
UPDATE
Here's a complete working sample of Alternative 1.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
const int ROWS = 2;
const int COLS = 2;
Button[,] btn = new Button[ROWS,COLS];
ComboBox[] cmb = new ComboBox[ROWS];
private void Form1_Load(object sender, EventArgs e)
{
placeRows();
}
private readonly string[] cbTexts = new string[] { "Monday", "Tuesday" };
public void createColumns(int rowIndex)
{
int s = rowIndex * 40;
// Your original code kept overwriting btn[i] for each column. You need a 2-D array
// indexed by the row and column
for (int colIndex = 0; colIndex < COLS; colIndex++)
{
btn[rowIndex, colIndex] = new Button();
btn[rowIndex, colIndex].SetBounds(40 * colIndex, s, 35, 35);
btn[rowIndex, colIndex].Text = Convert.ToString(colIndex);
btn[rowIndex, colIndex].Tag = cbTexts[colIndex];
panel1.Controls.Add(btn[rowIndex, colIndex]);
}
cmb[rowIndex] = new ComboBox();
cmb[rowIndex].SelectedIndexChanged += new EventHandler(cmb_SelectedIndexChanged);
cmb[rowIndex].Text = "Disable";
foreach (string cbText in cbTexts)
{
cmb[rowIndex].Items.Add(cbText);
}
cmb[rowIndex].SetBounds(40, s, 70, 70);
cmb[rowIndex].Tag = rowIndex; // Store the row index so we know which buttons to affect
panel2.Controls.Add(cmb[rowIndex]);
}
void cmb_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox senderCmb = (ComboBox)sender;
int row = (int)senderCmb.Tag;
for (int col = 0; col < COLS; col++)
{
Button b = btn[row, col];
// These three lines can be combined to one. I broke it out
// just to highlight what is happening.
string text = ((string)b.Tag);
bool match = text == senderCmb.SelectedItem.ToString();
b.Enabled = match;
}
}
public void placeRows()
{
for (int rowIndex = 0; rowIndex < 2; rowIndex++)
{
createColumns(rowIndex);
}
}
}