How to get an event when WinForms TreeView items gets cleared - winforms

I am using a standard TreeView in a WinForms application and everything works fine except for one issue:
Parts of the system need to change depending on the selected TreeNode, which works fine using the AfterSelect event.
However, sometimes the TreeView will get cleared completely resulting in an empty selection which does not trigger this event.
At the momemnt I am calling the event callback manually to fix this issue.
This is obviously dangerous, since I will forget to call this function somewhere. Is there a "correct" way to do this?
Thank You!

This is by design. The underlying native Windows controls only generate notifications for things you cannot figure out yourself. The ListBox control for example doesn't have any event that tells you an item got added or removed. Which is because there is no way for the user to add or remove items. Similarly, there's no way for the user to remove the nodes from a tree view.
These kinds of changes requires code that you write. Since it is your code, you cannot not know that these changes happened. If you want an event then you'll have to raise it yourself. Beware that this is harder than it looks, the TreeNodeCollection class doesn't reliably let you generate an event for programmatic changes to the node collection. It doesn't behave like an ObservableCollection. You are definitely better off by not needing this event.

Related

Changing ListView.ShowItemToolTips raises ItemChecked events

Hi when I set ShowItemToolTips of a ListView with checkbox items to true in designer and change it to false in the code, the event ItemChecked is raised. The checked state itself is not changed though. But inside the (also raised) ItemCheck event the old value is not equal to the new value but the new value is the value that was previously visible. It seems like the items are re-inserted or reset in some way.
I tested this on two machines and projects. Why does this happen and how can I avoid it?
I'll explain the "why", a workaround is hard to come by. Some control properties are very impactful and can have odd side-effects when you change them. Like ShowItemToolTips, changing it after the ListView is created requires Winforms to completely destroy the native control and recreate it from scratch. Under the hood, it is a style flag (LVS_EX_INFOTIP) that's specified in the CreateWindowEx() call. The Control.RecreateHandle() method ensures it is effective. You'll see the flicker that this causes if you look closely.
So for a brief moment, the native control exists without yet being initialized with the original checkbox states. Getting a flaky event for that is a bug, but it is the kind that was either never fixed because doing so was too difficult or was just never discovered because nobody ever changes the ShowItemToolTips property after the control was created. It is very uncommon to do so.
In general, this native control re-creation trick has been a significant bug generator in Winforms. And workarounds are hard to come by, they fit either in the "deal with it" or the "don't do it" category. With the latter one strongly recommended in this case.

How to optimize TreeNode name change?

I have a TreeView which holds approximately 100,000 TreeNodes or even more, I have optimized everything related to loading or unloading them on deserialization process but now I'm stuck with an issue I can't overcome.
Its important to mention I decided not to use the LabelEdit default event given by the control since its pretty tricky to make it work as I wanted to, Its widely known that there are a lot of "problems" with this particular event which have pushed many devs to implement their own custom TreeViews.
In my case I am using a ContextMenu which has a Rename option, this brings a textbox right in front of the TreeNode and then I just simply change the TreeNode.Text property to whatever the user input was in the TextBox keydown event, once we trigger this event, the whole GUI freezes for a couple of seconds (4-5), I'm not doing any Depth search over the TreeNodeCollection or anything, I am directly accessing the TreeNode and modifying the property...
So, any thoughts on what could be wrong here? I already tried BeginUpdate / SuspendLayout / or even a custom solution found here How do I suspend painting for a control and its children? and nothing seems to help.
The first thing that comes to mind is that when the text is changed on the node, it must be redrawing the entire treeview.
In this situation, suspendlayout will not help, as the control isn't laying its contents.
I think beginupdate stops the drawing when nodes are being added to the list, but the text changed might bypass this.
Have you considered not using the keydown, and just updating the text once the user has dismissed the textbox? (i.e. done editing). Not ideal, but will limit the performance hit to once, instead of every key stroke?

Custom Undo/Redo in WPF TextBox with proper caret-movement

I have implemented a custom Undo/Redo stack and Im trying to get it to work with the WPF TextBox.
I have turned off the built in Undo-mechanism and hooked up my custom Undo on Ctrl+Z. Everything works fine accept that the caret in the TextBox is always being moved to index 0 on every undo/redo. The question is how to solve this?
I have tried having a custom behaviour on the TextBox which listens to TextChanged and is localizing the last change in the text-string. But this only works unless you start typing the same letter several times in a row. The my method breaks down.
What I ideally want is some kind of behaviour that only makes actual changes to the TextBox.Text-property. As it is now it is updated completely for every Undo, even if its only the last entered letter that is removed. This is of course no suprise since it listens to the Text-property on my PresentationModel which is triggering PropertyChanged on Undo.
But wouldnt it be great if there was some more fine-detailed way of telling exactly what had changed with the property-value, that only one or a couple of letters where inserted/removed in the string value. Then the TextBox could change only that without having to refresh its entire Text-value. Is there any such way of telling the TextBox this allready or could it be possible to make a custom TextBox that behaved in this way? Then it would be possible to pinpoint the exact location for the new caret without having it go straight back to 0 for every propertychange-update!

A better way of managing a forms state?

I am new to Windows programming, as in my previous work I've mostly been involved with web technologies, and mostly in the backend. I have inherited a Winforms application, and one of my biggest nightmares is navigating through the endless states a form can be in.
To give you an example, a form has the state 'New' and 'Edit' depending on whether the user decided to Add or Edit a record. On this form, we have logic. If this texbox has a certain value, then these other textboxes are disabled, etc. This leads to endless chaining of these rules. So, a textbox's TextChanged event will influence another field. It in turn will fire X event that changes the state of other controls. It quickly devolves into a tangled mess that is impossible to maintain.
There has to be a better way... something simple and elegant that solves this problem. Any suggestions?
What I do is to have a single method called FormatControls(). In this method, I implement all the logic such as myTextbox.Enabled = mycheckBox.Checked and so on.
I call this method from my event handlers in the form, such as on checked changed, etc... I also call it when appropriate (ie, form newly loaded with no data, record loaded from database, etc). This has suited me well for many years now, it makes everything less complex.
You are correct, if you do not have a pattern in use it can turn into a too-complex thing.
You can try to use tha Application.Idle event to perform the enable disable logic and insulate this part from the business logic part.
Depending on what controls you have on your form, you might be able to do away with the separate textboxes and add/delete buttons and replace the whole works with a DataGrid.

How do I Determine the Source of the SelectionChangedEvent

I have a question regarding a ComboBox in silverlight and it's selected item.
I would like to determine what triggered the SelectionChangedEvent, was it the user selecting a new item in the list or was it programatically set?
While ideally I would like to solve this using the CommandPattern (I am essentially using a modified RelayCommand (http://joshsmithonwpf.wordpress.com/2008/11/17/emulating-icommandsource-in-silverlight-2/). I am open to other suggestions.
I have also played around with the SelectionChangedEventArgs, which has an OriginalSource property, which upon first inspection may appear to help, however it is null (regardless of the manner in which the item was selected.)
Any ideas, other than setting an internal flag? :)
Thanks
Unfortunately this is a tough thing to determine, since the framework works pretty hard to simply bubble up any changes or user events in this situation as that selection changed event.
If you really need to, you could write a simple ComboBoxWrapper that is effectively the flag you're talking about - so you could derive from ComboBox, try overriding or hiding the CLR setter for SelectedItem, and then maintain state that way.
Any particular scenario in use here? There may be another way to approach a solution.

Resources