{"id":993,"date":"2009-11-12T19:39:00","date_gmt":"2009-11-12T19:39:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/2009\/11\/12\/spot-the-bug-is-it-in-vb-or-xaml-jonathan-aneja\/"},"modified":"2024-07-05T12:42:22","modified_gmt":"2024-07-05T19:42:22","slug":"spot-the-bug-is-it-in-vb-or-xaml-jonathan-aneja","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/spot-the-bug-is-it-in-vb-or-xaml-jonathan-aneja\/","title":{"rendered":"Spot the Bug! &#8211; Is it in VB or XAML? (Jonathan Aneja)"},"content":{"rendered":"<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">What\u2019s wrong with the following WPF code?<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\"><\/font>&nbsp;<\/p>\n<p class=\"MsoNormal\"><span>Class<\/span><span> Window1 <\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp; <\/span>Sub<\/span><span> OK_Click(sender <span>As<\/span> <span>Object<\/span>, e <span>As<\/span> RoutedEventArgs) <span>Handles <\/span>OK.Click<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MsgBox(<span>&#8220;Button Clicked&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp; <\/span><span>End<\/span> <span>Sub<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span>End<\/span><span> <span>Class<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span>&lt;<\/span><span>Window<\/span><span> x<\/span><span>:<\/span><span>Class<\/span><span>=&#8221;Window1&#8243;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp; <\/span><span><span>&nbsp;<\/span>xmlns<\/span><span>=&#8221;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\/presentation&#8221;<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp; <\/span><span><span>&nbsp;<\/span>xmlns<\/span><span>:<\/span><span>x<\/span><span>=&#8221;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml&#8221;<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp; <\/span><span><span>&nbsp;<\/span>Title<\/span><span>=&#8221;Window1&#8243;<\/span><span> Height<\/span><span>=&#8221;300&#8243;<\/span><span> Width<\/span><span>=&#8221;300&#8243;&gt;<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><\/span><span>&lt;<\/span><span>Grid<\/span><span>&gt;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><span>&lt;<\/span><span>Button<\/span><span> Name<\/span><span>=&#8221;OK&#8221;<\/span><span> Click<\/span><span>=&#8221;OK_Click&#8221;&gt;<\/span><span>OK<\/span><span>&lt;\/<\/span><span>Button<\/span><span>&gt;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><\/span><span>&lt;\/<\/span><span>Grid<\/span><span>&gt;<\/span><\/p>\n<p class=\"MsoNormal\"><span>&lt;\/<\/span><span>Window<\/span><span>&gt;<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\" face=\"Calibri\">.<\/font><\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\" face=\"Calibri\">.<\/font><\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\" face=\"Calibri\">.<\/font><\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\" face=\"Calibri\">.<\/font><\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\" face=\"Calibri\">.<\/font><\/p>\n<p class=\"MsoNoSpacing\"><b><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/b><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\"><b>Answer: <\/b>The message box will be displayed twice!<span>&nbsp; <\/span>To understand why, open up the project in Reflector, and in the System_Windows_Mark_IComponentConnector_Connect method you\u2019ll see these two lines:<\/font><\/font><\/p>\n<pre><font face=\"Courier New\"><span><span>&nbsp;&nbsp;&nbsp; <\/span>Me<\/span>.<\/font><a title=\"Property WpfApplication1.Window1.OK As Button\" href=\"http:\/\/www.aisto.com\/roeder\/dotnet\/Default.aspx?Target=code:\/\/WpfDoubleEvent:1.0.0.0\/WpfApplication1.Window1\/property:OK:System.Windows.Controls.Button\"><font color=\"#0000ff\" face=\"Courier New\">OK<\/font><\/a><font face=\"Courier New\"> = <span>DirectCast<\/span>(target, <\/font><a title=\"System.Windows.Controls.Button\" href=\"http:\/\/www.aisto.com\/roeder\/dotnet\/Default.aspx?Target=code:\/\/PresentationFramework:3.0.0.0:31bf3856ad364e35\/System.Windows.Controls.Button\"><font color=\"#0000ff\" face=\"Courier New\">Button<\/font><\/a><font face=\"Courier New\">)<\/font><\/pre>\n<pre><font face=\"Courier New\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>AddHandler Me<\/span>.<\/font><a title=\"Property WpfApplication1.Window1.OK As Button\" href=\"http:\/\/www.aisto.com\/roeder\/dotnet\/Default.aspx?Target=code:\/\/WpfDoubleEvent:1.0.0.0\/WpfApplication1.Window1\/property:OK:System.Windows.Controls.Button\"><font color=\"#0000ff\" face=\"Courier New\">OK<\/font><\/a><font face=\"Courier New\">.<\/font><a title=\"Event System.Windows.Controls.Primitives.ButtonBase.Click As RoutedEventHandler\" href=\"http:\/\/www.aisto.com\/roeder\/dotnet\/Default.aspx?Target=code:\/\/PresentationFramework:3.0.0.0:31bf3856ad364e35\/System.Windows.Controls.Primitives.ButtonBase\/event:Click:System.Windows.RoutedEventHandler\"><font color=\"#0000ff\" face=\"Courier New\">Click<\/font><\/a><font face=\"Courier New\">, <span>New <\/span><\/font><a title=\"System.Windows.RoutedEventHandler\" href=\"http:\/\/www.aisto.com\/roeder\/dotnet\/Default.aspx?Target=code:\/\/PresentationCore:3.0.0.0:31bf3856ad364e35\/System.Windows.RoutedEventHandler\"><font color=\"#0000ff\" face=\"Courier New\">RoutedEventHandler<\/font><\/a><font face=\"Courier New\">(<span>AddressOf Me<\/span>.<\/font><a title=\"WpfApplication1.Window1.OK_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)\" href=\"http:\/\/www.aisto.com\/roeder\/dotnet\/Default.aspx?Target=code:\/\/WpfDoubleEvent:1.0.0.0\/WpfApplication1.Window1\/OK_Click(Object,System.Windows.RoutedEventArgs)\"><font color=\"#0000ff\" face=\"Courier New\">OK_Click<\/font><\/a><font face=\"Courier New\">)<\/font><\/pre>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">Ok so we\u2019re adding one handler here, but click the link to navigate to \u201cOK\u201d.<span>&nbsp; <\/span>You\u2019ll see this is actually a <i>property<\/i> of type Button (that\u2019s what the compiler does for WithEvents\/Handles \u2013 the full story of how WithEvents works is its own blog entry\u2026).<span>&nbsp; <\/span>In the Setter you\u2019ll see this code:<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<pre><font face=\"Courier New\"><span><span>&nbsp;&nbsp;&nbsp; <\/span>If<\/span> (<span>Not<\/span> <span>Me<\/span>.<\/font><a title=\"_OK As Button\" href=\"http:\/\/www.aisto.com\/roeder\/dotnet\/Default.aspx?Target=code:\/\/WpfDoubleEvent:1.0.0.0\/WpfApplication1.Window1\/_OK:System.Windows.Controls.Button\"><font color=\"#0000ff\" face=\"Courier New\">_OK<\/font><\/a><font face=\"Courier New\"> <span>Is<\/span> <span>Nothing<\/span>) <span>Then<\/span><\/font><\/pre>\n<pre><font face=\"Courier New\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>AddHandler Me<\/span>.<\/font><a title=\"_OK As Button\" href=\"http:\/\/www.aisto.com\/roeder\/dotnet\/Default.aspx?Target=code:\/\/WpfDoubleEvent:1.0.0.0\/WpfApplication1.Window1\/_OK:System.Windows.Controls.Button\"><font color=\"#0000ff\" face=\"Courier New\">_OK<\/font><\/a><font face=\"Courier New\">.<\/font><a title=\"Event System.Windows.Controls.Primitives.ButtonBase.Click As RoutedEventHandler\" href=\"http:\/\/www.aisto.com\/roeder\/dotnet\/Default.aspx?Target=code:\/\/PresentationFramework:3.0.0.0:31bf3856ad364e35\/System.Windows.Controls.Primitives.ButtonBase\/event:Click:System.Windows.RoutedEventHandler\"><font color=\"#0000ff\" face=\"Courier New\">Click<\/font><\/a><font face=\"Courier New\">, handler<\/font><\/pre>\n<pre><font face=\"Courier New\"> <span>&nbsp;&nbsp;&nbsp;<\/span><span>End If<\/span><\/font><\/pre>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">So now we can clearly see there\u2019s two AddHandler calls and thus the event gets handled multiple times by the same method (which is perfectly legal).<span>&nbsp; <\/span>One of them came from <\/font><span>Handles <\/span><span>OKButton.Click<\/span><font size=\"3\" face=\"Calibri\">, and the other came from <\/font><span>Click<\/span><span>=&#8221;OK_Click&#8221;<\/span><font size=\"3\"><font face=\"Calibri\">.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\"><i>The key thing to realize is that if you wire up the eventhandler in XAML, don\u2019t wire it up in code using Handles (and vice-versa).<\/i><span>&nbsp; <\/span>Thankfully in this scenario it\u2019s obvious that there\u2019s a problem because there\u2019s a message box, but if the eventhandler was doing something more subtle (such as incrementing a counter or modifying some other state), this can lead to hard-to-diagnose bugs.<span><\/span><\/font><\/font><\/p>\n","protected":false},"excerpt":{"rendered":"<p>What\u2019s wrong with the following WPF code? &nbsp; Class Window1 &nbsp; &nbsp; Sub OK_Click(sender As Object, e As RoutedEventArgs) Handles OK.Click &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MsgBox(&#8220;Button Clicked&#8221;) &nbsp; End Sub &nbsp; End Class &nbsp; &lt;Window x:Class=&#8221;Window1&#8243; &nbsp;&nbsp; &nbsp;xmlns=&#8221;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\/presentation&#8221; &nbsp;&nbsp; &nbsp;xmlns:x=&#8221;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml&#8221; &nbsp;&nbsp; &nbsp;Title=&#8221;Window1&#8243; Height=&#8221;300&#8243; Width=&#8221;300&#8243;&gt; &nbsp;&nbsp;&nbsp; &lt;Grid&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Button Name=&#8221;OK&#8221; Click=&#8221;OK_Click&#8221;&gt;OK&lt;\/Button&gt; &nbsp;&nbsp;&nbsp; &lt;\/Grid&gt; &lt;\/Window&gt; &nbsp; . &nbsp; . &nbsp; [&hellip;]<\/p>\n","protected":false},"author":260,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[195],"tags":[83,143,165,166,167],"class_list":["post-993","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-visual-basic","tag-jonathan-aneja","tag-spot-the-bug","tag-vb2005","tag-vb2008","tag-vb2010"],"acf":[],"blog_post_summary":"<p>What\u2019s wrong with the following WPF code? &nbsp; Class Window1 &nbsp; &nbsp; Sub OK_Click(sender As Object, e As RoutedEventArgs) Handles OK.Click &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MsgBox(&#8220;Button Clicked&#8221;) &nbsp; End Sub &nbsp; End Class &nbsp; &lt;Window x:Class=&#8221;Window1&#8243; &nbsp;&nbsp; &nbsp;xmlns=&#8221;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\/presentation&#8221; &nbsp;&nbsp; &nbsp;xmlns:x=&#8221;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml&#8221; &nbsp;&nbsp; &nbsp;Title=&#8221;Window1&#8243; Height=&#8221;300&#8243; Width=&#8221;300&#8243;&gt; &nbsp;&nbsp;&nbsp; &lt;Grid&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Button Name=&#8221;OK&#8221; Click=&#8221;OK_Click&#8221;&gt;OK&lt;\/Button&gt; &nbsp;&nbsp;&nbsp; &lt;\/Grid&gt; &lt;\/Window&gt; &nbsp; . &nbsp; . &nbsp; [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/993","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/260"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=993"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/993\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=993"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=993"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=993"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}