C# UserControl BringIntoView()工作不正常

C# UserControl BringIntoView()工作不正常,c#,wpf,user-controls,scrollbar,C#,Wpf,User Controls,Scrollbar,背景: 我在ScrollViewer中定义了一个usercontrol以及一个ContentControl,该ContentControl将一直可见,其中有一个按钮,当单击该按钮时,将usercontrol设置为visible,当usercontrol显示(visibility=“visibility”)时,我希望将其滚动到视图中。我有 XAML 问题:这不起作用,或者更准确地说,我的usercontrol首先滚动到视图中,然后在一眨眼的时间内返回到ScrollViewer的底部 奇怪的事情:在

背景: 我在
ScrollViewer
中定义了一个
usercontrol
以及一个
ContentControl
,该
ContentControl
将一直可见,其中有一个
按钮
,当单击该按钮时,将
usercontrol
设置为
visible
,当
usercontrol
显示(
visibility=“visibility”
)时,我希望将其滚动到视图中。我有

XAML

问题:这不起作用,或者更准确地说,我的
usercontrol
首先滚动到视图中,然后在一眨眼的时间内返回到
ScrollViewer
的底部

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

当前黑客解决方案:您可以看到,即使在加载
后立即关闭
窗口
,也可以使用此方法

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
的窗口时发生了什么?这是因为它刷新了
窗口
,因此只有在加载
用户控件
后才会出现
弹出视图
?(与我现在遇到的问题不同:
BringIntoView
首先出现,然后
窗口
被刷新并将
滚动条
放回顶部)。我的问题的正确解决方法是什么

它看起来像是在呈现my
Usercontrol
之前调用的
BringIntoView
,因此,当它完全呈现时,
滚动条会还原回顶部(如我在问题中所述)。谢谢你对另一个问题的回答,我现在得到了更好的解决方案(可能更少的黑客?)。还是想看看是否有更好的解决方案

   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;
    }  
private void MyView\u IsVisibleChanged(对象发送方,DependencyPropertyChangedEventArgs e)
{
var border=(FrameworkElement)发送方;
if(border.IsVisible)
{
//窗口ss=新窗口();
//ss.Loaded+=新的路由防盗器(ss_Loaded);
//ss.ShowDialog();
使用(BackgroundWorker bg=新BackgroundWorker())
{
bg.DoWork+=新DoWorkEventHandler(bg_DoWork);
bg.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler(bg\u RunWorkerCompleted);
元组b=新元组(border,border.Height);
运行工作同步(b);
}
}
}       
私有void bg_RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
(e.Result as UserControl).BringIntoView();
}
私有void bg_DoWork(对象发送方,DoWorkEventArgs e)
{   
int maxwait=300//not scrolled to the view不是一个灾难,但是如果程序永远挂起,它将是一个灾难,因此设置此选项以防止发生这种情况
while(maxwait!=0
&& 
(e.参数作为元组)。Item1.实际高度!=(e.参数作为元组)。Item2)
{
睡眠(1);
maxwait--;
}
e、 结果=(e.参数为元组);
}  

使用后台工作程序进行此类操作是不正确的!如果您只能使用LayoutUpdated事件,那么它将是最佳选项。当实际宽度或高度不等于0时执行作业,或使用计时器而不是bg worker

userControl.LayoutUpdated+=OnLayoutUpdated;

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

在scrollviewer中除了你的用户控件还有什么?我已经按照你在throwaway项目中所描述的创建了安装程序,它可以在没有任何窗口的情况下按照你的预期工作。“你必须有一些你认为与这个问题无关的事情发生在那里。”拉斐尔,我已经更新了我的问题。谢谢。@nit,我有一个
ContentControl
   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;
    }  
userControl.LayoutUpdated+=OnLayoutUpdated;

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