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
首先出现,然后窗口
被刷新并将滚动条
放回顶部)。我的问题的正确解决方法是什么 它看起来像是在呈现myUsercontrol
之前调用的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;
}
}