Combobox passed as a Control template then as a popup - c#

I have a combobox "recent_users" as a control template and then as a poppup. How can I pass the selected value of the popup to the method below?(popup click)
recent_users.SelectedItem.ToString() always returns null.
private void usernameEnter_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
Trace.WriteLine("testing dropdown");
ControlTemplate ct = recent_users.Template;
Popup popup1 = ct.FindName("PART_Popup", recent_users) as Popup;
if (popup1 != null)
{
popup1.Placement = PlacementMode.Top;
}
recent_users.IsDropDownOpen = true;
popup1.PreviewMouseUp += new MouseButtonEventHandler((s,e) => popupClick(s,e,recent_users.SelectedItem.ToString()));
}
private void popupClick(object sender, MouseButtonEventArgs e, String recent)
{
usernameEnter.Text = recent;
Trace.WriteLine("appending norms");
}
}
}

Isn't it because the user has not made any selection in the ComboBox? I have re-written the code slightly
private void usernameEnter_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
ControlTemplate ct = recent_users.Template;
Popup popup1 = ct.FindName("PART_Popup", recent_users) as Popup;
if (popup1 != null)
{
popup1.Placement = PlacementMode.Top;
}
recent_users.IsDropDownOpen = true;
// if none selected, set first as selected
if (recent_users.SelectedIndex < 0 && recent_users.HasItems)
{
recent_users.SelectedIndex = 0;
}
var selectedItem = recent_users.SelectedItem as ComboBoxItem;
var selectedUser = selectedItem.Content.ToString();
popup1.PreviewMouseUp += new MouseButtonEventHandler((s, e) => popupClick(s, e, selectedUser));
}
But I was wondering adding a handler for PreviewMouseUp event (in the last line) is something that you really want. I would have fetched the selected user in the SelectionChanged of the recent_users rather.

Related

How to re-enable listbox when removing a specified item from an output listbox

I am trying to re-enable only the listbox that pertains to the item that has been removed from the output listbox. For example, If I select "Wagon" from Body Type listbox and "Advance" from Package listbox, the listbox named "lstOutPut" displays the following:
What I want to do is, if I were to remove "SUV", I would only want for Body Type listbox re-enabled and not the rest
Here is my code
private void lstBody_SelectedIndexChanged(object sender, EventArgs e)
{
if (lstBody.SelectedItem != null)
{
lstOutput.Items.Add(lstBody.SelectedItem);
lstBody.SelectionMode = SelectionMode.None;
lstBody.Enabled = false;
}
}
private void lstPackage_SelectedIndexChanged(object sender, EventArgs e)
{
if (lstPackage.SelectedItem != null)
{
lstOutput.Items.Add(lstPackage.SelectedItem);
lstPackage.SelectionMode = SelectionMode.None;
lstPackage.Enabled = false;
}
}
And this is what I have for the remove button
private void btnRemove_Click(object sender, EventArgs e)
{
//remove selected item only
while (lstOutput.SelectedItems.Count > 0)
{
lstOutput.Items.Remove(lstOutput.SelectedItems[0]);
}
lstBody.Enabled = true;
lstPackage.Enabled = true;
}
Any ideas?
Thanks.
Assuming there would not be duplicates values among the different input listboxes,you could do the following in the btnRemove_Click event
var inputListBoxes = new[] { lstPackage, lstBody };
while (lstOutput.SelectedItems.Count > 0)
{
inputListBoxes.First(x => x.Items.Contains(lstOutput.SelectedItems[0])).Enabled = true;
lstOutput.Items.Remove(lstOutput.SelectedItems[0]);
}
For each listbox, enable it if non of its items exist in lstOutput:
var listBoxes = new ListBox[] {body, package, wheel, accessories};
foreach(var lst in listBoxes)
lst.Enabled = !lst.Items.Cast<string>().Any(x => lstOutput.Items.Contains(x));

How to set Textbox.Enabled from false to true on TextChange?

