I have a WPF window with a grid (named SimOrder_grd) that is built into my MainWindow that is filled with buttons inside my MainWindow_Loaded event as follows:
public partial class MainWindow: Window
{
List<DirectiveObjects> SimOrders = new List<DirectiveObjects>();
SqlConnection admin_connect = ... (removed for post)
public MainWindow()
{
InitializeComponenent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
admin_connect.Open();
string sim_sqlString = "SELECT * FROM dbo.SimOrder;";
//get all sim orders from database
using (SqlCommand so_cmd = new SqlCommand(sim_sqlString,admin_connect))
{
SqlDataReader so_rd = so_cmd.ExecuteReader();
while (so_rd.Read())
{
SimOrders.Add(new DirectiveObjects
{
id= Convert.ToInt16(so_rd["Id"]),
title = so_rd["Title"].ToString(),
});
}
}
admin_connect.Close();
int topmargin = 0; int rownum = 0;
foreach(DirectiveObjects dir in SimOrders)
{
//generate button
Button dir_btn = new Button();
dir_btn.Content = dir.title; dir_btn.Width = SimOrder_grd.Width;
dir_bt.Height = 20;
dir_btn.Margin = new Thickness(0, topmargin, 0,0);
dir_btn.Name = dir.title + "_btn";
dir_btn.Click += dir_btn_Click;
SimOrder_grd.Children.Add(dir_btn); topmargin += 25; rownum++;
}
}
This all works as expected, and I get a nice button inside of my grid that I can click on; dir_btn_click event works fine. However, I've created a button where users can add there own "SimOrder" to the grid menu. It is called AddSimO and the button click works below:
private void AddSimO_btn_Click(object sender, RoutedEventArgs e)
{
string DBName = "dbo.SimOrder"; string GridName = "SimOrder_grd";
var CreateNewDialog = new FrAdministration.SimAdd(DBName, GridName);
CreateNewDialog.Show();
}
This opens a new window that the user can type in a new title for a sim order, it get's saved to the database like so. From SimAdd.xaml.cs;
public partial class SimAdd: Window
{
public SimAdd(string db, string grid)
{
InitializeComponent();
}
private void Cancel_btn_Click(object sender, RoutedEventArgs e)
{
this.Close(); //cancel button closes the window.
}
private void saveSim_btn_Click(object sender, RoutedEventArgs e)
{
if (String.IsNullOrEmpty(SimName_txt.Text){MessageBox.Show("Please enter a title");}
else
{
SqlConnection Si_connect = new ...(removed again)
Si_connect.Open();
string add_sqlString = "INSERT INTO dbo.SimOrder (Title) VALUES (@title);";
using (SqlCommand add_cmd = new SqlCommand(add_sqlString, SimConnect))
{
add_cmd.Parameters.Add("@title", SqlDbType.NvarChar).Value = SimName_txt.Text;
add_cmd.ExecuteNonQuery();
}
Si_connect.Close();
this.Close();
MainWindow mwindow = new FrAdministration.MainWindow();
mwindow.Sim_update();
}
}
}
This works as well as I can see my database update. The next piece is where my question lies.
How can I get my grid to update with the new button for the new entry I've created in my database. Here is what I've tried:
1.) I tried to recreate my button list inside of the Sim_update method called in the SimAdd window.
public void Sim_update()
{
admin_connect.Open();
SimOrder_grd.Children.Clear(); SimOrders.Clear();
this.UpdateLayout();//saw this on Stack Overflow and thought I'd try.
string sim_sqlString = "SELECT * FROM dbo.SimOrder;";
//get all sim orders from database
using (SqlCommand so_cmd = new SqlCommand(sim_sqlString,admin_connect))
{
SqlDataReader so_rd = so_cmd.ExecuteReader();
while (so_rd.Read())
{
SimOrders.Add(new DirectiveObjects
{
id= Convert.ToInt16(so_rd["Id"]),
title = so_rd["Title"].ToString(),
});
}
}
admin_connect.Close();
int topmargin = 0; int rownum = 0;
foreach(DirectiveObjects dir in SimOrders)
{
//generate button
Button dir_btn = new Button();
dir_btn.Content = dir.title; dir_btn.Width = SimOrder_grd.Width;
dir_bt.Height = 20;
dir_btn.Margin = new Thickness(0, topmargin, 0,0);
dir_btn.Name = dir.title + "_btn";
dir_btn.Click += dir_btn_Click;
SimOrder_grd.Children.Add(dir_btn); topmargin += 25; rownum++;
}
}
I understand this is the same information that was in MainWindow_Loaded event, but this wouldn't work.
2.) I tried adding this.UpdateLayout(); and this.InvalidateVisual() after my foreach loop and after my grid clearing, but that didn't seem to help. I also tried SimOrder_grd.UpdateLayout(); and SimOrder_grd.InvalidateVisual();.
3.) I created a button to refresh my page called Refresh. This works to refresh my grid when I manually click the button.
private void Refresh_Click(object sender, RoutedEventArgs e)
{
admin_connect.Open();
SimOrder_grd.Children.Clear(); SimOrders.Clear();
this.UpdateLayout();
string sim_sqlString = "SELECT * FROM dbo.SimOrder;";
//get all sim orders from database
using (SqlCommand so_cmd = new SqlCommand(sim_sqlString,admin_connect))
{
SqlDataReader so_rd = so_cmd.ExecuteReader();
while (so_rd.Read())
{
SimOrders.Add(new DirectiveObjects
{
id= Convert.ToInt16(so_rd["Id"]),
title = so_rd["Title"].ToString(),
});
}
}
admin_connect.Close();
int topmargin = 0; int rownum = 0;
foreach(DirectiveObjects dir in SimOrders)
{
//generate button
Button dir_btn = new Button();
dir_btn.Content = dir.title; dir_btn.Width = SimOrder_grd.Width;
dir_bt.Height = 20;
dir_btn.Margin = new Thickness(0, topmargin, 0,0);
dir_btn.Name = dir.title + "_btn";
dir_btn.Click += dir_btn_Click;
SimOrder_grd.Children.Add(dir_btn); topmargin += 25; rownum++;
}
}
I don't want the users to have to click another button to see their changes, so I tried to automate the button in the following ways (all inside of Sim_update from the 4th code quote block).
4.) ButtonAutomationPeer peer = new ButtonAutomationPeer(Refresh); IInvokeProvider invoker = peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider; invoker.Invoke();
5.) Refresh.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
6.) Refresh.Click(this,null);
Both of these will run the Refresh_Click event, but neither updates the grid like manually pressing the Refresh button.
Lastly I tried the following inside Sim_update(): 7.)
this.Dispatcher.BeginInvoke(new Action() => this.SimOrder_grd.UpdateLayout()), null);
and 8.) Action EmptyDelegate = delegate(){}; SimOrder_grd.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
I am all out of ideas, and I would really like to know functionally why everything I'm trying is not working.
Is it because I'm coming from a second window and running method without activating the main window?
Is it because ButtonAutomationPeer does not update the UI the same as manually clicking the button?
Thank you all,
DataGridTemplateColumnto create a template with a button in aDataGrid.