【问题标题】:Silverlight: Layout changes when I call NavigationService.NavigateSilverlight:当我调用 NavigationService.Navigate 时布局发生变化
【发布时间】:2010-12-30 19:21:54
【问题描述】:

这是一个非常奇怪的错误。我不知道为什么会这样。我知道在这里发布它有点远,但我没有其他想法。

我有两个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>

这两个漏洞都存在。

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

    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 方法,所以我认为这不是问题。

我正在使用适用于 Windows Phone 7 的 Silverlight

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

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

<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));
        }

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

更新 3:更怪异。附加调试器时仍然无法重现应用程序。如果我让加载进度条总是折叠,bug就消失了:

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

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

LoadingProgressBar.Visibility = Visibility.Collapsed;

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

这里是混乱的控件的完整 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>

【问题讨论】:

  • 这种问题通常与异步调用有关,并且有 70% 的时间在其他事情之前发生了某些事情(这可能是它在调试模式下工作的原因)。尝试使用一个不依赖于项目其余部分的较小示例来重现该问题,然后将其发布在这里,很难用您提供的内容重现您所拥有的相同内容。
  • 您有任何自定义导航框架,还是只有默认框架? ViewModel 是否在后台做一些异步工作?我需要更多详细信息,以帮助您解决问题!
  • 没有自定义导航框架。唯一的异步代码是WebClient从网络下载数据。

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

    如果您附加到列表框、网格或网格父级的 layoutUpdated() 事件,您应该能够查看引导您到那里的堆栈跟踪 - 在我看来,您会发现 layoutUpdated() 是发射比你想要的更多。此外,您将能够在这些步骤中输出高度和宽度(当然是 ActualHeight 等),这样您就可以看到这些变化发生的确切时间。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-29
      • 1970-01-01
      • 2016-05-02
      • 2021-09-28
      • 1970-01-01
      • 2013-10-01
      • 1970-01-01
      相关资源
      最近更新 更多