首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >UserControl BringIntoView()不能正常工作

UserControl BringIntoView()不能正常工作
EN

Stack Overflow用户
提问于 2013-09-10 16:50:14
回答 2查看 2.8K关注 0票数 2

背景:I有一个在ScrollViewer中定义的usercontrol和一个ContentControlContentControl将始终可见,其中有一个Button,当单击按钮时将usercontrol设置为Visible,当usercontrol显示(Visiblility="Visible")时,我希望将其滚动到视图中。我有过

XAML

代码语言:javascript
运行
复制
<ScrollViewer  VerticalScrollBarVisibility="Auto"  MaxHeight="465">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="*" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <ContentControl Content="{Binding MyOtherViewModel}"  Width="960" ></ContentControl>
    <local:MyView  IsVisibleChanged="MyView_IsVisibleChanged" Grid.Row="1" Visibility="{Binding IsNonCompliant, Converter={StaticResource BooltoVisible}, UpdateSourceTrigger=PropertyChanged}" />        
</ScrollViewer>

代码背后

代码语言:javascript
运行
复制
private void MyView_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as Control).BringIntoView();        
        }

问题:--它不起作用,或者更准确地说,我的usercontrol先滚动到视图中,然后在眨眼之间恢复到ScrollViewer的底部。

奇怪的事情:在调用BringIntoView之前显示了一个messagebox,它将正确地将my usercontrol显示在视图的中间

当前黑客解决方案:--您可以看到它甚至可以在Windowloaded之后立即关闭

代码语言:javascript
运行
复制
private void MyView_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
            {
                Window ss = new Window();
                ss.Loaded += new RoutedEventHandler(ss_Loaded);
                ss.ShowDialog();
                (sender as Control).BringIntoView();        
            }   

private void ss_Loaded(object sender, RoutedEventArgs e)
        {
            (sender as Window).Close();
        }

问题:--我知道肯定有别的事情发生了,但我只是无法辨认,但是我真的想知道当一个窗口显示在ShowDialog上时发生了什么?这是因为它刷新window以便BringIntoView只在加载usercontrol之后才会发生吗?(与我现在遇到的问题不同:BringIntoView首先发生,然后window被刷新,并将scrollbar重新放到顶部)。对我的问题有什么正确的解决办法?

EN

回答 2

Stack Overflow用户

发布于 2013-09-13 15:02:21

它看起来像是在我的BringIntoView被呈现之前调用的,因此当它被完全呈现时,scrollbar会恢复到顶部(正如我在我的问题中所描述的)。感谢@Evgeny发布的另一个问题的答案,我现在得到了一个更好的解决方案(也许更少的黑客攻击?)还想看看是否有更好的解决方案。

代码语言:javascript
运行
复制
   private void MyView_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
   {
        var border = (FrameworkElement)sender;
        if (border.IsVisible)
        {
            //Window ss = new Window();
            //ss.Loaded += new RoutedEventHandler(ss_Loaded);
            //ss.ShowDialog();
            using (BackgroundWorker bg = new BackgroundWorker())
            {
                bg.DoWork += new DoWorkEventHandler(bg_DoWork);
                bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
                Tuple<FrameworkElement, double> b = new Tuple<FrameworkElement, double>(border, border.Height);
                bg.RunWorkerAsync(b);
            }
        }
   }       

    private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        (e.Result as UserControl).BringIntoView();
    }

    private void bg_DoWork(object sender, DoWorkEventArgs e)
    {   
        int maxwait = 300 //not scrolled to the view is not a disaster, but if the program hangs forever it will be a disaster, so set this to prevent that from happening
        while (maxwait!=0 
               && 
               (e.Argument as Tuple<FrameworkElement, double>).Item1.ActualHeight != (e.Argument as Tuple<FrameworkElement, double>).Item2)
        {
            Thread.Sleep(1);
            maxwait --;
        }
        e.Result = (e.Argument as Tuple<FrameworkElement, double>).Item1;
    }  
票数 1
EN

Stack Overflow用户

发布于 2014-11-24 10:52:38

我不敢相信使用背景工作者是一个正确的解决方案!您可以使用LayoutUpdated事件轻松查找何时加载并最终显示控件。

代码语言:javascript
运行
复制
userControl.LayoutUpdated+=OnLayoutUpdated;    
private bool loaded=false;


    private void OnLayoutUpdated(object sender,EventArgs e)
    {
      if (!loaded && (view.ActualHeight > 0 || view.ActualWidth > 0))
      {
         // Unsubscribe or set a flag.
         userControl.LayoutUpdated -= OnLayoutUpdated;
         loaded = true;
      }
    }

因此,您可以在更新布局和设置高度或宽度时执行该代码。这意味着将加载并显示控件。无法取消订阅或设置初始化已完成的标志。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18724686

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档