locked
Problem bei Browser-History-Navigation im IE9 - System.ArgumentException RRS feed

  • Allgemeine Diskussion

  • Hallo,

    ich habe ein seltsames Problem mit dem IE9 bei einer Silverlight-Navigationsanwendung. Die SL app besteht aus einem Frame, in dem 4 Pages dargestellt werden können. Wenn ich in der SL app durch Klick auf die HyperlinkButton die Seiten in loser Reihenfolge nacheinander aufrufe und dann die Browser-History verwende um rückwärts zu navigieren, funktioniert noch alles einwandfrei.

    Wenn ich dann aber in der Browser-History vorwärts navigieren will, landet der ablaufende Code im NavigationFailed event und wirft eine System.ArgumentException. Eine Auswertung von e.Uri beim Debuggen ergibt, dass der Wert des Uri leer ist.

    Eine System.ArgumentException wird auch geworfen, wenn in folgender Reihenfolge durch die Pages der Seiten navigiert wird:

    Ausgangspunkt: Startseite Page1 (wird aufgerufen Frame.Navigate(...) im Konstruktor von MainPage.xaml.vb)

    Aktion: Klick auf HyperlinkButton P2 -> Navigation zu Page2

    Aktion: Klick auf den Rückwärts-Button im Browser -> Navigation zu Page1

    Aktion: Klick auf den Vorwärts-Button im Browser -> Navigation zu Page2

    Aktion: Klick auf den Rückwärts-Button im Browser -> NavigationFalied() mit System.ArgumentException (leerer Uri)

     

    Die im Browser durch einen Rechtsklick auf die Vorwärts- bzw. Rückwärts-Button angezeigten Verlaufsdaten entsprechen der historischen Abfolge der Seitenaufrufe.

     

    Die JournalOwnership-Eigenschaft des Frame hat den Wert Automatisch.

     

    Den IE9 habe ich heute morgen installiert. Davor benutzte ich den IE8. Beim IE8 trat mit demselben Code dieses Problem nicht auf.

     

    Woran kann das liegen?

     

    • Typ geändert Robert Breitenhofer Freitag, 13. Mai 2011 14:18 Keine Rückmeldung des Fragenstellender
    Freitag, 22. April 2011 11:02

