Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MetadataUpdateHandler to WinForms to repaint all open forms #4831

Merged
merged 1 commit into from
Apr 26, 2021

Conversation

stephentoub
Copy link
Member

@stephentoub stephentoub commented Apr 22, 2021

Proposed changes

.NET hot reload enables changes to be made to an app while it's running. If you were to patch a control's OnPaint routine, for example, the next time that was invoked, it would end up running the newly patched code. However, nothing at the runtime level applying updates automatically triggers Windows Forms to refresh its controls. Instead, a notification mechanism is used to invoke any interested listeners about an update. Windows Forms can have its own listener, which it can use to do anything it would like in response to the update notification. This PR adds such a listener, and uses it to refresh every open form in the application. Future updates to it could be used to do other things, like request that data bound controls rebind, in case the thing they're bound to has changed in some way. (Note that TypeDescriptor.Refresh is invoked via the same mechanism, so any control's listening to TypeDescriptor.Refreshed will automatically be notified as well; this appears to only be the case for PropertyGrid today.)

Customer Impact

Windows Forms apps being used with hot reload automatically refresh in response to a hot reload update.

Regression?

No

Risk

The hot reload work is still in flight and the pattern employed by this loosely-coupled mechanism is still in development; the pattern may evolve, in which case we'll need to update it along with all the other handlers we've added / are adding in .NET 6.

Test methodology

Build the changes locally and patched my installed nightly .NET 6 build. Then use hot reload with several apps, including some that had custom OnPaint overrides, which I could change to see that hot reload edits forced a repaint.

cc: @KlausLoeffelmann, @JeremyKuhne, @pranavkm, @tommcdon, @mikem8361, @LyalinDotCom

Microsoft Reviewers: Open in CodeFlow

@stephentoub stephentoub requested a review from a team as a code owner April 22, 2021 21:25
@ghost ghost assigned stephentoub Apr 22, 2021
@RussKie
Copy link
Member

RussKie commented Apr 22, 2021

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 2 pipeline(s).

Copy link
Member

@JeremyKuhne JeremyKuhne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a reasonable first step for this.

Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested the hot reload against the current nightly and it works!
🚀

@RussKie RussKie merged commit 10b48cc into dotnet:main Apr 26, 2021
@ghost ghost added this to the 6.0 Preview5 milestone Apr 26, 2021
@RussKie
Copy link
Member

RussKie commented Apr 26, 2021

