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

Nic*_*ner 6 c# silverlight xaml windows-phone-7

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

我有两个ListBoxs作为菜单.

                <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>
Run Code Online (Sandbox Code Playgroud)

这两个错误都存在.

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

    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;
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

我正在使用Silverlight for Windows Phone 7

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

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

<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));
        }
Run Code Online (Sandbox Code Playgroud)

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

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

                <ProgressBar x:Name="LoadingProgressBar"
                 IsIndeterminate="True"
                 Visibility="Collapsed"
                 Style="{StaticResource PerformanceProgressBar}"
                 VerticalAlignment="Top"/>
Run Code Online (Sandbox Code Playgroud)

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

LoadingProgressBar.Visibility = Visibility.Collapsed;
Run Code Online (Sandbox Code Playgroud)

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

这是控件的完整XAML,它变得混乱:

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

                <TextBlock x:Name="DownloadFailed"
                         Visibility="Collapsed"
                         Style="{StaticResource disabledText}"
                         Margin="56,8,8,-8" >
                    FooBar.com could not be reached. Do you have a network connection?
                </TextBlock>

                <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>

            </Grid>
        </controls:PivotItem>
Run Code Online (Sandbox Code Playgroud)

小智 0

在开始之前,我要说的是,我没有太多使用 Windows Phone 的经验,因此我的答案基于更通用的 WPF 知识,因此,如果我忽略了平台的具体情况,或者引用的功能并非如此,请原谅我。可用的。

一些诊断问题(抱歉,这不是直接答案):

首先,Navigate 似乎确实调用了大量的layoutUpdates。我还没有看到什么类型的容器包含您正在更新的页面,但值得一问的是,它是否也被破坏或只有菜单?

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

您将这些放在网格中,这意味着要根据其内容调整大小,或者采用默认大小(普通 WPF 中的 100x100)或从其父级中获取大小,而无需知道您如何指定网格或网格的父级,很难了解它的行为。此外,网格会根据其子级的添加顺序自动对其子级进行 z 排序。你能确定是否只是lisbox的布局受到干扰,还是整个网格受到干扰?或者说,它比这个大吗?

如果您附加到列表框、网格或网格父级的layoutUpdated()事件,您应该能够查看引导您到达那里的堆栈跟踪 - 在我看来,您会发现layoutUpdated()触发的次数超过你会喜欢的。此外,您将能够在这些步骤中输出高度和宽度(当然是实际高度等),以便您可以看到这些更改何时发生。

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