{"id":473,"date":"2011-09-21T17:05:13","date_gmt":"2011-09-21T21:05:13","guid":{"rendered":"http:\/\/blog.bitsofgenius.com\/?p=473"},"modified":"2011-09-21T17:05:13","modified_gmt":"2011-09-21T21:05:13","slug":"the-relations-between-controls-and-idle-states-in-a-windows-form","status":"publish","type":"post","link":"https:\/\/blog.bitsofgenius.com\/?p=473","title":{"rendered":"The relations between controls and idle states in a Windows Form"},"content":{"rendered":"<p>I recently wrote a code conversion project, with a simple windows form to review and adjust the results. \u00a0It had a list view container on the left to enumerate the scripts, and two text boxes on the right for the selected script in the list: the top for the original script, and the bottom for the result of the programmatic conversion. \u00a0The conversion was 100% correct in about 95% of the scripts, so the human element was needed to catch exceptions that the code converter missed and make adjustments.<\/p>\n<p>I added code in the instantiation method to populate the listview control from its database source. \u00a0To save the user unnecessary mouse movement and clicks, I then added code to iterate through each script on the first pass, and convert the script. \u00a0This saved the user a few button presses to convert and save, where no script adjustment was needed&#8211;the vast majority of cases. \u00a0The user, while reviewing scripts, could also reconvert the script with a button press to reset to the original content if any change needed to be reset.<\/p>\n<p>I wrote the load and update methods for the scripts to operate on the currently selected item in the ListView. \u00a0So the code to pre-populate the script conversions used the .selected property to select the script to operate on, then called the Load\/Convert\/Update methods to do the work. \u00a0These db-layer methods used the table \u00a0identity value, stored in the .Tag property of the item. \u00a0 Afterwards, the .selected property was set back to false before the next iteration.<\/p>\n<p>The code worked fine when the user would click on an item in the list view, but the initial population would throw an error saying &#8220;index out of range&#8221;. \u00a0I discovered the problem when I single-stepped the code in the pre-population. \u00a0While the .selected property of the item was set to true, the .SelectedItems and .SelectedIndices properties both still showed a count of \u00a0zero on the next instruction.<\/p>\n<p>I began to recognize that I had a state problem with the ListView object. \u00a0While the property is set to true, these other properties are not updated until the method completes, and the windows form thread bubbles its way out of your method through the various wrappers, and returns to an idle state. \u00a0The problem is similar to the orphaned tray icon problem (see <a href=\"http:\/\/blog.bitsofgenius.com\/?p=79\" target=\"_blank\">Preventing the orphaned system tray icon in a Windows App<\/a>). So to use the ListView as the indexer in my loop, I needed to implement an idle state, and move the work into a timer event. An example of the code is <a href=\"\/CodeView\/WinFormListViewIdleState_Extract_cs.html\" target=\"_blank\">here<\/a>.<\/p>\n<p>One other approach is to write the GetScript() and UpdateScript() methods for the individual scripts to take the identity value as a parameter. \u00a0This would facilitate both a straight index from a loop, and a selected ListViewItem (i.e. passing the stored identity from the .Tag property, etc). \u00a0If you plan on doing bulk actions on your items in the ListView manifest, this is a better approach. \u00a0But if you are inheriting code that just needs to have bulk actions added where previously only actions on selected items occurred, and the code is highly intertwined, this is a way of using the existing windows control&#8217;s selection work when using iteration.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently wrote a code conversion project, with a simple windows form to review and adjust the results. \u00a0It had a list view container on the left to enumerate the scripts, and two text boxes on the right for the selected script in the list: the top for the original script, and the bottom for [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16,23,17],"tags":[],"class_list":["post-473","post","type-post","status-publish","format-standard","hentry","category-dotnettechniques","category-dotnetwinforms","category-tips-and-tricks"],"_links":{"self":[{"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/posts\/473","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=473"}],"version-history":[{"count":0,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/posts\/473\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=473"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=473"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=473"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}