【问题标题】:Part of list not rendered部分列表未呈现
【发布时间】:2013-12-10 08:06:20
【问题描述】:

我遇到了布局渲染问题。我在C# 有一些经验,但我以前从未遇到过这样的事情。

我正在构建一个视频消息应用程序,当对话开始时会打开一个新窗口,并且列表和背景设置为Collapsed。 对话结束时,新窗口关闭,列表和背景设置回可见。

当发生这种情况时,我会得到: 我的列表是用 StackPanel 和 UserControl 构建的,当我滚动列表时,渲染再次正常。

我在 Google 上对未在 UI 上呈现的对象进行了一些研究,发现您可以使用 InvalidateVisual 强制再次呈现 UI,但这似乎不适用于我的应用程序。在使列表和背景可见之后,我会在每次对话结束时调用此方法。

有哪些方法可以确保 UI 正确呈现? 谢谢。

更新 1:

我已将这段代码添加到我的 UserControl。

protected override void OnRender(DrawingContext drawingContext)
{
   InvalidateVisual();
   base.OnRender(drawingContext);
}

但这是要走的路吗?我已经看到当我这样做时,该方法会在循环中反复调用,但我似乎不会影响我测试的设备的性能。

更新 2:

经过一些更深入的测试后,我发现我在 Update 1 中添加的代码确实对应用程序的性能有很大影响,所以这对我不起作用。

更新 3:

现在我使用Timer 在调用InvalidateVisual 之前创建了一个延迟。在调用 InvalidateVisual 之前将 Timer 设置为 500 毫秒,这会强制布局再次呈现。到我的第二个窗口关闭时,布局将第二次更新。这是我的代码

Timer t = new Timer(500);
t.AutoReset = false;
t.Elapsed += (s, ee) =>
{
   ((Timer)s).Stop();
   ((Timer)s).Dispose();
   InvalidateVisual();
};
t.Start();

经过快速测试,它似乎可以工作,但我需要更深入地测试它以确保。任何其他建议仍然欢迎。

更新 4:

在更新 3 中测试我的解决方案后,我发现这行不通。 @Sheridan:我的应用程序不需要调整大小,它是一个全屏应用程序。这是我为创建列表而编写的代码:

这是 XAML 代码

<TabItem x:Name="TabHistory" Header="Geschiedenis">
  <sys:FixedScrollViewer VerticalAlignment="Stretch" 
                     HorizontalAlignment="Stretch" 
                     PanningMode="VerticalOnly" 
                     Margin="0,0,0,7"
                     HorizontalScrollBarVisibility="Hidden"  
                     VerticalScrollBarVisibility="Hidden"
                     HorizontalContentAlignment="Left">
    <StackPanel x:Name="CallLogList" />
  </sys:FixedScrollViewer>
</TabItem>

这是填充它的代码。

private void OnRosterUpdate(object sender, RosterUpdateEventArgs e) 
{
  if (MessageWindow.IsOpen) MessageWindow.Close();
  Dispatcher.Invoke((Action)delegate()
  {
     if (e.Action == RosterAction.ADD)
     {
        RosterContact button = new RosterContact(e.Item);
        button.Call += StartCall_Callback;
        button.ShowInfo += Info_Callback;
        button.HideInfo += button_HideInfo;
        roster.Children.Add(button);
     }
     else if (e.Action == RosterAction.REMOVE)
     {
        foreach (RosterContact item in roster.Children)
        {
           if (item.UserData.Peer == e.Item.Peer)
           {
              roster.Children.Remove(item);
              break;
           }
        }
     }
  });
}

RosterContact 是 UserControl 类型。

【问题讨论】:

  • 滚动后尝试使用 this.Invalidate()
  • 当我滚动一点时,渲染再次正常。所以我认为它真的是让它崩溃,然后让它可见。

标签: c# .net wpf user-interface


【解决方案1】:

我不认为这与 InvalidateVisual... 在 WPF 中,我们不需要手动刷新 UI... 如果编写得当,WPF 会负责刷新 UI。

不幸的是,您没有显示任何代码,因此很难确定,但每当我听到/读到 StackPanel 和渲染问题时,通常意味着相同的事情......不要使用 @987654323 @s 用于 UI 布局!!他们调整其内容的大小。尝试用Grids 替换它们,您的问题可能就会得到解决。

【讨论】:

    【解决方案2】:

    我搜索了 allot 并没有找到任何关于此的内容。所以我用我自己的方式确保列表不会消失在我身上。它可能有点脏,但我不能带其他任何东西。当然,当找到另一种方法时,仍然欢迎提出建议。

    我现在的做法是在屏幕上创建一个全白屏幕。我就是这样做的,首先我在表单中创建了一个全屏网格并给它一个白色背景。

    <Grid Background="White" Visibility="Collapsed" x:Name="gridWhite" />
    

    我还创建了一个使白屏可见并在一秒钟后折叠它的函数。

    private void ShowWhiteScreen()
    {
        Dispatcher.Invoke(() =>
        {
            gridWhite.Visibility = System.Windows.Visibility.Visible;
            Timer t = new Timer(1000);
            t.AutoReset = false;
            t.Elapsed += (s, e) =>
            {
                ((Timer)s).Stop();
                ((Timer)s).Dispose();
                Dispatcher.Invoke(() =>
                {
                    gridWhite.Visibility = System.Windows.Visibility.Collapsed;
                });
            };
            t.Start();
        });
    }
    

    我通过从另一台平板电脑调用测试平板电脑对此进行了测试,对话后我的错误没有再次出现。我在这两种设备上进行了 5 次测试,每次都得到相同的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-23
      相关资源
      最近更新 更多