Alle Antworten

  • Auf der weiteren Suche nach der Fehlerquelle habe ich mal überprüft, wie sich andere Navigationsanwendungen verhalten, die ich früher entwickelt habe. Das Ergebnis ist, dass dort dieses Problem nicht auftaucht.

    Ich gehe daher davon aus, dass es an dem speziellen Projekt liegen muss, bei dem dieser Fehler geworfen wird. Deswegen zeige ich weiter unten mal den wesentlichen Quellcode.

    Ein paar Erläuterungen zum Projekt:

    Aufgabe des Projekts ist es, die Verwendung eines Custom Attached DependencyProperty (IsKeepFocusVisualProperty) zu testen, das ich entworfen habe. Dieses Attached DependencyProperty hat die Aufgabe, zwei VisualStates (IsSelected und IsNotSelected) einer zusätzlichen VisualStateGroup (KeepFocusVisualStates) aus der HyperlinkButton-Vorlage zu verwalten. Diese VisualStates simulieren visuell den Focus für einen HyperlinkButton auch dann, wenn der HyperlinkButton den Focus nicht (mehr) hat. Damit erhält der HyperlinkButton einen visuellen Indikator für die aktuell angezeigte Seite.

    Die Attached DependencyProperty IsKeepFocusVisualProperty ist in der Klasse HyperlinkButtonExtension.vb definiert. Verwendet wird sie in der Routine ControlIsSelectedState() in MainPage.xaml. ControlIsSelectedState() hängt sich an das Navigated()-Ereignis des Frame heran. In der Ereignisbehandlung wird der Wert von IsKeepFocusVisualProperty dynamisch jeweils für den HyperlinkButton aus True gesetzt, der geklickt wurde, für alle anderen HyperlinkButtons wird der Wert aus False gesetzt. Im PropertyChangedCallBack von IsKeepFocusVisualProperty (OnIsKeepFocusVisualPropertyChanged) wird dann entweder der VisualState IsSelected oder der VisualState IsNotSelected aktiviert, je nach dem, ob der neue Wert True oder False ist.

    Wie gesagt, das Ganze funktioniert einwandfrei im IE8. Seit ich heute morgen den IE9 installierte, wird in den beschriebenen Ablauffolgen bei der Verwendung der Browser-History-Navigation eine System.ArgumentException geworfen.

    Her ist also der Quellcode:

    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
    

     

    Das obige Beispiel-Projekt sollte eigentlich in Teil 1 eines Artikels verwendet werden, in dem ich diese Lösung detailliert vorstelle. Was für ein Glück, dass ich vor der Veröffentlichung den IE9 installiert habe. Teil 2 des Artikels befaßt sich mit einem HyperlinkButton Custom Control, das die gleiche Funktionalität hat, (Halten einer zusätzlichen VisualStateGroup in der Vorlage mit zwei VisualStates zur visuellen Darstellung einer IsSelectedProperty als DependencyProperty des Custom Control). Das HyperlinButton Custom Cntrol erbt von HyperlinkButton. Seltsamerweise bestehen bei der Lösung über das HyperlinkButton Custom Control die selben Probleme im IE9, wie bei der Lösung über eine Custom Attached DependencyProperty! Im IE8 läuft aber auch das einwandfrei. Wenn es notwendig ist, kann ich den Code für das Custom Control ggfls. zusätzlich posten.

    Ehrlich gesagt, im Moment bin ich ratlos.

    Es wäre wirklich super, wenn sich jemand die Mühe machen könnte, mir bei der Suche nach der Ursache für den Fehler zu helfen. Wie gesagt, im IE8 funktioniert das Ganze reibungslos. Nur halt im IE9 nicht.

    Beste Grüße,

    Martin

     

     

    Freitag, 22. April 2011 12:25
  • Hallo,

    nach diversen Versuchen der Fehlersuche habe ich festgestellt, dass der Fehler sehr wahrscheinlich in meinem Visual Studio 2010 verborgen ist. Denn der Fehler taucht nur beim Debuggen, und auch nur beim Debuggen mit Visual Studio 2010 auf. Beim Debuggen mit Expression Blend 4 läuft alles einwandfrei. Auch nach einem release im Internet läuft alles korrekt. (Was schonmal ziemlich cool ist, weil das bedeutet, dass mein Quellcode sauber funktioniert.)

    Als wahrscheinliche Ursache habe ich folgendes festgestellt. Beim Debuggen mit Visual Studio 2010 wird nach dem Start der Anwendung im Browser oben in der Adresszeile folgende url angezeigt:

    file:///C:/Entwicklungsprojekte%204/SL%204%20VB/Blog%20Labs/KeepHyperlinkButtonFocusVisually/KeepHyperlinkButtonFocusVisually/Bin/Debug/TestPage.html#/home.xaml

    Beim Debuggen mit Expression Blend 4 wird demgegenüber angezeigt:

    http://localhost:49265/TestPage.html#/home.xaml

    Kann es sein, dass mein VS2010 nicht mehr korrekt an den development server angebunden ist? Wie kann ich das Problem beheben?


    Mittwoch, 27. April 2011 07:45
  • Hallo Martin,

     

    ich würde mal schauen welches Projekt die Startanwendung ist. Dort dann in den Projekt - Einstellungen prüfen was beim Start gemacht werden soll. Bei einem WebProjekt müsste in den Projekteigenschaften unter "Web" alles nötige zu finden sein (VS WebServer verwenden etc).

     

    Daniel


    http://www.silverlight-community.de - deutsche Community mit Tutorials, Blogs und Usergroups
    Donnerstag, 28. April 2011 11:57
  • Hallo Daniel,

    vielen Dank für Deine Antowrt.

    Es ist ein Silverlight-Projekt ohne WebProject. In den Projekteigenschaften ist demzufolge für das Startprojekt nur angezeigt, dass die Testseite dynamisch erzeugt wird. Wo finde ich denn eigentlich für ein solches Projekt die Einstellungen/Informationen über den WebServer für das Debugging?

    Beste Grüße,

    Martin

     

    Donnerstag, 28. April 2011 12:17
  • Reine Silverlight - Projekte (ohne Web) werden vom Studio aus immer ohne Server gestartet.

    Da hilft es nur ein "TestWeb" als Projekt hinzuzufügen oder die Projektausgabe in ein Verzeichnis zu leiten welches im IIS gemappt ist.

    Expression Blend verhält sich da anderes und startet immer den Dev-WebServer.

     

    Schönes Wochenende,

    Daniel


    http://www.silverlight-community.de - deutsche Community mit Tutorials, Blogs und Usergroups
    Freitag, 29. April 2011 12:16