locked
IE9 - System.ArgumentException at browser history navigation in Silverlight 4 navigation application with custom attached DependencyProperty for Hyperlinkbutton RRS feed

  • Question

  • Hello

    I have a strange problem with the IE9 in a Silverlight navigation app. The SL app consists of a frame in which to display the 4 pages. If I call the pages in loose order one at a time by clicking on the hyperlinkbutton in the SL app and then use the browser history to only move backwards, everything works fine in generell.

    But iff I then navigate forward in the browser history, the code ends up running code in the NavigationFailed event and throws a System.ArgumentException. An evaluation of e.Uri when debugging indicates that the value of the URI is empty.

    Also, a System.ArgumentException is thrown if navigates through the pages of the pages in the following order:

    Starting point: Home Page1 (Frame.Navigate(...) in the constructor called by MainPage.xaml.vb)

    Action: Click on Hyperlinkbutton P2-> navigate to Page2

    Action: Click on the back button in the browser-> navigation to Page1

    Action: Click on the forward button in the browser-> navigate to Page2

    Action: Click on the back button in the browser-> NavigationFalied() with system.ArgumentException (empty URI)



    The historical data displayed in the browser by right clicking on the forward or backward button correspond to the historical sequence of page views.

    The JournalOwnership property of the frame has the value auto.

    I recently installed IE9 (x32). Previously I was using the IE8 (x 32). In the IE8 (x 32) this problem does not occure, with the same code.

    Looking for the source of the error, I have checked how other navigation applications behave, which I have previously developed. The result is that there this problem doesn't appear.

    I therefore assume that the error source is in the special project in which this error is thrown. That is why I'll show the essential source below.

    A few notes on the project's source code:

    Task of the project is to test the use of a custom attached DependencyProperty (IsKeepFocusVisualProperty), which I have created. This attached DependencyProperty has the task to manage two VisualStates (IsSelected and IsNotSelected) of an additional VisualStateGroup (KeepFocusVisualStates) from the customized HyperlinkButton template. These VisualStates simulate the focus for a clicked Hyperlinkbutton visually, even when the Hyperlinkbutton has no longer the focus. Thus, the Hyperlinkbutton will receive a visual indicator for the currently displayed page.

    The attached DependencyProperty IsKeepFocusVisualProperty is defined in the class HyperlinkButtonExtension.vb. It is used in the routine ControlIsSelectedState() in MainPage.xaml.vb. ControlIsSelectedState() hangs on the Navigated() event of the frame. In the event handling the value of IsKeepFocusVisualProperty is set dynamically for each of the Hyperlinkbutton. It is set to True to the HyperlinkButton, which was clicked, and is set to False for all other Hyperlinkbuttons. In the PropertyChangedCallBack of IsKeepFocusVisualProperty (OnIsKeepFocusVisualPropertyChanged) the VisualState IsSelected or the VisualState IsNotSelected is activated then, depending on whether the new value of IsKeepFocusVisualProperty is True or False.

    As I said, it works perfectly in the IE8 (x32). Since I installed the IE9 yesterday morning, a System.ArgumentException is thrown into the described effects of flow when using the browser history navigation.

    This is the main source code of the project (the rest of the source code is for the 4 Pages):

    MainPage.xaml:

     

    <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:silverlaw="clr-namespace:KeepHyperlinkButtonFocusVisually.SilverLaw"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
     mc:Ignorable="d"
     x:Class="KeepHyperlinkButtonFocusVisually.MainPage"
     Width="560"
     Height="600">
    
     <Grid x:Name="LayoutRoot"
     Background="#FF282828">
     <Grid.RowDefinitions>
     <RowDefinition Height="80" />
     <RowDefinition />
     </Grid.RowDefinitions>
     <StackPanel x:Name="spContainer"
     HorizontalAlignment="Center"
     Orientation="Horizontal"
     VerticalAlignment="Bottom">
     <HyperlinkButton x:Name="hb1"
     Content="Home"
     VerticalAlignment="Top"
     Style="{StaticResource KeepFocusVisualHyperlinkButtonStyle}"
     d:LayoutOverrides="Width"
     Tag="home"
     Margin="0,0,26,0" />
     <HyperlinkButton x:Name="hb2"
     Content="Labs"
     Tag="labs"
     Margin="0,0,26,0" 
     Style="{StaticResource KeepFocusVisualHyperlinkButtonStyle}" />
     <HyperlinkButton x:Name="hb3"
     Content="Solutions"
     Tag="solutions"
     Margin="0,0,26,0" 
     Style="{StaticResource KeepFocusVisualHyperlinkButtonStyle}" />
     <HyperlinkButton x:Name="hb4"
     Content="About"
     Tag="About"
     Margin="0,0,26,0" 
     Style="{StaticResource KeepFocusVisualHyperlinkButtonStyle}" />
     </StackPanel>
     <Button x:Name="b1"
     Content="Button"
     HorizontalAlignment="Left"
     VerticalAlignment="Top"
     Width="75" />
     	<sdk:Frame x:Name="contentFrame" 
     Grid.Row="1" 
     Margin="20,20,20,40"/>
     </Grid>
    </UserControl>
    

     

    SilverLawHyperlinkButtonStyle.xaml (ein ResourceDictionary):

     

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:KeepHyperlinkButtonFocusVisually_SilverLaw="clr-namespace:KeepHyperlinkButtonFocusVisually.SilverLaw"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d">
     <!-- Hier werden Einträge für Ressourcenverzeichnisse definiert. -->
     <Style x:Key="KeepFocusVisualHyperlinkButtonStyle"
     TargetType="HyperlinkButton">
     <Setter Property="Foreground"
     Value="#FF73A9D8" />
     <Setter Property="Padding"
     Value="2,0,2,0" />
     <Setter Property="Cursor"
     Value="Hand" />
     <Setter Property="HorizontalContentAlignment"
     Value="Left" />
     <Setter Property="VerticalContentAlignment"
     Value="Top" />
     <Setter Property="Background"
     Value="Transparent" />
     <Setter Property="Template">
     <Setter.Value>
     <ControlTemplate TargetType="HyperlinkButton">
     <Grid Background="{TemplateBinding Background}"
     Cursor="{TemplateBinding Cursor}">
     <VisualStateManager.VisualStateGroups>
     <VisualStateGroup x:Name="CommonStates">
     <VisualState x:Name="Normal" />
     <VisualState x:Name="MouseOver">
     <Storyboard>
     <DoubleAnimation Duration="0"
      To="1"
      Storyboard.TargetProperty="(UIElement.Opacity)"
      Storyboard.TargetName="MouseOverVisual"
      d:IsOptimized="True" />
     </Storyboard>
     </VisualState>
     <VisualState x:Name="Pressed" />
     <VisualState x:Name="Disabled">
     <Storyboard>
     <ObjectAnimationUsingKeyFrames Duration="0"
      Storyboard.TargetProperty="Visibility"
      Storyboard.TargetName="DisabledOverlay">
     <DiscreteObjectKeyFrame KeyTime="0">
     <DiscreteObjectKeyFrame.Value>
     <Visibility>Visible</Visibility>
     </DiscreteObjectKeyFrame.Value>
     </DiscreteObjectKeyFrame>
     </ObjectAnimationUsingKeyFrames>
     </Storyboard>
     </VisualState>
     </VisualStateGroup>
     <VisualStateGroup x:Name="FocusStates">
     <VisualState x:Name="Focused">
     <Storyboard>
     <DoubleAnimation Duration="0"
      To="1"
      Storyboard.TargetProperty="(UIElement.Opacity)"
      Storyboard.TargetName="FocusVisual"
      d:IsOptimized="True" />
     </Storyboard>
     </VisualState>
     <VisualState x:Name="Unfocused" />
     </VisualStateGroup>
     <!--Additional VisualStateGroup which holds the two extra VisualStates 
     to indicate the IsKeepFocusVisualProperty visually --> 
     <VisualStateGroup x:Name="KeepFocusVisualStates">
     <VisualState x:Name="IsNotSelected" />
     <VisualState x:Name="IsSelected">
     <Storyboard>
     <DoubleAnimation Duration="0"
      To="1"
      Storyboard.TargetProperty="(UIElement.Opacity)"
      Storyboard.TargetName="KeepFocusVisual"
      d:IsOptimized="True" />
     </Storyboard>
     </VisualState>
     </VisualStateGroup>
     </VisualStateManager.VisualStateGroups>
     <TextBlock x:Name="DisabledOverlay"
     Foreground="#FFAAAAAA"
     HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
     Margin="{TemplateBinding Padding}"
     Text="{TemplateBinding Content}"
     Visibility="Collapsed"
     VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
     Canvas.ZIndex="1" />
     <ContentPresenter x:Name="contentPresenter"
     ContentTemplate="{TemplateBinding ContentTemplate}"
     Content="{TemplateBinding Content}"
     HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
     Margin="{TemplateBinding Padding}"
     VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
     <!--This element is responsible for the visual focus.-->
     <TextBlock x:Name="FocusVisual"
     HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
     TextWrapping="Wrap"
     Text="{TemplateBinding Content}"
     VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
     Margin="{TemplateBinding Padding}"
     Foreground="#FFD8D073"
     Opacity="0" />
     <!--This element is responsible for the visual effect on mouse over.-->
     <TextBlock x:Name="MouseOverVisual"
     Margin="{TemplateBinding Padding}"
     TextWrapping="Wrap"
     Text="{TemplateBinding Content}"
     d:LayoutOverrides="Width, Height"
     HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
     VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
     Canvas.ZIndex="1"
     Foreground="#99F3F3F2"
     Opacity="0" />
     <!--This element is responsible for keeping the focus visually.
     This element is mandatory-->
     <TextBlock x:Name="KeepFocusVisual"
     Margin="{TemplateBinding Padding}"
     TextWrapping="Wrap"
     Text="{TemplateBinding Content}"
     d:LayoutOverrides="Width, Height"
     HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
     VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
     Opacity="0"
     Foreground="#FFD8D073" />
     </Grid>
     </ControlTemplate>
     </Setter.Value>
     </Setter>
     </Style>
    </ResourceDictionary>
    

     

    HyperlinkButtonExtension.vb:

     

    Namespace SilverLaw
    
    
     Public Class HyperlinkButtonExtension
    
    
     Public Shared Function GetIsKeepFocusVisual(ByVal hb As HyperlinkButton) As Boolean
    
     If hb Is Nothing Then
    
     Throw New ArgumentNullException("hyperlinkButton")
    
     End If
    
     Return CStr(hb.GetValue(IsKeepFocusVisualProperty))
    
     End Function
    
    
     Public Shared Sub SetIsKeepFocusVisual(ByVal hb As HyperlinkButton, ByVal value As Boolean)
    
     If hb Is Nothing Then
    
     Throw New ArgumentNullException("hyperlinkButton")
    
     End If
    
     hb.SetValue(IsKeepFocusVisualProperty, value)
    
     End Sub
    
    
     Public Shared ReadOnly IsKeepFocusVisualProperty As DependencyProperty =
     DependencyProperty.RegisterAttached("IsKeepFocusVisual",
      GetType(Boolean),
      GetType(HyperlinkButton),
      New PropertyMetadata(New PropertyChangedCallback(AddressOf OnIsKeepFocusVisualPropertyChanged)))
    
    
     Shared Sub OnIsKeepFocusVisualPropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
    
     Dim hb As HyperlinkButton = CType(d, HyperlinkButton)
    
     If hb Is Nothing Then
    
     Throw New NotSupportedException("IsKeepFocusVisual property is only valid for a HyperlinkButton instance.")
    
     End If
    
     Dim newValue As Boolean = CBool(e.NewValue)
    
     ' active / deactivate IsSelected / IsNotSelected visual state:
     If newValue Then
    
     VisualStateManager.GoToState(hb, "IsSelected", True)
    
     Else
    
     VisualStateManager.GoToState(hb, "IsNotSelected", True)
    
     End If
    
     End Sub
    
    
     End Class
    
    
    End Namespace
    
    

     

    MainPage.xaml.vb:

     

    Partial Public Class MainPage
    	Inherits UserControl
    
     Public Sub New()
     InitializeComponent()
    
     ' Travers the children of the stackpanel; 
     ' PLEASE NOTE: All children inside the stackpanel are
     ' of type HyperlinkButton. Keep this in mind when you add
     ' elements other than of type HyperlinkButton. In that case
     ' you will have to implement additional code that checks
     ' the type of each element before you add the delegate.
     For Each element As HyperlinkButton In spContainer.Children
     AddHandler element.Click, AddressOf NavigateToSite
     Next
    
     ' The logic of keeping the focus visually takes place in the navigated() event.
     ' The benefit of the navigated() event is, that the focus can be kept even when 
     ' the user navigates the app by using the browser history.
     AddHandler contentFrame.Navigated, AddressOf ControlIsSelectedState
    
     ' Here we go to the initial site when the app starts for the fisrt time.
     NavigateToSite(hb1, Nothing)
    
     End Sub
    
    
     Private Sub NavigateToSite(ByVal sender As Object, ByVal e As RoutedEventArgs)
    
     ' The sender is the HyperlinkButton the user has clicked.
     ' In the Xaml of each HyperlinkButton we set the name of 
     ' the Page the specific HyperlinkButton shall navigate to
     ' as value to the Tag property. This provides us to get
     ' the Page name and use this value to create the Uri.
     contentFrame.Navigate(New Uri("/" + CType(sender, HyperlinkButton).Tag.ToString + ".xaml", UriKind.RelativeOrAbsolute))
    
     End Sub
    
    
     Private Sub ControlIsSelectedState(ByVal sender As Object, ByVal e As Navigation.NavigationEventArgs)
    
     ' Set the focus on the plug-in
     System.Windows.Browser.HtmlPage.Plugin.Focus()
    
     ' Get the name part of the targeted page
     Dim target As String = e.Uri.OriginalString.Substring(1, e.Uri.OriginalString.IndexOf(CChar(".")) - 1)
    
     ' Travers the StackPanel container, containing the HyperlinkButtons
     For Each elem In spContainer.Children
    
     ' Check if the Tag value of the HyperlinButton fits to the name of the targeted page
     If CType(elem, HyperlinkButton).Tag.ToString = target Then
    
     ' If it fits, then set the IsKeepFocusVisualProperty to True ...
     elem.SetValue(SilverLaw.HyperlinkButtonExtension.IsKeepFocusVisualProperty, True)
    
     ' Set the focus on this HyperlinkButton
     CType(elem, HyperlinkButton).Focus()
    
     Else
    
     ' If it doesn't fit, set the IsKeepFocusVisualProperty to False
     elem.SetValue(SilverLaw.HyperlinkButtonExtension.IsKeepFocusVisualProperty, False)
    
     End If
    
     Next
    
     End Sub
    
    
     Private Sub contentFrame_NavigationFailed(ByVal sender As Object, ByVal e As System.Windows.Navigation.NavigationFailedEventArgs) Handles contentFrame.NavigationFailed
    
     Dim debugstop As Integer = 0
    
     'contentFrame.Navigate(contentFrame.CurrentSource)
    
     e.Handled = True
    
     End Sub
    
    
    End Class
    
    I have the same problem with a hyperlinkbutton custom control that has the same functionality as the example above (holding an additional VisualStateGroup in the template with two VisualStates to display an IsSelectedProperty DependencyProperty of custom control visually). There everything is running properly in the IE8 and I have the same problem in the IE9. If it is necessary, I can possibly the code for the custom control In addition to post.Any help or idea on this issue is very much appreciated.


    Saturday, April 23, 2011 2:16 PM