UserControl BringIntoView()无法正常工作 [英] UserControl BringIntoView() not working properly
问题描述
背景:
我在ScrollViewer
和ContentControl
中定义了usercontrol
,ContentControl
始终可见,并且其中有一个Button
,单击按钮时将设置Visible
,并且当usercontrol
显示(Visiblility="Visible"
)时,我希望将其滚动到视图中.我有
Background:
I have a usercontrol
defined in a ScrollViewer
along with a ContentControl
, the ContentControl
will be visible all the time, and within it there is a Button
, when the button is clicked will set the usercontrol
to Visible
, and when the usercontrol
shows (Visiblility="Visible"
) I want it to be scrolled into the view. I have
XAML
<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>
背后的代码
private void MyView_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
(sender as Control).BringIntoView();
}
问题: :这不起作用,或更准确地说,我的usercontrol
首先滚动到视图中,然后在眨.
Problem: this is not working, or more precisely, my usercontrol
scrolled into the view first then revert back to the bottom of the ScrollViewer
in a blink.
奇怪的事情: 在调用BringIntoView
之前显示messagebox
会正确地将我的usercontrol
显示在视图中间
Weird thing: show a messagebox
before calling BringIntoView
will correctly display my usercontrol
into the middle of the view
当前的黑客解决方案: ,您甚至可以看到Window
在loaded
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
放回顶部).对我的问题正确的解决方法是什么?
Question: I know there must be something else going on, but I just can't identify it, but I really want to know what happened when a window showing with ShowDialog
? Is this because it refreshes the window
so that the BringIntoView
will happen only after the usercontrol
been loaded? (Not as the problem I have now: BringIntoView
happened first, and then the window
get refreshed and put the scrollbar
back to the top). And what is the correct fix for my problem?
推荐答案
看起来像BringIntoView
在我的Usercontrol
渲染之前被调用,结果,当它完全渲染时,scrollbar
还原为顶部(正如我在问题中所描述的).还要感谢 @Evgeny 提出的另一个问题的答案,我现在有了更好的解决方案(也许没有hack了?).还是想看看是否有更好的解决方案.
It looks like BringIntoView
called before my Usercontrol
getting rendered, as a result when it gets fully rendered, the scrollbar
is revert back to the top (as I have described in my question). And thanks for the answer from @Evgeny posted for another question, I get a better solution now (less hack maybe?). Still want to see if there are better solutions.
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 BringIntoView()无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!