I programmatically create a Form with two textboxes. My goal is to disable one textbox if I type something in the second one and contrariwise. I managed to disable second textbox on first textbox textchange,but can't figure out how enable it when the first textbox.Text is empty.
Here is the code :
private void metaName_TextChanged(object sender,EventArgs e)
{
var ctrl = (Control)sender;
var frm = ctrl.FindForm();
TextBox metaTxt = null;
foreach (var ctr in frm.Controls)
{
if (ctr is TextBox)
{
metaTxt = (TextBox)ctr;
if (metaTxt.Name == "metaHTTPEquiv")
{
metaTxt.Enabled = false;
}
else
if (?)
{
}
}
}
}
I want to make something like this :
if(textBox3.Text == String.Empty)
{
textBox4.Enabled = true;
}
else
if(textBox3.Text != String.Empty)
{
textBox4.Enabled = false;
}
You can check only the textchanged event for each one like the following:
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox2.Enabled = !(textBox1.Text.Length >= 1);
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
textBox1.Enabled = !(textBox2.Text.Length >= 1);
}
The self textbox has some values, then the enabled will be false for the other one
First set a flag to enable or disable the second control based on the content of the metaName textbox that raises the event, then search for the second textbox using a bit of Linq.
private void metaName_TextChanged(object sender,EventArgs e)
{
TextBox ctrl = sender as TextBox;
if(ctrl != null)
{
bool enable = !string.IsNullOrEmpty(ctrl.Text);
TextBox secondOne = this.Controls
.OfType<TextBox>()
.FirstOrDefault(x => x.Name == "metaHTTPEquiv");
if(secondOne != null)
secondOne.Enabled = enable;
}
}
The same code, reversing the textboxes roles, could be used as the event handler of the second textbox.
Forget about control events and use data binding.
Take the following helper method
static void Bind(Control target, string targetProperty, object source, string sourceProperty, Func<object, object> expression)
{
var binding = new Binding(targetProperty, source, sourceProperty, true, DataSourceUpdateMode.Never);
binding.Format += (sender, e) => e.Value = expression(e.Value);
target.DataBindings.Add(binding);
}
and just add something like this in your form load event
Bind(textBox2, "Enabled", textBox1, "Text", value => string.IsNullOrEmpty((string)value));

Showing a Context Menu for an item in a ListView

