I´m building a ContextMenu on the fly, like this
readinstance = null;
ContextMenu cMenu = new ContextMenu();
for (int i = 0; i < instances.Length; i++) {
string text = String.Format("{0} - {1}", instances[i].Id, instances[i].FormName);
MenuItem item = new MenuItem(text, new EventHandler(cMenuitem_Click));
item.Tag = instances[i];
cMenu.MenuItems.Add(item);
}
cMenu.Show((Button)sender, new Point(0, 0));
cMenu.Dispose();
if (readinstance == null)
throw new Exception("Must select some instance");
and the handler is
void cMenuitem_Click(object sender, EventArgs e)
{
MenuItem item = (MenuItem)sender;
readinstance = (FormPrintingStorage)item.Tag;
}
The menu displays correctly, but when I click some of the options, the handler is not called, so readinstance remains null, and the exception throws. As a side note, when I click any of the options, the menu disappears.
I cannot see what is wrong with my code. Any help will be appreciated.
I´m answering my own question, because I tried more ways.
The first one was to replace the ContextMenu with a ListView and an "Ok" button, at no luck, because the wait loop needed a Thread.Sleep. No comments.
The solution was to implement a new dialog with an empty list view an the Ok button. Some of the relevant code follows. Note that only TreeViewItem/s are moved between the main form and the dialog.
ListViewItem _result = null;
public ListViewItem Result { get { return _result; } }
public List<ListViewItem> Source
{
set
{
listView1.Items.Clear();
foreach (ListViewItem item in value)
listView1.Items.Add(item);
listView1.View = View.List;
}
}
private void button1_Click(object sender, EventArgs e)
{
if (_result == null)
return;
DialogResult = DialogResult.OK;
Close();
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
ListView list = (ListView)sender;
ListView.SelectedIndexCollection indices = list.SelectedIndices;
if (indices.Count == 0)
return;
_result = list.Items[indices[0]];
}
Getting the Result, the main form may do anything it wants with the Tag member. In fact, I´m using the same dialog for two different purposes in the same form.
Related
So I creating some items in favsToolStripMenuItem.DropDown (ToolStripMenuItem) based on a file:
using (StreamReader reader = new StreamReader("text.ini"))
{
while (true)
{
string line = reader.ReadLine();
if (line== null)
break;
favsToolStripMenuItem.DropDown.Items.Add(line);
}
}
But how can I add click event for them? I want a click event based on the item's name (text).
Stub out your click method:
private void DropDown_Click(object sender, EventArgs e) {
ToolStripItem tsi = sender as ToolStripItem;
if (tsi != null) {
MessageBox.Show(tsi.Text);
}
}
and then use the Add parameter that includes the Event Handler:
favsToolStripMenuItem.DropDown.Items.Add(line, null, DropDown_Click);
First you need to assign the event when creating each menu item.
using (StreamReader reader = new StreamReader("text.ini"))
{
while (true)
{
string line = reader.ReadLine();
if (line== null)
break;
ToolStripMenuItem menu = new ToolStripMenuItem(line);
menu.Click += new EventHandler(menu_Click);
favsToolStripMenuItem.DropDown.Items.Add(menu);
}
}
Now, each submenu item has its own event to trigger when clicked. This is how you select which event to trigger based on the name/text of the item,
void menu_Click(object sender, EventArgs e)
{
var menuItem = sender as MenuItem;
var menuText = menuItem.Text;
switch(menuText) {
case "MenuItem1":
// menu item1 clicked .. do something
break;
case "MenuItem2":
// menu item2 clicked .. do something
break;
. ...
}
I have a strange problem with DataGrid context menu. I load item details from server after click on a item in datagrid. While loading the details the application shows a waitscreen:
private void gridViewOrders_MouseDown (object sender, MouseEventArgs e)
{
GridView gv = sender as GridView;
if (gv != null)
{
ShowWaitScreen (message);
GridHitInfo ghi = gv.CalcHitInfo (e.Location);
...
CloseWaitScreen ( );
}
}
When the user click the right mouse button, it should shows a context menu:
private void gridViewOrders_PopupMenuShowing (object sender, PopupMenuShowingEventArgs e)
{
if (e.MenuType == GridMenuType.Row)
{
DXMenuItem item = new DXMenuItem ("Delete", OnBtnDeleteOrder_Click);
e.Menu.Items.Add (item);
}
}
But the menu disappear at once. When I remove the waitscreen, the context menu is shown and the user can select the "Delete" menuitem. Any hints, how I can fix this problem? Thank you!
A good solution for my problem is to do the following:
private void gridViewOrders_MouseDown (object sender, MouseEventArgs e)
{
GridView gv = sender as GridView;
if (gv != null)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
ShowWaitScreen (message);
...
CloseWaitScreen ( )
}
}
}
Thanks to the DevExpress team for the hint!
I dont really thisnk you need to handle anything in MouseDown event.
This code works for GridView:
private void gridView1_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e)
{
GridView view = sender as GridView;
if (e.MenuType == DevExpress.XtraGrid.Views.Grid.GridMenuType.Row)
{
int rowHandle = e.HitInfo.RowHandle;
e.Menu.Items.Clear();
DXMenuItem zaznaczItem = new DXMenuItem("Zaznacz wszystkie", new EventHandler(zaznacz_Click));
DXMenuItem odznaczItem = new DXMenuItem("Odznacz wszystkie", new EventHandler(odznacz_Click));
e.Menu.Items.Add(zaznaczItem);
e.Menu.Items.Add(odznaczItem);
}
}
void zaznacz_Click(object sender, EventArgs e)
{
foreach (DataRow dr in (gcKontrahent.DataSource as DataTable).Rows)
{
dr["checkbox"] = true;
}
}
Handler zaznacz_Click is just example of handler for selected menu item. odznacz_Click is similar so I didnt post it. I dont have example for DataGrid so excuise me if it's not good solution. Just take it as example for acomplishing context menu handling in GridView.
I have a database row with a primary key index and strUsername and I'm using these to dynamically generate dropdown items in a menu strip. The code gives the dropdown item the username string as it's text value and creates an event handler. I want to pass the primary key integer to the click event method but the code I've got gives all the click event methods the database row.count value. Can anyone help please?
// Generate drop down items from database
daUsers.Fill(dtUsers);
// Update mnuFileNew drop down list
if (dtUsers.Rows.Count != 0)
{
mnuFileNew.DropDownItems.Clear();
foreach (dbAutoBloggerDataSet.dbTblUsersRow row in dtUsers.Rows)
{
ToolStripMenuItem newItem = new ToolStripMenuItem(row.strUsername);
newItem.Click += new EventHandler((sender, e) => mnuFileNewUser_Click(sender, e, row.nId));
mnuFileNew.DropDownItems.Add(newItem);
}
}
// Drop down item event handler
private void mnuFileNewUser_Click(object sender, EventArgs e, int nId)
{
frmLogin frmLogin = new frmLogin(nId);
DialogResult result = frmLogin.ShowDialog();
if (result == DialogResult.OK)
{
frmProfile frmProfile = new frmProfile(frmLogin.nId);
frmProfile.ShowDialog();
screenRefresh();
}
}
I think this sample code is useful
void AddMenuItem(string text, string action)
{
ToolStripMenuItem item = new ToolStripMenuItem();
item.Text = text;
item.Click += new EventHandler(item_Click);
item.Tag = action;
//first option, inserts at the top
//historyMenu.Items.Add(item);
//second option, should insert at the end
historyMenuItem.DropDownItems.Insert(historyMenuItem.DropDownItems.Count, item);
}
private void someHistoryMenuItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
string args = menuItem.Tag.ToString();
YourSpecialAction(args);
}
I have a form and I want to get an instance of the same form as stated in the code below. And I have a button: every time I press this button, if a new form is created, I want it to focus to that window, if not, I want to create a new form.
I managed to create a new form but if I want to focus on it, the code did not work, any ideas?
private void btn_Click(object sender, EventArgs e)
{
if (opened == false)
{
Text = "form1";
var form = new myformapp();
form.Show();
opened = true;
form.Text = "form2";
}
else
{
if (Application.OpenForms[1].Focused)
{
Application.OpenForms[0].BringToFront();
Application.OpenForms[0].Focus();
}
if (Application.OpenForms[0].Focused)
{
Application.OpenForms[1].BringToFront();
Application.OpenForms[1].Focus();
}
}
}
You can try shortening your code without the need to introduce more variables with this example:
void button1_Click(object sender, EventArgs e) {
bool found = false;
for (int i = 0; i < Application.OpenForms.Count; ++i) {
if (Application.OpenForms[i].GetType() == typeof(myformapp) &&
Application.OpenForms[i] != this) {
Application.OpenForms[i].Select();
found = true;
}
}
if (!found) {
myformapp form = new myformapp();
form.Show();
}
}
Updated code from Francesco Baruchelli's comment.
If I understand correctly what you are trying to do, you can keep a static List with the opened forms. Everytime an instance of your Form is opened you add it to the List, and everytime it is closed you remove it. The when you press the button you can check the size of the List. If it is 1 you create a new Form, open it and set the focus on it. If the size is already 2, you look in the List for the instance which is different from the one executing the click event. The code could be something like this:
private static List<Form1> openForms = new List<Form1>();
private void button1_Click(object sender, EventArgs e)
{
Form1 frm = null;
if (openForms.Count == 2)
{
foreach (Form1 aForm in openForms)
if (aForm != this)
{
frm = aForm;
break;
}
}
else
{
frm = new Form1();
frm.Show();
}
frm.Focus();
}
private void Form1_Load(object sender, EventArgs e)
{
openForms.Add(this);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
openForms.Remove(this);
}
I have a list box which is bound to a Service. It loads fine and allows me to select an item and moves through to second page.
The Second page loads a new observable collection from the same service and uses the selected Item from previous page to load a new listbox with a data filter.
This second listbox allows for a further selection to load a details page based on this selection. The error I have is that the second listbox loads and automatically selects the first item in the list. Upon pushing the back button it loads the second listbox with no selection made.
Can someone please tell me how to stop the automatic selection in my second listbox? Code details below.
First Listbox code including sender
void ServiceReference1Client_GetMensleaderListCompleted(object sender, GetMensLeaderListCompletedEventArgs e)
{
if (e.Error != null) { MensHeading.Text = "Connect to Data"; return; }
ObservableCollection<Mens_Leaders> mensLeaders = e.Result;
this.mensRankings.ItemsSource = mensLeaders;
}
private void mensRankings_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (mensRankings.SelectedItem != null)
{
Mens_Leaders SelectedPlayer = mensRankings.SelectedItem as Mens_Leaders;
_SelectedMensPlayer = (sender as ListBox).SelectedItem;
NavigationService.Navigate(new Uri("/Pages/PlayerProfile.xaml", UriKind.Relative));
FrameworkElement root2 = Application.Current.RootVisual as FrameworkElement;
root2.DataContext = _SelectedMensPlayer;
}
}
Page where second list loads
private void LoadPlayerList()
{
Service1Client ServiceReference1Client = new Service1Client();
ServiceReference1Client.GetTournamentListCompleted += new EventHandler<GetTournamentListCompletedEventArgs>(ServiceReference1Client_GetTournamentListCompleted);
ServiceReference1Client.GetTournamentListAsync();
FrameworkElement root2 = Application.Current.RootVisual as FrameworkElement;
var currentPlayer = root2.DataContext as ATP_Tennis_App.TennisService.Mens_Leaders;
_SelectedPlayer = currentPlayer;
_selectedPlayerTournamentsWon = currentPlayer.Name;
}
void ServiceReference1Client_GetTournamentListCompleted(object sender, GetTournamentListCompletedEventArgs e)
{
if (e.Error != null) { return; }
ObservableCollection<Tournaments> tournamentList = e.Result;
viewSource = new CollectionViewSource();
viewSource.Filter += TournamentWin_Filter;
viewSource.Source = tournamentList;
this.listBox1.ItemsSource = viewSource.View;
}
void TournamentWin_Filter(object sender, FilterEventArgs e)
{
if (e.Item != null)
e.Accepted = ((Tournaments)e.Item).Prev_Male_Winner.Contains(_selectedPlayerTournamentsWon);
}
private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (listBox1.SelectedItem != null)
{
Tournaments selectedTournament1 = listBox1.SelectedItem as Tournaments;
_SelectedItemTournament = (sender as ListBox).SelectedItem;
NavigationService.Navigate(new Uri("/Pages/TournamentDetailsPanorama.xaml", UriKind.Relative));
FrameworkElement root3 = Application.Current.RootVisual as FrameworkElement;
root3.DataContext = _SelectedItemTournament;
}
else
{
return;
}
}
On the listbox, set the IsSynchroziedWithCurrentItem to False. This fixed the issue.
I know this is a dirty solution, but you can set listBox1.SelectedIndex = -1