I have a tree view control that shows to the user the duplicated images files for two images folders, so when a duplication is found the app set the checkbox beside the tree view node to true.
It works fine but I can't prevent the user from altering the checkbox node values.
So, is it possible to disable the user altering to the checkbox for the tree view nodes, also is there other alternative control for the tree view control I can use instead?
Treeview is probably not what you want anyway.
However if this is Winforms (just a guess)
private void tree_BeforeCheck(object sender, TreeViewCancelEventArgs e)
{
e.Cancel = true;
}
Add pepper and salt to taste
TreeView.BeforeCheck Event
Occurs before the tree node check box is checked.
Furthermore
Setting the TreeNode.Checked property from within the BeforeCheck or
AfterCheck event causes the event to be raised multiple times and can
result in unexpected behavior. For example, you might set the Checked
property in the event handler when you are recursively updating the
child nodes, so that the user does not have to expand and check each
one individually. To prevent the event from being raised multiple
times, add logic to your event handler that only executes your
recursive code if the Action property of the TreeViewEventArgs is not
set to TreeViewAction.Unknown.
Related
I'm working on a form and I need to change the behaviour of some controls when some actions are given by the user. Since there are many controls to handle, meaning buttons, comboboxes, and others, do you know how I can handle methods for all those without handling one by one? Like a loop or something.
Like, for example, for comboboxes I need to overwrite the drawItem event with some code to change their appearance.
I can't find anything on google.
I did it, in the end. I set for the many comboboxes the same event handler/method, selecting all the comboboxes and then setting the handler name in the properties/events tab (in my case, in the DrawItem handler).
Then in the code the method comes by default with (object sender, DrawItemEventArgs e) so I set:
var combo = sender as ComboBox;
and with it I can generally get or set what I need
If I put a listview component into a windows form and add bellow code to it's SelectedIndexChanged event:
MessageBox.Show("Fired!");
foreach (int selectedIndex in listView1.SelectedIndices)
{
listView1.Items[selectedIndex].Selected = false;
listView1.Items[selectedIndex].Focused = false;
}
the message box will be shown 4 times! why is that?
Note: I use the loop to clear the selected items in listview
You should not change the selection in a SelectedIndexChanged event. More generally, you should not change a property inside of a notification that the property has been changed.
If you need to change a property in response to a notification, look to handle the corresponding *Changing event. Rather than being a notification that something has changed (which comes after the fact), it is a notification that something is about to change (which comes before the fact). In the SelectedIndexChanging event, you have a couple of different options to alter the course of events:
You can set the e.Cancel property to true, which will do just as it says. It will cancel the event and prevent the selected index from changing.
You can use the e.NewSelectedIndex property to alter the selection. Just set this property to the index of the item that you want to be selected.
And if you want to clear the selected items in a ListView in response to some other event (e.g., a click on a "Clear Selection" button that is not part of the ListView, or a similar context menu item), you don't need a loop at all. Just clear the control's SelectedItems collection: myListView.SelectedItems.Clear(). Again, you can't do this in response the SelectedIndexChanged event, or you'll have the same problem of triggering a bunch of notifications.
Honestly, though, the code you've written here makes no sense. Why would you want to clear all selected items when the user tries to select an item? If you don't want to allow selection, disable the control by setting its Enabled property to false.
Is there a predefined event for Tab Controls, or maybe something custom I can develop, that will allow me to execute some logic on a control I've removed from that Tab Control's Control Collection, before it ACTUALLY gets removed from the tab control.
Context :
I have a tab control with tab pages. These tab pages load documents related to entries in a reference grid. Each time I select a row in the reference grid, a tab page with the corresponding document loaded gets added to my tab control. The Check column for that row in the grid also gets checked.
I want to be able to close a tab page in my tab control and be able to relate this closed tab page to its corresponding entry in the reference grid so i can uncheck that row.
I've tried browsing through all the possible events for tab control and found nothing suitable. The ControlRemoved event fires only AFTER my tabpage has closed and tab focus has automatically shifted to the next tab.... This is causing my controlremoved logic to fail and enter an infinite loop, trying to close ALL the available tabs instead of just this one, and throwing an invalid index exceptions when it's closed the final one.
You need to ensure that when you uncheck the item in your grid programmatically you do not update the tab control. Otherwise you always will run into an infinite loop causing the unwanted behavior.
You can achieve this by using a boolean flag. In the code-example below I haven't used the "real" event-handlers because I have no IDE at hand to test this at the moment, but rather replaced them by simple methods, so get the idea:
private bool suppressTabUpdate = false;
private void HandleGridCheckedOrUncheckedEvent()
{
if (suppressTabUpdate)
return;
// Insert logic here to create or remove the tab pages as required
}
private void HandleTabPageRemovedEvent()
{
suppressTabUpdate = true;
// Uncheck the item in the grid here
suppressTabUpdate = false;
}
I'm not sure if there's an exact event for you're looking for, but I have an alternative approach to propose.
It sounds to me that some of the UI code is too closely tied together. The grid and the tab control should not be talking to each other directly from the event handlers: that's what's causing the infinite loop (the events are "ping-ponging" back and forth).
Instead, I recommend that both the grid and the tab control be managed by another "component" (just a class, or a few methods in the existing form class) and that this component manage opening/closing tabs and modifying rows in the grid.
For example, when the user selects a row in the grid, don't modify the grid directly at all: instead, call a new method that does whatever needs to happen when a row is selected: check a checkbox, open a tab, etc. When a row no longer needs to be selected, don't change any selections directly: instead, call a new method that does whatever needs to happen when a row is not selected: uncheck a checkbox, close a tab, etc.
If you need a reference to your tab BEFORE it gets removed, there is one simple way to do it. Make CustomTabControl that inherits from TabControl and override its OnControlRemoved event.
If you have this:
public class CTabControl:TabControl
{
protected override void OnControlRemoved(ControlEventArgs e)
{
TabPage tp = e.Control as TabPage; // reference to tab page before it gets removed
base.OnControlRemoved(e);// gets removed here
}
}
I have a C# program that has two elements, a TreeView and a DataGridView and two EventHandelrs. When an item is selected in the TreeView, the DataGridView with a table that displays some information and can be edited by the user. Each item in the TreeView has its own unique table. When the user unfocuses on the DataGridView, the software underlying software model is updated (saving the changes the user made):
aDataGridView_Leave(object sender, EventArgs e)
{
//Update the software model (save the current DataGridView)
}
aTreeView_AfterSelect(object sender, EventArgs e)
{
//Update the table that is shown in aDataGridView
}
My problem is that if the user de-focuses on the DataGridView by selecting a different item in the TreeView I essentially have a race condition between which of these events happens first (even though this is all on one thread). Obviously, in this case I want the DataGridView_Leave Event to fire first or the changes the user made to the table get blown away by a new table being loaded before the changes are saved.
Is there anyway graceful way to enforce what event happens first?
It sounds like you can resolve this by keeping an isDirty bool that is true when there are changes that must be saved. You need to track this yourself, for example in property setters. Check isDirty in aTreeView_AfterSelect and save if necessary, and in aDataGridView_Leave so that you don't save if there are no changes.
This should work, but it sounds like your set up is a little hacky, and it may be counter-intuitive to users that changes are saved when an element loses focus.
What comes immediately to mind is some sort of counter. Assign each event call a number and store the last one processed. That way you can check if it is an old event and ignore it. I haven't seen it used in C# exactly, but plenty of times with AJAX when network delay often causes this situation.
I created a simple windows form application with a treeview, gridview and text box to log events that occur. When you leave the gridview its leave event always fires before the treeviews after select.
Are you saving the data in the gridview asynchronously? I could see if you are saving asynchronously then the treeviews after select could fire before your async method grabbed the data to save from the grid.
If this is the case, push the gridviews data to a stack and pop it off in the method that does the save.
I'm developing a WP7 app and have a listbox with generated buttons all supposed to lead to somewhere specific. I can't figure out how to know which button was pushed at runtime. The list gets generated from a collection of objects with a couple of attributes in each. One of those attributes contain a value that I need to get to be able to know where to send the user.
So my desired process is that the user clicks on an item in the listbox, passing the value of the attribute in the object the button was generated from, to a click handler which sends the user to the right place.
Any suggestions?
I presume your ListBox contains a ItemTemplate which constructs a Button for each of the items bound to your list? if this is the case, within your Click event handler you need to inspect the DataContext of the button that was clicked:
private void Button_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
var myObject = btn.DataContext;
}
As an aside, if you are using this for navigation, a ListBox will not give you very good performance. See the following blog post for an alternative:
http://www.scottlogic.co.uk/blog/colin/2011/04/a-fast-loading-windows-phone-7-navigationlist-control/
Check the sender property of the OnClick event handler for the click handling.
Alternatively you may want to handle the SelectionChanged event of the ListBox and then query the contents of the SelectedItem.