I know how to make a contextMenu that pops up when I right click on a listView, what I want is for it to pop up when I right click on an item. I am trying to make a chat server and client, and now... Now I want to view client info when I right click on a connected client's item.
How can I do this?
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
var focusedItem = listView1.FocusedItem;
if (focusedItem != null && focusedItem.Bounds.Contains(e.Location))
{
contextMenuStrip1.Show(Cursor.Position);
}
}
}
You can put connected client information in the contextMenuStrip1. and when you right click on a item, you can show the information from that contextMenuStrip1.
You are going to have to use the ListViews Context Menu, but change it according to the ListView Item you right click on.
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
bool match = false;
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
foreach (ListViewItem item in listView1.Items)
{
if (item.Bounds.Contains(new Point(e.X, e.Y)))
{
MenuItem[] mi = new MenuItem[] { new MenuItem("Hello"), new MenuItem("World"), new MenuItem(item.Name) };
listView1.ContextMenu = new ContextMenu(mi);
match = true;
break;
}
}
if (match)
{
listView1.ContextMenu.Show(listView1, new Point(e.X, e.Y));
}
else
{
//Show listViews context menu
}
}
}
You can trigger MouseDown or MouseUp event of ListView in which if MouseButton.Right then grab the selected Item by using ListView.Hittest and give the Context menu related to that Selected Item.
For more clear info you can go through this link
Fully solution
Pops up when user right click on a item in a listView.
Avoid an exception if the list have no items.
If an item was selected, display Delete and Edit options.
Code:
private void Form1_Load(object sender, EventArgs e)
{
listView1.MouseUp += new MouseEventHandler(listView1_MouseClick);
}
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
string id = "xxx";//extra value
if (e.Button == MouseButtons.Right)
{
if (listView1.FocusedItem != null && listView1.FocusedItem.Bounds.Contains(e.Location) == true)
{
ContextMenu m = new ContextMenu();
MenuItem cashMenuItem = new MenuItem("編輯");
cashMenuItem.Click += delegate (object sender2, EventArgs e2) {
ActionClick(sender, e, id);
};// your action here
m.MenuItems.Add(cashMenuItem);
MenuItem cashMenuItem2 = new MenuItem("-");
m.MenuItems.Add(cashMenuItem2);
MenuItem delMenuItem = new MenuItem("刪除");
delMenuItem.Click += delegate (object sender2, EventArgs e2) {
DelectAction(sender, e, id);
};// your action here
m.MenuItems.Add(delMenuItem);
m.Show(listView1, new Point(e.X, e.Y));
}
}
}
private void DelectAction(object sender, MouseEventArgs e, string id)
{
ListView ListViewControl = sender as ListView;
foreach (ListViewItem eachItem in ListViewControl.SelectedItems)
{
// you can use this idea to get the ListView header's name is 'Id' before delete
Console.WriteLine(GetTextByHeaderAndIndex(ListViewControl, "Id", eachItem.Index) );
ListViewControl.Items.Remove(eachItem);
}
}
private void ActionClick(object sender, MouseEventArgs e, string id)
{
//id is extra value when you need or delete it
ListView ListViewControl = sender as ListView;
foreach (ListViewItem tmpLstView in ListViewControl.SelectedItems)
{
Console.WriteLine(tmpLstView.Text);
}
}
public static string GetTextByHeaderAndIndex(ListView listViewControl, string headerName, int index)
{
int headerIndex = -1;
foreach (ColumnHeader header in listViewControl.Columns)
{
if (header.Name == headerName)
{
headerIndex = header.Index;
break;
}
}
if (headerIndex > -1)
{
return listViewControl.Items[index].SubItems[headerIndex].Text;
}
return null;
}
The topic is quite old, but I'll leave my solution for reference.
In xaml ListView definition put your context menu:
<ListView Name="m_list" >
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="menuItem1" Click="ContextMenuItem1Clicked" />
<MenuItem Header="menuItem2" Click="ContextMenuItem2Clicked" />
</ContextMenu>
</ListView.ContextMenu>
...
</ListView>
Now, in the code, define two event handlers that will fire up on clicking respective menu item:
private void ContextMenuItem1Clicked(object sender, RoutedEventArgs e)
{
// handle the event for the selected ListViewItem accessing it by
ListViewItem selected_lvi = this.m_list.SelectedItem as ListViewItem;
}
private void ContextMenuItem2Clicked(object sender, RoutedEventArgs e)
{
// handle the event for the selected ListViewItem accessing it by
ListViewItem selected_lvi = this.m_list.SelectedItem as ListViewItem;
}
ListView can accommodate objects, which means that the selected_lvi can be of type of your object. Just cast is to proper type.
I hope this helps.
Best regards,
Mike
I've found a new solution that doesn't rely on mouse event handlers.
The ContextMenu has a "Popup" event handler.
On popup, I add the relevant menu items I need depending on my context.
Example :
private MenuItem[] standardMenuItems;
private MenuItem[] selectedMenuItems;
public SomePanel() {
InitializeComponent();
// These are list of menu items (name / callback) that will be
// chosen depending on some context
standardMenuItems = new MenuItem[] { new MenuItem("New", OnNew) };
selectedMenuItems = new MenuItem[] { new MenuItem("Delete", OnDelete), new MenuItem("Edit", OnEdit) };
ContextMenu contextMenu = new ContextMenu();
// begin with "standard items"
contextMenu.MenuItems.AddRange(standardMenuItems);
listview.ContextMenu = contextMenu;
// add the popup handler
contextMenu.Popup += OnMenuPopup;
}
// Called right before the menu comes up
private void OnMenuPopup(object sender, EventArgs e) {
ContextMenu menu = sender as ContextMenu;
if (menu == null)
return;
// If an item was selected, display Delete and Edit options
if (listview.SelectedItems.Count > 0) {
menu.MenuItems.Clear();
menu.MenuItems.AddRange(selectedMenuItems);
}
// Else display only the New option
else {
menu.MenuItems.Clear();
menu.MenuItems.AddRange(standardMenuItems);
}
}
I'm not fluent enough in C# and Winforms to be sure there are no drawbacks to this technique, but it's an alternative to relying on mouse events (what if / does the context menu can appear on other keyboard or mouse event ?)
private void contextMenuStripExport_Opening(object sender, System.ComponentModel.CancelEventArgs e)
{
if (exportview.SelectedItems.Count <= 0)
{
uploadToolStripMenuItem.Visible = false;
exportToolStripMenuItem.Visible = false;
}
else
{
uploadToolStripMenuItem.Visible = true;
exportToolStripMenuItem.Visible = true;
}
}
Using DevExpress 20.2 Core... Winforms. This is similar to handling a menu item in a GridView.
Private WithEvents _menuViewLabelitem As MenuItem
Private Sub lvShipTracking_MouseClick(sender As Object, e As MouseEventArgs) Handles lvShipTracking.MouseClick
If e.Button = MouseButtons.Right Then
If lvShipTracking.FocusedItem IsNot Nothing AndAlso lvShipTracking.FocusedItem.Bounds.Contains(e.Location) = True Then
Dim m As ContextMenu = New ContextMenu()
_menuViewLabelitem = New MenuItem("View Label")
AddHandler Click, AddressOf Handle_ViewLabel
m.MenuItems.Add(_menuViewLabelitem)
m.Show(lvShipTracking, New Point(e.X, e.Y))
End If
End If
End Sub
Private Sub Handle_ViewLabel(sender As Object, e As EventArgs) Handles _menuViewLabelitem.Click
MsgBox("it worked!")
End Sub

