我有一个TextBlock内容是绑定到ViewModel的字符串属性的数据.这TextBlock有一个ScrollViewer缠绕它.
我想要做的是每次日志更改时,ScrollViewer将滚动到底部.理想情况下我想要这样的东西:
<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollPosition="{Binding Path=ScrollPosition}">
<TextBlock Text="{Binding Path=Logs}"/>
</ScrollViewer>
Run Code Online (Sandbox Code Playgroud)
我不希望后面使用代码!我在寻找应该使用该解决方案唯一的结合和/或XAML中.
Jus*_* XL 45
您可以创建附加属性或行为来实现您想要的而不使用后面的代码.无论哪种方式,您仍然需要编写一些代码.
以下是使用附加属性的示例.
附属物
public static class Helper
{
public static bool GetAutoScroll(DependencyObject obj)
{
return (bool)obj.GetValue(AutoScrollProperty);
}
public static void SetAutoScroll(DependencyObject obj, bool value)
{
obj.SetValue(AutoScrollProperty, value);
}
public static readonly DependencyProperty AutoScrollProperty =
DependencyProperty.RegisterAttached("AutoScroll", typeof(bool), typeof(Helper), new PropertyMetadata(false, AutoScrollPropertyChanged));
private static void AutoScrollPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var scrollViewer = d as ScrollViewer;
if (scrollViewer != null && (bool)e.NewValue)
{
scrollViewer.ScrollToBottom();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Xaml绑定
<ScrollViewer local:Helper.AutoScroll="{Binding IsLogsChangedPropertyInViewModel}" .../>
Run Code Online (Sandbox Code Playgroud)
您需要创建一个布尔属性,IsLogsChangedPropertyInViewModel并在更改字符串属性时将其设置为true.
希望这可以帮助!:)
Roy*_* T. 26
答案更新2017-12-13,现在使用ScrollChanged事件并检查范围的大小是否发生变化.更可靠,不会干扰手动滚动
我知道这个问题很老,但我有一个改进的实现:
该代码深受Justin XL和Contango解决方案的影响
public static class AutoScrollBehavior
{
public static readonly DependencyProperty AutoScrollProperty =
DependencyProperty.RegisterAttached("AutoScroll", typeof(bool), typeof(AutoScrollBehavior), new PropertyMetadata(false, AutoScrollPropertyChanged));
public static void AutoScrollPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
var scrollViewer = obj as ScrollViewer;
if(scrollViewer != null && (bool)args.NewValue)
{
scrollViewer.ScrollChanged += ScrollViewer_ScrollChanged;
scrollViewer.ScrollToEnd();
}
else
{
scrollViewer.ScrollChanged-= ScrollViewer_ScrollChanged;
}
}
private static void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
// Only scroll to bottom when the extent changed. Otherwise you can't scroll up
if (e.ExtentHeightChange != 0)
{
var scrollViewer = sender as ScrollViewer;
scrollViewer?.ScrollToBottom();
}
}
public static bool GetAutoScroll(DependencyObject obj)
{
return (bool)obj.GetValue(AutoScrollProperty);
}
public static void SetAutoScroll(DependencyObject obj, bool value)
{
obj.SetValue(AutoScrollProperty, value);
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
<ScrollViewer n:AutoScrollBehavior.AutoScroll="True" > // Where n is the XML namespace
Run Code Online (Sandbox Code Playgroud)
Con*_*ngo 12
来自Geoff的ScrollViewer AutoScroll行为博客.
添加此课程:
namespace MyAttachedBehaviors
{
/// <summary>
/// Intent: Behavior which means a scrollviewer will always scroll down to the bottom.
/// </summary>
public class AutoScrollBehavior : Behavior<ScrollViewer>
{
private double _height = 0.0d;
private ScrollViewer _scrollViewer = null;
protected override void OnAttached()
{
base.OnAttached();
this._scrollViewer = base.AssociatedObject;
this._scrollViewer.LayoutUpdated += new EventHandler(_scrollViewer_LayoutUpdated);
}
private void _scrollViewer_LayoutUpdated(object sender, EventArgs e)
{
if (Math.Abs(this._scrollViewer.ExtentHeight - _height) > 1)
{
this._scrollViewer.ScrollToVerticalOffset(this._scrollViewer.ExtentHeight);
this._height = this._scrollViewer.ExtentHeight;
}
}
protected override void OnDetaching()
{
base.OnDetaching();
if (this._scrollViewer != null)
{
this._scrollViewer.LayoutUpdated -= new EventHandler(_scrollViewer_LayoutUpdated);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
此代码取决于Blend Behaviors,它需要引用System.Windows.Interactivity.请参阅添加帮助System.Windows.Interactivity.
如果您安装MVVM Light NuGet包,可以在此处添加引用:
packages\MvvmLightLibs.4.2.30.0\lib\net45\System.Windows.Interactivity.dll
Run Code Online (Sandbox Code Playgroud)
确保标题中包含此属性,该属性指向System.Windows.Interactivity.dll:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Run Code Online (Sandbox Code Playgroud)
将混合行为添加到ScrollViewer:
<i:Interaction.Behaviors>
<implementation:AutoScrollBehavior />
</i:Interaction.Behaviors>
Run Code Online (Sandbox Code Playgroud)
例:
<GroupBox Grid.Row="2" Header ="Log">
<ScrollViewer>
<i:Interaction.Behaviors>
<implementation:AutoScrollBehavior />
</i:Interaction.Behaviors>
<TextBlock Margin="10" Text="{Binding Path=LogText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TextWrapping="Wrap"/>
</ScrollViewer>
</GroupBox>
Run Code Online (Sandbox Code Playgroud)
我们必须为命名空间添加一个定义,否则它将不知道在哪里找到我们刚刚添加的C#类.将此属性添加到<Window>标记中.如果您使用的是ReSharper,它会自动为您提供此信息.
xmlns:implementation="clr-namespace:MyAttachedBehaviors"
Run Code Online (Sandbox Code Playgroud)
现在,如果一切顺利,框中的文本将始终向下滚动到底部.
给出的示例XAML将绑定属性的内容打印LogText到屏幕,这非常适合日志记录.
小智 5
这很简单,例如:
yourContronInside.ScrollOwner.ScrollToEnd ();
yourContronInside.ScrollOwner.ScrollToBottom ();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
40628 次 |
| 最近记录: |