WPF 消息框 TextBox 綁定新數據時讓光標和滾動條跳到最下面
我們在使用 WPF 的 TextBox 作為消息展示框時,如果想在出現滾動條之后,新消息到來時還能夠被看到,也就是說讓滾動條始終在最下面,或者說光標始終在最后面,有什么方法呢?
當然,直接在后台寫邏輯,在附加新消息時控制滾動條或者光標移到最后,這是一個辦法。不過,本文探討的是直接在前台 Xaml 處實現這個需求,這樣更適合於 MVVM 模式的程序。
需要用到 System.Windows.Interactivity.dll 和 Microsoft.Expression.Interactions.dll 這兩個動態庫:
關於這兩個動態庫,有些人說使用 NuGet 安裝(版本很舊了),有些人說是安了 Blend 之后才有,還有的人從網上搜索下載。事實上,如果你是做開發的,或者是喜歡安各種軟件的朋友,那么很大概率上,在你的電腦的很多隱秘的角落,都散落着它們的身影。所以,我們只需要使用類似 Everything 這樣的軟件進行搜索,就能拿來為我所用了。
至於選擇哪個,則可以看文件版本,或者明顯更適合你的程序的那個(依據 .NET 版本)。我這次選擇的 dll 版本號分別為 3.0.40218 和 2.0.20525:
找到后,將它們拷貝到項目中,並添加引用。然后在 Xaml 中添加命名空間引用:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
這樣就可以在 TextBox 中使用了:
<!--消息框--> <TextBox x:Name="TBInfo" Grid.Column="0" Height="Auto" TextWrapping="Wrap" AcceptsReturn="True" VerticalScrollBarVisibility="Auto" Text="{Binding Info}"> <i:Interaction.Triggers> <ei:DataTrigger Binding="{Binding Text.Length, ElementName=TBInfo}" Comparison="NotEqual" Value="0"> <ei:ChangePropertyAction TargetName="TBInfo" PropertyName="CaretIndex" Value="{Binding ElementName=TBInfo, Path=Text.Length}"> </ei:ChangePropertyAction> </ei:DataTrigger> </i:Interaction.Triggers> </TextBox>
<i:Interaction.Triggers> 就是觸發器開始,ei:DataTrigger 就是數據觸發器(注意區別於 WPF 自帶的 DataTrigger),綁定了元素 TBInfo 的 Text.Length,當其值不等 0 時執行內部指令。ei:ChangePropertyAction 指令表示改變屬性值,目標元素也是 TBInfo,屬性為插入位置,也就是光標位置 CaretIndex,將光標位置的值綁定為文本長度,這樣就能將光標置於最后了。(這里面應該還能簡化或者改進,大家自行探索)
先來看看動圖效果:
可以看到輸入一個字符后,也就是信息變動了之后,光標馬上跳到了最后面。所以,這個是消息框專用的,不適用於輸入框。
最后來看看實戰的效果吧(動圖):
可以看到,效果是能達到,不過要求是文本框要先獲得焦點,這個要求說實話也無可厚非。
如果實在要在未獲取焦點時也能到最底下,可使用 調用方法指令(ei:CallMethodAction) 控制光標滾動到最后:
<ei:CallMethodAction MethodName="ScrollToEnd"></ei:CallMethodAction>
這句的后台等價代碼為:
TBInfo.ScrollToEnd();
建議兩個指令一起使用,所以最終消息框代碼為:
<TextBox x:Name="TBInfo" Grid.Column="0" Height="Auto" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" Text="{Binding Info}"> <i:Interaction.Triggers> <ei:DataTrigger Binding="{Binding Text.Length, ElementName=TBInfo}" Comparison="NotEqual" Value="0"> <ei:ChangePropertyAction TargetName="TBInfo" PropertyName="CaretIndex" Value="{Binding ElementName=TBInfo, Path=Text.Length}"> </ei:ChangePropertyAction> <ei:CallMethodAction MethodName="ScrollToEnd"></ei:CallMethodAction> </ei:DataTrigger> </i:Interaction.Triggers> </TextBox>
代碼放在了本人的 WPF 模板項目中:https://gitee.com/dlgcy/WPFTemplate
祝使用愉快!
同步首發:
http://dlgcy.com/wpf-textbox-scroll-bottom/