RadioButtons CheckedChanged event

I have 20 radiobuttons on the page and I want to know which one of them was clicked.
protected void Page_Load(object sender, EventArgs e)
{
Button newBTN = new Button();
newBTN.Text = "Button 1";
PlaceHolder1.Controls.Add(newBTN);
for (int i = 0; i < 20; i++)
{
RadioButton r = new RadioButton();
r.ID = i.ToString();
r.CheckedChanged += RadioButton1_CheckedChanged;
PlaceHolder1.Controls.Add(r);
}
}
New Updated code.. NOTE: THE CODE DOESNT RELATE TO THE ABOVE CODE.
public List<int> ThreadID2Treat { get { return ViewState["Checked"] == null ? null : (List<int>)ViewState["Checked"]; } set { ViewState["Checked"] = value; } }
protected void CheckBox1_CheckedChanged(object sender, EventArgs e)
{
var rad = (CheckBox)sender;
int threadID = int.Parse(rad.ID.ToString());
ThreadID2Treat.Add(threadID);
}
public void DeleteButton_Clicked(object sender, EventArgs e)
{
foreach (var item in ThreadID2Treat)
{
UsefulStaticMethods.DeleteThreads(item);
}
}
How do i find out?
var rad = (RadioButton)sendder;
Response.Write("RadioButton Id :" + rad.Id.ToString());
You could try the above.
Update :
To get all select radio buttons in PlaceHolder make sure the AutoPostBack is not set on the radio buttons. You dont need to add CheckChanged Event. "r.CheckedChanged += RadioButton1_CheckedChanged;" <= remove.
StringBuilder stringBuilder = new StringBuilder();
foreach (var control in placeHolder1.Controls)
{
var rad = control as RadioButton;
if (rad != null)
{
if (rad.Checked)
stringBuilder.AppendLine(String.Format("Radion Button Checked : {0}", rad.ID));
}
}
Response.Write(stringBuilder.ToString());
With the parameter sender you have a direct reference to the event-source control.
var rb = (RadioButton)sender;
If you want to trigger this event and the postback directly, you must set the RadioButton's AutoPostBack-Property to true.
protected void RadioButton1_CheckedChanged(object sender, EventArgs e)
{
if (sender is RadioButton)
{
RadioButton radioButton = (RadioButton)sender;
//Code to use radioButton's properties to do something useful.
// get the radio button by its ID
string id = radioButton.ID;
}
}
You can try this.
RadioButton r = sender as RadioButton;
Response.Write(r.Id);
Cast sender as RadioButton:
RadioButton r = sender as RadioButton;
if(r != null)
{
//Do stuff
}

