Silverlight:当我调用NavigationService.Navigate时,布局会发生变化

时间:2010-12-30 19:21:55

标签: c# silverlight xaml windows-phone-7

这是一个非常奇怪的错误。我不知道为什么会发生这种情况。我知道在这里发布它有点长篇大论,但我没有其他想法。

我有两个ListBox作为菜单。

                <ListBox Margin="56,8,15,0" FontSize="64"
                         ItemsSource="{Binding FavoriteSections}"
                         SelectionChanged="MenuList_SelectionChanged">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <toolkit:ContextMenuService.ContextMenu>
                                    <toolkit:ContextMenu>
                                        <toolkit:MenuItem Header="Remove" Click="FavoritesContextMenuItem_Click" />
                                    </toolkit:ContextMenu>
                                </toolkit:ContextMenuService.ContextMenu>

                                <TextBlock Text="{Binding DisplayName}" />
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>


                <ListBox x:Name="sectionList" Margin="56,8,15,0" FontSize="64" 
                         SelectionChanged="MenuList_SelectionChanged"
                         ItemsSource="{Binding SectionViewModels}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <toolkit:ContextMenuService.ContextMenu>
                                    <toolkit:ContextMenu>
                                        <toolkit:MenuItem Header="Add to favorites" Click="SectionContextMenuItem_Click" />
                                    </toolkit:ContextMenu>
                                </toolkit:ContextMenuService.ContextMenu>
                                <TextBlock Text="{Binding DisplayName}" />
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

这两个错误都存在。

当任一菜单上的选择发生变化时,会调用此方法:

    void MenuList_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e.AddedItems.Count == 0)
        {
            return;
        }

        Uri page = null;
        object selected = e.AddedItems[0];
        if (selected is NavigableItem)
        {
            NavigableItem selectedItem = (NavigableItem)selected;
            page = selectedItem.Page;
        }
        else if (selected is SectionViewModel)
        {
            SectionViewModel selectedVM = (SectionViewModel)selected;
            page = selectedVM.Section.Page;
        }

        Debug.Assert(page != null, "What is the type of `selected`?");

        // if I comment out this line, the problem goes away:
        NavigationService.Navigate(page);

        ListBox selectedBox = (ListBox)sender;
        selectedBox.SelectedIndex = -1;
    }

如果我注释掉NavigationService.Navigate()行,则问题就会消失。如果我用不同的URI替换该行,则问题仍然存在。

大约70%的时间,当我点击菜单项时,内容会跳到整个页面。 (剩余的30%,没有错误发生。)发生的事情发生得太快,看不到真正发生的事情,但不同的UI元素相互重叠。

这只发生在应用程序生命周期内第一次点击这些菜单中的内容时。如果我点击“返回”然后再次选择菜单项,则不会出现问题。

这里可能发生什么?我真的不知道。代码隐藏没有OnNavigatedFrom方法,因此我不认为这是一个问题。

我正在使用Silverlight for Windows Phone 7

更新:神秘的是,我似乎无法在调试器中重现这一点 - 只有在部署应用程序并在未连接的模拟器中运行它之后。 ???

更新2 :从按钮的NavigationService.Navigate()事件处理程序调用{​​{1}}时出现错误:

Click

看起来这个错误与导航有关,而不是用于触发调用的UI元素。

更新3 :更奇怪。在附加调试器时仍无法重现应用程序。如果我使加载进度条总是崩溃,则错误消失:

<Button Content="Foo" Click="Button_Click" Grid.Row="0"/>

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            NavigationService.Navigate(new Uri("/Views/sections.xaml?section=43", UriKind.Relative));
        }

或者,在代码隐藏中注释掉这一行会使错误消失:

                <ProgressBar x:Name="LoadingProgressBar"
                 IsIndeterminate="True"
                 Visibility="Collapsed"
                 Style="{StaticResource PerformanceProgressBar}"
                 VerticalAlignment="Top"/>

我真的不明白这里发生了什么。从页面导航时不执行该行代码。

这是控制器的完整XAML,它已经搞砸了:

                

LoadingProgressBar.Visibility = Visibility.Collapsed;

2 个答案:

答案 0 :(得分:1)

问题在于您使用 Indeterminate ProgressBar。它的所有动画都是在UI线程上完成的,而不是通常的做法,而不是Compositor线程。由于您已经在使用Windows Phone Toolkit,因此可以使用工具包提供的PerformanceProgressBar轻松替换ProgressBar。这应该可以解决你的问题。

答案 1 :(得分:0)

在开始之前,请允许我说我对Windows Phone没有太多经验,所以我的答案基于更通用的WPF知识,所以请原谅我,如果我忽略了平台的细节,或者我引用不可用的功能。

一些诊断问题(对不起,这不是直接的答案):

首先,看起来Navigate似乎调用了很多layoutUpdates。我还没有看到什么类型的容器包含您正在更新的页面,但值得一提的是,是否也被中断或只有菜单?

其次,您可以尝试明确指定itemPanel吗?您期望它们是virtualizingStackPanels,但您可能会发现可视层次结构中的某些父对象正在创建不同的继承方案。

你有这些在网格中,它的大小是其内容,或采用默认大小(普通WPF为100x100)或从其父级获取大小,这不知道你如何指定网格,或网格的父母,很难知道它的行为。此外,网格根据添加顺序自动对子项进行z排序。你能确定它是否只是受到干扰的lisboxes的布局,还是它是整个网格?或者,它是否大于那个?

如果您附加到列表框,网格或网格的父级的layoutUpdated()事件,您应该能够查看引导您的堆栈跟踪 - 听起来您会发现layoutUpdated()是射击比你想要的更多。此外,您将能够在这些步骤中输出高度和宽度(当然为ActualHeight等),以便您可以确切地知道这些更改何时发生。

我希望其中一些诊断步骤可以帮助您找到答案。