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,