How can I add a context menu to a ListBoxItem?

I have a ListBox and I want to add a context menu to each item in the list. I've seen the "solution" to have the right click select an item and suppress the context menu if on white space, but this solution feels dirty.
Does anyone know a better way?
Just to elaborate a little further to what Frans has said...Even though the ListBox owns the ContextMenuStrip, you can still customize the items in the menu strip at the time it's opening. Thus customizing it's contents based on the mouse position within the listbox.
The example below selects the item in the listbox based on a right mouse click and then customizes a context menu strip based on the item the user right-clicked on. This is a simple example but should get you going: Add a listbox to a form and add this code:
#region Private Members
private ContextMenuStrip listboxContextMenu;
#endregion
private void Form1_Load( object sender, EventArgs e )
{
//assign a contextmenustrip
listboxContextMenu = new ContextMenuStrip();
listboxContextMenu.Opening +=new CancelEventHandler(listboxContextMenu_Opening);
listBox1.ContextMenuStrip = listboxContextMenu;
//load a listbox
for ( int i = 0; i < 100; i++ )
{
listBox1.Items.Add( "Item: " + i );
}
}
private void listBox1_MouseDown( object sender, MouseEventArgs e )
{
if ( e.Button == MouseButtons.Right )
{
//select the item under the mouse pointer
listBox1.SelectedIndex = listBox1.IndexFromPoint( e.Location );
if ( listBox1.SelectedIndex != -1)
{
listboxContextMenu.Show();
}
}
}
private void listboxContextMenu_Opening( object sender, CancelEventArgs e )
{
//clear the menu and add custom items
listboxContextMenu.Items.Clear();
listboxContextMenu.Items.Add( string.Format( "Edit - {0}", listBox1.SelectedItem.ToString() ) );
}
Hope that help.
This way the menu will pop up next to the mouse
private string _selectedMenuItem;
private readonly ContextMenuStrip collectionRoundMenuStrip;
public Form1()
{
var toolStripMenuItem1 = new ToolStripMenuItem {Text = "Copy CR Name"};
toolStripMenuItem1.Click += toolStripMenuItem1_Click;
var toolStripMenuItem2 = new ToolStripMenuItem {Text = "Get information on CR"};
toolStripMenuItem2.Click += toolStripMenuItem2_Click;
collectionRoundMenuStrip = new ContextMenuStrip();
collectionRoundMenuStrip.Items.AddRange(new ToolStripItem[] {toolStripMenuItem1, toolStripMenuItem2 });
listBoxCollectionRounds.MouseDown += listBoxCollectionRounds_MouseDown;
}
private void toolStripMenuItem2_Click(object sender, EventArgs e)
{
var info = GetInfoByName(_selectedMenuItem);
MessageBox.Show(info.Name + Environment.NewLine + info.Date);
}
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
Clipboard.SetText(_selectedMenuItem);
}
private void myListBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Right) return;
var index = myListBox.IndexFromPoint(e.Location);
if (index != ListBox.NoMatches)
{
_selectedMenuItem = listBoxCollectionRounds.Items[index].ToString();
collectionRoundMenuStrip.Show(Cursor.Position);
collectionRoundMenuStrip.Visible = true;
}
else
{
collectionRoundMenuStrip.Visible = false;
}
}
There's no other way: the context menu isn't owned by the item in the listbox but by the listbox itself. It's similar to the treeview control which also owns the context menu instead of the treenode. So whenever an item in the listbox is selected, set the context menu of the listbox according to the selected item.
And Here it is My Solution :
listBox_Usernames.ContextMenuStrip = contextMenuStripRemove;
listBox_Usernames.MouseUp += new MouseEventHandler(listBox_Usernames_MouseUp);
void listBox_Usernames_MouseUp(object sender, MouseEventArgs e)
{
int index = listBox_Usernames.IndexFromPoint(e.Location);
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
if (index != ListBox.NoMatches)
{
if (listBox_Usernames.SelectedIndex == index)
{
listBox_Usernames.ContextMenuStrip.Visible = true;
}
else
{
listBox_Usernames.ContextMenuStrip.Visible = false;
}
}
else
{
listBox_Usernames.ContextMenuStrip.Visible = false;
}
}
else
{
listBox_Usernames.ContextMenuStrip.Visible = false;
}
}
In XAML it shows like this:
<ListBox>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Add User..."/>
<MenuItem Header="Edit..."/>
<MenuItem Header="Disable"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
In one line of code (more for binding):
var datasource = new BindingList<string>( new List<string>( new string[] { "item1" } ) );
listbox.DataSource = datasource ;
listbox.ContextMenu = new ContextMenu(
new MenuItem[] {
new MenuItem("Delete",
new EventHandler( (s,ev) =>
datasource.Remove(listbox.SelectedItem.ToString())
)
)
});
private void buttonAdd_Click(object sender, EventArgs e)
{
datasource.Add( textBox.Text );
}
If its just a question of enabling or disabling context menu items, it might be more efficient to only do it when the context menu is launched rather than every time the list box selection changes:
myListBox.ContextMenu.Popup += new EventHandler(myContextPopupHandler);
private void myContextPopupHandler(Object sender, System.EventArgs e)
{
if (SelectedItem != null)
{
ContextMenu.MenuItems[1].Enabled = true;
ContextMenu.MenuItems[2].Enabled = true;
}
else
{
ContextMenu.MenuItems[1].Enabled = false;
ContextMenu.MenuItems[2].Enabled = false;
}
}
this one is best...
using System.Windows.Forms;
ContextMenuStrip menu;
this.menu.Items.AddRange(new ToolStripItem[] { this.menuItem });
this.listBox.MouseUp += new MouseEventHandler(this.mouse_RightClick);
private void mouse_RightClick(object sender, MouseEventArgs e)
{
int index = this.listBox.IndexFromPoint(e.Location);
if (index != ListBox.NoMatches)
{
menu.Visible = true;
}
else
{
menu.Visible = false;
}
}
//Create and Initialize the contextMenuStrip component
contextMenuStrip_ListaAulas = new ContextMenuStrip();
//Adding an Item
contextMenuStrip_ListaAulas.Items.Add("Modificar");
//Binding the contextMenuStrip with the ListBox
listBox_Aulas.ContextMenuStrip = contextMenuStrip_ListaAulas;
//The solution below
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
//select the item under the mouse pointer
listBox_Aulas.SelectedIndex = listBox_Aulas.IndexFromPoint(e.Location);
//if the selected index is an item, binding the context MenuStrip with the listBox
if (listBox_Aulas.SelectedIndex != -1)
{
listBox_Aulas.ContextMenuStrip = contextMenuStrip_ListaAulas;
}
//else, untie the contextMenuStrip to the listBox
else
{
listBox_Aulas.ContextMenuStrip = null;
}
}
I do like this, this works great and fast for me.
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
if (Listbox.SelectedItem == null)
e.Cancel = true;
}

Categories