For anyone who wants to experience the magic before the release:

  1. (Optional) Create a new winforms project
  2. Copy WinFormsMetadataUpdateHandler into your project
  3. Add the following launchSettings.json in your Properties folder:
    {
      "profiles": {
        "does-not-matter": {
          "commandName": "Project",
          "hotReloadProfile": "aspnetcore"
        }
      }
  4. Run dotnet watch
  5. Enjoy!

hotreload

@stephentoub stephentoub deleted the hotreloadrepaint branch April 26, 2021 10:49
@KlausLoeffelmann
Copy link
Member

Nice! I bragged I wanted to try it over the weekend, and then our Internet was gone completely. Bummer. So...it'll be soon! 😄

wreuel added a commit to wreuel/winforms that referenced this pull request Apr 28, 2021
commit ca0630b
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Wed Apr 28 23:21:46 2021 +1000

    [main] Update dependencies from dotnet/runtime (dotnet#4852)

    * Update dependencies from https://github.com/dotnet/runtime build 20210427.1

    Microsoft.NETCore.ILAsm , Microsoft.NETCore.ILDAsm , Microsoft.NETCore.Platforms , Microsoft.NETCore.Targets , Microsoft.Win32.Registry , Microsoft.Win32.Registry.AccessControl , Microsoft.Win32.SystemEvents , Microsoft.NETCore.App.Runtime.win-x64 , Microsoft.NET.Sdk.IL , Microsoft.NETCore.App.Ref , System.Diagnostics.EventLog , System.Diagnostics.PerformanceCounter , System.DirectoryServices , System.Drawing.Common , System.IO.FileSystem.AccessControl , System.IO.Packaging , System.IO.Pipes.AccessControl , System.Reflection.MetadataLoadContext , System.Resources.Extensions , System.Security.AccessControl , runtime.win-x64.Microsoft.NETCore.ILAsm , System.Configuration.ConfigurationManager , System.CodeDom , runtime.win-x86.Microsoft.NETCore.ILAsm , System.Security.Cryptography.ProtectedData , System.Security.Cryptography.Pkcs , System.Security.Permissions , System.Security.Cryptography.Xml , System.Security.Principal.Windows , System.Text.Encodings.Web , System.Text.Json , System.Threading.AccessControl , System.Windows.Extensions , VS.Redist.Common.NetCore.SharedFramework.x64.6.0
     From Version 6.0.0-preview.5.21226.1 -> To Version 6.0.0-preview.5.21227.1

    * Update dependencies from https://github.com/dotnet/runtime build 20210427.7

    Microsoft.NETCore.ILAsm , Microsoft.NETCore.ILDAsm , Microsoft.NETCore.Platforms , Microsoft.NETCore.Targets , Microsoft.Win32.Registry , Microsoft.Win32.Registry.AccessControl , Microsoft.Win32.SystemEvents , Microsoft.NETCore.App.Runtime.win-x64 , Microsoft.NET.Sdk.IL , Microsoft.NETCore.App.Ref , System.Diagnostics.EventLog , System.Diagnostics.PerformanceCounter , System.DirectoryServices , System.Drawing.Common , System.IO.FileSystem.AccessControl , System.IO.Packaging , System.IO.Pipes.AccessControl , System.Reflection.MetadataLoadContext , System.Resources.Extensions , System.Security.AccessControl , System.Configuration.ConfigurationManager , runtime.win-x64.Microsoft.NETCore.ILAsm , System.CodeDom , runtime.win-x86.Microsoft.NETCore.ILAsm , System.Security.Cryptography.ProtectedData , System.Security.Cryptography.Pkcs , System.Security.Permissions , System.Security.Cryptography.Xml , System.Security.Principal.Windows , System.Text.Encodings.Web , System.Text.Json , System.Threading.AccessControl , System.Windows.Extensions , VS.Redist.Common.NetCore.SharedFramework.x64.6.0
     From Version 6.0.0-preview.5.21226.1 -> To Version 6.0.0-preview.5.21227.7

    Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>

commit 9321ce6
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Tue Apr 27 20:30:13 2021 +1000

    [main] Update dependencies from dotnet/runtime (dotnet#4848)

commit 10b48cc
Author: Stephen Toub <stoub@microsoft.com>
Date:   Mon Apr 26 03:53:10 2021 -0400

    Add MetadataUpdateHandler to WinForms to repaint all open forms (dotnet#4831)

commit 02ba694
Author: Igor Velikorossov <RussKie@users.noreply.github.com>
Date:   Mon Apr 26 17:34:52 2021 +1000

    VS config (dotnet#4842)

commit 8063e5c
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Sun Apr 25 12:33:24 2021 +0000

    Update dependencies from https://github.com/dotnet/runtime build 20210424.4 (dotnet#4845)

    [main] Update dependencies from dotnet/runtime

commit df5c5ae
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Sat Apr 24 12:56:20 2021 +0000

    Update dependencies from https://github.com/dotnet/runtime build 20210424.1 (dotnet#4844)

    [main] Update dependencies from dotnet/runtime

commit 7020d4b
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Sat Apr 24 12:55:11 2021 +0000

    Update dependencies from https://github.com/dotnet/arcade build 20210422.1 (dotnet#4843)

    [main] Update dependencies from dotnet/arcade

commit 973db87
Author: Igor Velikorossov <RussKie@users.noreply.github.com>
Date:   Sat Apr 24 15:37:13 2021 +1000

    Editor Guidelines config (dotnet#4836)

    https://marketplace.visualstudio.com/items?itemName=PaulHarrington.EditorGuidelines

commit 5ba42a1
Author: Igor Velikorossov <RussKie@users.noreply.github.com>
Date:   Sat Apr 24 15:36:48 2021 +1000

    Script to mark API as shipped (dotnet#4837)

commit 5d05007
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Fri Apr 23 12:43:12 2021 +0000

    Update dependencies from https://github.com/dotnet/runtime build 20210422.13 (dotnet#4840)

    [main] Update dependencies from dotnet/runtime

commit 3e70d7e
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Thu Apr 22 12:51:23 2021 +0000

    Update dependencies from https://github.com/dotnet/runtime build 20210422.1 (dotnet#4827)

    [main] Update dependencies from dotnet/runtime

commit 9613a57
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Thu Apr 22 12:45:22 2021 +0000

    Update dependencies from https://github.com/dotnet/arcade build 20210421.1 (dotnet#4826)

    [main] Update dependencies from dotnet/arcade

commit 90efa2b
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Thu Apr 22 07:59:08 2021 +0000

    Update dependencies from https://github.com/dotnet/runtime build 20210421.1 (dotnet#4823)

    [main] Update dependencies from dotnet/runtime

commit 267a19d
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Wed Apr 21 17:33:13 2021 +0000

    Update dependencies from https://github.com/dotnet/arcade build 20210420.2 (dotnet#4822)

    [main] Update dependencies from dotnet/arcade

commit 76e7021
Author: Sergey Smirnov <sergey.smirnov@akvelon.com>
Date:   Wed Apr 21 11:34:04 2021 +0300

    Fix rectangle of the ListViewGroup (dotnet#4800)

    Fixes dotnet#4778

    ## Proposed changes
    - The issue with the incorrect rectangle is reproduced because the "FragmentRoot" property was not overridden. Added an override for the "FragmentRoot" property.
    - Fixed issue with getting a rectangle for a ListViewGroup. Now, instead of the ListViewGroup index, we use the group ID. Fixed a issue with getting an incorrect ListViewGroup index.
    - Added unit tests. Fixed typos in unit-tests naming

    <!-- We are in TELL-MODE the following section must be completed -->

    ## Customer Impact
    ### Case 1
    **Before fix:**
    ![Issue-4778-case1-before](https://user-images.githubusercontent.com/23376742/114997193-41c42500-9ea8-11eb-9d8d-dd2fed7be588.png)

    **After fix:**
    ![Issue-4778-case1-after](https://user-images.githubusercontent.com/23376742/114997486-8e0f6500-9ea8-11eb-8e14-0aae753335ac.png)

    ### Case 2
    **Before fix:**
    ![Issue-4778-case2-before](https://user-images.githubusercontent.com/23376742/114997915-0bd37080-9ea9-11eb-8203-d76619915de9.png)

    **After fix:**
    ![Issue-4778-case2-after](https://user-images.githubusercontent.com/23376742/114997927-1130bb00-9ea9-11eb-80fe-bee59783f3cf.png)

    ## Regression?

    - Yes (from dotnet#3224)

    ## Risk

    - Minimal

    ## Test methodology <!-- How did you ensure quality? -->
    - CTI team
    - unit tests

    ## Accessibility testing  <!-- Remove this section if PR does not change UI -->
    - Inspector

    ## Test environment(s) <!-- Remove any that don't apply -->
    - Microsoft Windows [Version 10.0.19041.388]
    - .NET Core SDK: 6.0.100-preview.2.21155.3

commit 7ecc0cf
Author: Jeremy Kuhne <jkuhne@microsoft.com>
Date:   Tue Apr 20 19:26:13 2021 -0700

    Don't use Marshal.SizeOf for SCROLLINFO (dotnet#4819)

commit 29cd684
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Wed Apr 21 12:25:18 2021 +1000

    [main] Update dependencies from dotnet/arcade (dotnet#4817)

commit ebe1bee
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Tue Apr 20 12:51:05 2021 +0000

    Update dependencies from https://github.com/dotnet/runtime build 20210419.10 (dotnet#4818)

    [main] Update dependencies from dotnet/runtime

commit 248b732
Merge: 374b00e 03bd984
Author: Jeremy Kuhne <jkuhne@microsoft.com>
Date:   Mon Apr 19 17:03:10 2021 -0700

    Merge pull request dotnet#4814 from JeremyKuhne/newgetcontext

    Use new GetContext overloads

commit 03bd984
Author: Jeremy Kuhne <jkuhne@microsoft.com>
Date:   Mon Apr 19 16:00:36 2021 -0700

    Use new GetContext overloads

    Use new Graphics.GetContext overloads that minimize allocations and remove warning suppression.

commit 374b00e
Merge: 3e372a1 66df1fa
Author: Jeremy Kuhne <jkuhne@microsoft.com>
Date:   Mon Apr 19 14:58:51 2021 -0700

    Merge pull request dotnet#4802 from dotnet/darc-main-81e048c2-036b-4ff2-9f48-45ff7c71cc72

    [main] Update dependencies from dotnet/runtime

commit 3e372a1
Merge: 7098999 a0ccc42
Author: Jeremy Kuhne <jkuhne@microsoft.com>
Date:   Mon Apr 19 13:41:58 2021 -0700

    Merge pull request dotnet#4811 from JeremyKuhne/syslib16

    Disable SYSLIB0016 warning

commit a0ccc42
Author: Jeremy Kuhne <jkuhne@microsoft.com>
Date:   Mon Apr 19 12:57:21 2021 -0700

    Disable SYSLIB0016 warning

    This is a new obsoletion in System.Drawing. Disabling so we can consume the new build. Will follow this change with another that consumes the newer API.

commit 66df1fa
Author: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Date:   Sun Apr 18 12:07:45 2021 +0000

    Update dependencies from https://github.com/dotnet/runtime build 20210418.1

    Microsoft.NETCore.Platforms , Microsoft.NETCore.Targets , Microsoft.Win32.Registry , Microsoft.Win32.Registry.AccessControl , Microsoft.Win32.SystemEvents , Microsoft.NETCore.ILDAsm , Microsoft.NETCore.ILAsm , Microsoft.NETCore.App.Runtime.win-x64 , Microsoft.NET.Sdk.IL , Microsoft.NETCore.App.Ref , System.Diagnostics.PerformanceCounter , System.DirectoryServices , System.Drawing.Common , System.IO.FileSystem.AccessControl , System.IO.Packaging , System.IO.Pipes.AccessControl , System.Diagnostics.EventLog , System.Reflection.MetadataLoadContext , System.Resources.Extensions , System.Security.AccessControl , System.Security.Cryptography.Cng , runtime.win-x64.Microsoft.NETCore.ILAsm , runtime.win-x86.Microsoft.NETCore.ILAsm , System.CodeDom , System.Configuration.ConfigurationManager , System.Security.Cryptography.ProtectedData , System.Security.Cryptography.Pkcs , System.Security.Permissions , System.Security.Cryptography.Xml , System.Security.Principal.Windows , System.Text.Encodings.Web , System.Text.Json , System.Threading.AccessControl , System.Windows.Extensions , VS.Redist.Common.NetCore.SharedFramework.x64.6.0
     From Version 6.0.0-preview.4.21214.9 -> To Version 6.0.0-preview.5.21218.1

commit 7098999
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Sat Apr 17 12:39:44 2021 +0000

    Update dependencies from https://github.com/dotnet/arcade build 20210416.2 (dotnet#4806)

    [main] Update dependencies from dotnet/arcade

commit b76c1b3
Author: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Date:   Sat Apr 17 12:10:32 2021 +0000

    Update dependencies from https://github.com/dotnet/runtime build 20210417.1

    Microsoft.NETCore.Platforms , Microsoft.NETCore.Targets , Microsoft.Win32.Registry , Microsoft.Win32.Registry.AccessControl , Microsoft.Win32.SystemEvents , Microsoft.NETCore.ILDAsm , Microsoft.NETCore.ILAsm , Microsoft.NETCore.App.Runtime.win-x64 , Microsoft.NET.Sdk.IL , Microsoft.NETCore.App.Ref , System.Diagnostics.PerformanceCounter , System.DirectoryServices , System.Drawing.Common , System.IO.FileSystem.AccessControl , System.IO.Packaging , System.IO.Pipes.AccessControl , System.Diagnostics.EventLog , System.Reflection.MetadataLoadContext , System.Resources.Extensions , System.Security.AccessControl , System.Security.Cryptography.Cng , runtime.win-x64.Microsoft.NETCore.ILAsm , runtime.win-x86.Microsoft.NETCore.ILAsm , System.CodeDom , System.Configuration.ConfigurationManager , System.Security.Cryptography.ProtectedData , System.Security.Cryptography.Pkcs , System.Security.Permissions , System.Security.Cryptography.Xml , System.Security.Principal.Windows , System.Text.Encodings.Web , System.Text.Json , System.Threading.AccessControl , System.Windows.Extensions , VS.Redist.Common.NetCore.SharedFramework.x64.6.0
     From Version 6.0.0-preview.4.21214.9 -> To Version 6.0.0-preview.5.21217.1

commit b53c2eb
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Fri Apr 16 12:40:23 2021 +0000

    Update dependencies from https://github.com/dotnet/arcade build 20210415.5 (dotnet#4801)

    [main] Update dependencies from dotnet/arcade

commit b1f43ab
Author: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Date:   Fri Apr 16 12:10:49 2021 +0000

    Update dependencies from https://github.com/dotnet/runtime build 20210415.13

    Microsoft.Win32.Registry , Microsoft.Win32.Registry.AccessControl , Microsoft.Win32.SystemEvents , Microsoft.NETCore.Targets , Microsoft.NETCore.Platforms , Microsoft.NETCore.ILAsm , Microsoft.NETCore.App.Runtime.win-x64 , Microsoft.NETCore.ILDAsm , Microsoft.NET.Sdk.IL , Microsoft.NETCore.App.Ref , System.Diagnostics.EventLog , System.Diagnostics.PerformanceCounter , System.DirectoryServices , System.Drawing.Common , System.IO.FileSystem.AccessControl , System.IO.Packaging , System.IO.Pipes.AccessControl , System.Reflection.MetadataLoadContext , System.Resources.Extensions , System.Security.AccessControl , System.Configuration.ConfigurationManager , runtime.win-x64.Microsoft.NETCore.ILAsm , runtime.win-x86.Microsoft.NETCore.ILAsm , System.CodeDom , System.Security.Cryptography.Cng , System.Security.Cryptography.ProtectedData , System.Security.Cryptography.Pkcs , System.Security.Cryptography.Xml , System.Security.Permissions , System.Security.Principal.Windows , System.Text.Encodings.Web , System.Text.Json , System.Threading.AccessControl , VS.Redist.Common.NetCore.SharedFramework.x64.6.0 , System.Windows.Extensions
     From Version 6.0.0-preview.4.21214.9 -> To Version 6.0.0-preview.4.21215.13

commit c9287e9
Author: Devendar Reddy Adulla <dreddy@microsoft.com>
Date:   Thu Apr 15 19:12:24 2021 -0700

    Branding change for Winforms 6.0 preview 5 (dotnet#4799)

commit ecfb941
Author: Devendar Reddy Adulla <dreddy@microsoft.com>
Date:   Thu Apr 15 18:12:20 2021 -0700

    SHipped APIs for Preview4 (dotnet#4798)

commit f379253
Author: Sergey Smirnov <sergey.smirnov@akvelon.com>
Date:   Fri Apr 16 03:20:04 2021 +0300

    Fix Empty ListViewGroups are displayed in the Inspect tree dotnet#4779 (dotnet#4789)

    In this issue, we have two problems with invisible ListViewGroups and invisible ListViewItems.

    An ListViewItem is considered invisible when it is in a ListViewGroup but not added to the ListView. In this case, the ListViewGroup contains data about it, but the ListViewItem is not displayed in the list. To solve this problem, the "GetVisibleItems" method was added, which returns a list of only displayed ListViewItems, in which the property "ListView" is not empty. Now, when receiving data about the ListViewItems of a ListViewGroup, we use this method and not "Items" property of the ListViewGroup.

    The second issue, if the ListViewGroup is empty or contains invisible ListViewItems (case above), then this ListViewGroup is also not displayed in the ListView. This issue was solved in the same way as the issue above, by adding the "GetVisibleGroups" method that returns a list of only the displayed ListViewGroups.

    Added unit tests for ListViewAccessibleObject, ListViewGroupAccessibleObject, ListViewItemAccessibleObject

commit 970b01a
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Thu Apr 15 12:51:35 2021 +0000

    Update dependencies from https://github.com/dotnet/runtime build 20210414.9 (dotnet#4795)

    [main] Update dependencies from dotnet/runtime

commit 2c9de98
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Thu Apr 15 12:45:45 2021 +0000

    Update dependencies from https://github.com/dotnet/arcade build 20210414.5 (dotnet#4794)

    [main] Update dependencies from dotnet/arcade

commit f188aa6
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Wed Apr 14 12:49:07 2021 +0000

    Update dependencies from https://github.com/dotnet/runtime build 20210413.3 (dotnet#4792)

    [main] Update dependencies from dotnet/runtime

commit 7e785d0
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Wed Apr 14 00:12:18 2021 +0000

    Update dependencies from https://github.com/dotnet/arcade build 20210412.6 (dotnet#4783)

    [main] Update dependencies from dotnet/arcade

commit 7916a2c
Author: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date:   Tue Apr 13 12:46:42 2021 +0000

    Update dependencies from https://github.com/dotnet/runtime build 20210413.1 (dotnet#4784)

    [main] Update dependencies from dotnet/runtime
@ghost ghost locked as resolved and limited conversation to collaborators Jan 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants