Listbox with Custom Listitem -- Prevent Selection? - c#

I have a listbox that uses a UserControl as the item template. Inside the UserControl, I have an image (an X) that when clicked, sends out event to remove the UserControl(listitem) from the listbox.
Is there a way to prevent the listbox from selecting that item when a user clicks on the image but still allows listitem selection for everything else in the control?

Make sure you mark the event as handled when the user clicks the Image:
private void ImageClicked(object sender, RoutedEventArgs e)
{
//send out event to remove UserControl
//ensure the event doesn't bubble up further to the ListBoxItem
e.Handled = true;
}

Related

ListBox handling in wpf application

i have a list box and a button click event ,when i select an item in the list box and click on the button then the list item should appear in the text box...please help with the code.
private void Get_Click(object sender, RoutedEventArgs e)
{
tb1.Text = listbox1.SelectedItem.ToString();
but it is not working, I'm getting like this but i just need item name to appear on textbox...
System.Windows.Controls.ListBoxItem: item name
Try this:
listbox1.SelectedItem.Content.ToString()
ListBoxes wrap all content in a ListBoxItem, which is what you are seeing. ListBoxItem inherits ContentControl and therefore has a Content property. This contains the object that you want.
http://msdn.microsoft.com/en-us/library/system.windows.controls.listboxitem.aspx

Right click selection in DataGrid

I have a DataGrid created in XAML in a C# project. I've added a context menu to the rows. Basically when the user clicks directly on the cell it should open the relevant item in the current window, which is implemented on the SelectionChanged event.
However if the user right clicks a row it should show the the context menu without selecting the row, so that the user can select an item in the context menu to open the relevant item in a new window. So they can look at both the already selected item and the new item at once, but as the right click selects the row, the user see the newly selected item in the current window and the new window.
How can I stop the right click action to show the context menu from selecting the cell?
For my solution, I have to overwrite the following two event handlers (i.e., PreviewMouseRightButtonDown and PreviewMouseRightButtonUp). Plus, not sure why data-binding for the ItemsSource does not work, so that I have to bind it manually.
private void ResultDataGrid_PreviewMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (sender is DataGrid dg)
{
if (this.DataContext is PipelineStepResultViewModel dataContext
&& dataContext.DatagridMenuItems != null)
{
dg.ContextMenu.ItemsSource = dataContext.DatagridMenuItems;
}
}
e.Handled = true;
}
private void ResultDataGrid_PreviewMouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (sender is DataGrid dg && dg.ContextMenu.ItemsSource != null)
{
ResultDataGrid.ContextMenu.IsOpen = true;
}
e.Handled = true;
}

Select UserControl from FlowLayoutPanel

I have set up UserControls in a FlowPanelLayout with the help in this question:
For Each DataTable Add UserControl to FlowLayoutPanel
I am now trying to implement a click event which allows me to put a border around the UserControl that has been selected. I have done this:
private void User_Load(object sender, EventArgs e)
{
flowlayoutpanelUsers.HorizontalScroll.Visible = false;
// Load and Sort Users DataTable
DataTable datatableUsers = UserMethods.GetUsers().Tables["Users"];
datatableUsers.DefaultView.Sort = "Name";
DataView dataviewUsers = datatableUsers.DefaultView;
// Loop Through Rows and Add UsersGrid to FlowLayoutPael
foreach (DataRowView datarowviewUsers in dataviewUsers)
{
var UsersGrid = new UsersGrid
{
Username = datarowviewUsers["Username"].ToString(),
User = datarowviewUsers["Name"].ToString(),
Admin = datarowviewUsers["Administrator"].ToString(),
};
flowlayoutpanelUsers.Controls.Add(UsersGrid);
UsersGrid.MouseClick += new MouseEventHandler(user_click);
}
}
private UsersGrid selectedUser;
void user_click(object sender, EventArgs e)
{
if (selectedUser != null)
selectedUser.BorderStyle = BorderStyle.None;
selectedUser = (UsersGrid)sender;
selectedUser.BorderStyle = BorderStyle.FixedSingle;
}
My issue is that it only works when I click in a white space in the UserControl but not when the user clicks on the two labels or image. How do I make it work for all child objects too?
Also, how can I then use the selected UserControl to do other things like open a form which shows all the details for that selected user?
I have a few suggestions for you. At the bottom of my response I included code that demonstrates my suggestions.
Suggestion 1: Fixing MouseClick in your UC
When you register the MouseClick event for a UserControl (UC) you're doing so for the UserControl itself, not for any controls that you place on the UserControl such as your Labels, etc. If you click one of these child controls the click won't be 'seen' by the underlying UC.
To fix this register the MouseClick event for all your child controls; you can even register the same MouseClick event handler you have for the UserControl itself.
Suggestion 2: Setting your UC's BorderStyle
I'd move your code for setting the UC's BorderStyle into the UC itself. Create public property IsSelected that's set to true when the UC is selected. In the property's setter update the UC's BorderStyle property depending on the value of the property.
Exposing an IsSelected property for your UC can be handy: you can query a group of these UCs to see which ones are selected rather than trying to track this status outside of the control like through a Form-level variable.
Edit in response to your comment:
Here's an example of how you might query the UCs in a FlowLayoutPanel to see if any are selected and if one is found how you might take some action. In this case the action is to call an EditUser method that takes as parameters values you get from properties in the selected UC:
var selectedUC = flowLayoutPanel.Controls.Cast<UserControl1>().FirstOrDefault(uc => uc.IsSelected);
if (selectedUC != null) {
// Use the properties of the UC found to be selected as parameters is method EditUser.
EditUser(selectedUC.Name, selectedUC.Username, selectedUC.Administrator);
}
Suggestion 3: Managing selection in a group of your UCs
If you want to unselect all UCs in a group except for the one that the user clicks (i.e. selects) you'll need to create an event in your UC that fires when a UC is clicked. The handler for this event explicitly sets IsSelected to false for all UCs in a set (such as in a container type control such as a Form, FlowLayoutPanel, etc.), the MouseClick handler in the UC that was clicked will then set the clicked UC's IsSelected to true.
It's worth considering creating another UserControl type that manages a group of your UCs. This new UserControl can encapsulate the code for the creation and state management of sets of your UC and would faciliate using your UCs in other projects as well as keeping the code of Forms hosting your UCs a bit cleaner.
I figured that rather than include a series of disjointed code snippets for each of my suggestions I'd include what I'm hoping is the minimum amount of code to allow you to reproduce what I'm talking about.
Create a new Visual Studio Winform project and use the following for class Form1:
public partial class Form1 : Form
{
public Form1() {
InitializeComponent();
flowLayoutPanel = new FlowLayoutPanel {
Dock = DockStyle.Fill,
};
this.Controls.Add(flowLayoutPanel);
// Add several sample UCs.
for (int i = 0; i < 10; i++) {
var uc = new UserControl1();
uc.WasClicked += UsersGrid_WasClicked;
flowLayoutPanel.Controls.Add(uc);
}
}
FlowLayoutPanel flowLayoutPanel;
// Event handler for when MouseClick is raised in a UserControl.
void UsersGrid_WasClicked(object sender, EventArgs e) {
// Set IsSelected for all UCs in the FlowLayoutPanel to false.
foreach (Control c in flowLayoutPanel.Controls) {
if (c is UserControl1) {
((UserControl1)c).IsSelected = false;
}
}
}
}
Next add a UserControl to the project. Keep the name UserControl1 and add a couple Labels and a PictureBox. Use this code for class UserControl1:
public partial class UserControl1 : UserControl
{
public UserControl1() {
InitializeComponent();
this.Load += UsersGrid_Load;
}
// Event fires when the MouseClick event fires for the UC or any of its child controls.
public event EventHandler<EventArgs> WasClicked;
private void UsersGrid_Load(object sender, EventArgs e) {
// Register the MouseClick event with the UC's surface.
this.MouseClick += Control_MouseClick;
// Register MouseClick with all child controls.
foreach (Control control in Controls) {
control.MouseClick += Control_MouseClick;
}
}
private void Control_MouseClick(object sender, MouseEventArgs e) {
var wasClicked = WasClicked;
if (wasClicked != null) {
WasClicked(this, EventArgs.Empty);
}
// Select this UC on click.
IsSelected = true;
}
private bool _isSelected;
public bool IsSelected {
get { return _isSelected; }
set {
_isSelected = value;
this.BorderStyle = IsSelected ? BorderStyle.Fixed3D : BorderStyle.None;
}
}
}
I know this is old, but I landed here looking for some pointers on how to do UC selection in a Container.
Jay's answer works well.
Just one update: The UsersGrid_Load method will only engage the top level controls, children of containers will not participate in the WasClicked event.
private void UsersGrid_Load(object sender, EventArgs e) {
// Register the MouseClick event with the UC's surface.
this.MouseClick += Control_MouseClick;
// Register MouseClick with all child controls.
RegisterMouseEvents(Controls);
}
Add recursive method RegisterMouseEvents to the UserControl
private void RegisterMouseEvents(ControlCollection controls)
{
foreach (Control control in controls)
{
// Subscribe the control to the
control.Click += Control_MouseClick;
if (control.HasChildren) RegisterMouseEvents(control.Controls);
}
}
You could possibly try subscribing to the GotFocus event on the UserControl.
Caveat:
Because this event uses bubbling routing, the element that receives focus might be a child element instead of the element where the event handler is actually attached. Check the Source in the event data to determine the actual element that gained focus.
UIElement.GotFocus Event
UPDATE
This question may be appropriate: Click event for .Net (Windows Forms) user control

ListView Item select in winform

I want to select item in a ListView upon clicking. I also want to know what I clicked.
I work on winforms with c#.I also want to know How I can clicking the all row?
Just handle the Click event on the list and use the ListView.SelectedItems property to get what items are selected:
private void listView1_Click(object sender, EventArgs e)
{
var firstSelectedItem = listView1.SelectedItems[0];
}
u can use MouseEventArgs and get the mouse location check if it exists inside the selected item bound , that means the click was made on the selected item .
EDIT :
example :
private void myList_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (myList.SelectedItems.Count >= 1)
{
ListViewItem item = myList.SelectedItems[0];
//here i check for the Mouse pointer location on click if its contained
// in the actual selected item's bounds or not .
// cuz i ran into a problem with the ui once because of that ..
if (item.Bounds.Contains(e.Location))
{
MessageBox.Show("Double Clicked on :"+item.Text);
}
}
}
also if you use xaml for window then you must add MouseUp="listView1_Click" attribute to ListView tag

Show Right Click Options on the Selected List View Record Only - Winforms C#.NET

alt text http://img413.imageshack.us/img413/9417/snapshotapp.jpg
The ContextMenuStrip tied to the ListView control. However, the right click option (edit)
appear where ever i click on the ListView area, this gives me exceptional error because the implementation of edit can only cope with a selected row. I only want it to appear when on a selected row (blue highlighted row). How can i do it?
Reset the ContextMenuStrip property back to (none). Implement the MouseUp event handler and use ListView.HitTest() to find out where it was clicked. For example:
private void listView1_MouseUp(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Right) {
var loc = listView1.HitTest(e.Location);
if (loc.Item != null) contextMenuStrip1.Show(listView1, e.Location);
}
}

Categories

Resources