WPF-自动滚动文本控件

效果图:

控件功能:根据文本自动换行,每增加一行,自动滚动到最后一行。

封装过程使用NuGet

复制代码
  <ItemGroup>
    <PackageReference Include="DevExpressMvvm" Version="24.1.6" />
    <PackageReference Include="ValueConverters" Version="3.1.22" />
  </ItemGroup>

代码部分:

  1. StringToColorConvert.cs

    cs 复制代码
    using System.Windows.Media;
    using System.Globalization;
    using System.Reflection;
    using System.Windows.Data;
    
    namespace WPFApp
    {
        public class StringToColorConvert : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                Dictionary<string, string> colorDic = parameter.ToString().Split(';', StringSplitOptions.RemoveEmptyEntries).Where(s=>s.Contains(':')).ToDictionary(s => s.Split(':')[0], s => s.Split(':')[1]);
                Brush brush = Brushes.Black;
                if (value == null)
                {
                    return brush;
                }
                if (colorDic.TryGetValue(value.ToString(), out string dicValue))
                {
                    PropertyInfo colorProperty = typeof(Brushes).GetProperty(dicValue, BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase);
                    if (colorProperty != null)
                    {
                        brush = (Brush)colorProperty.GetValue(null);
                    }
                }
                return brush;
    
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    }
  2. App.xaml

    cs 复制代码
    <Application
        x:Class="WPFApp.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPFApp"
        StartupUri="MainWindow.xaml">
        <Application.Resources>
            <local:StringToColorConvert x:Key="StringToColorConvert" />
            <Style TargetType="{x:Type local:LogControl}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type local:LogControl}">
                            <Border
                                HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                                VerticalAlignment="{TemplateBinding VerticalAlignment}"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                                <ItemsControl
                                    x:Name="PART_ItemsControl"
                                    HorizontalAlignment="Stretch"
                                    VerticalAlignment="Stretch"
                                    ItemsSource="{TemplateBinding Items}">
                                    <ItemsControl.Template>
                                        <ControlTemplate TargetType="ItemsControl">
                                            <ScrollViewer Name="scrollViewer" VerticalScrollBarVisibility="Auto">
                                                <StackPanel>
                                                    <ItemsPresenter />
                                                </StackPanel>
                                            </ScrollViewer>
                                        </ControlTemplate>
                                    </ItemsControl.Template>
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <Grid>
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="Auto" />
                                                    <RowDefinition Height="Auto" />
                                                </Grid.RowDefinitions>
                                                <!--  文本  -->
                                                <TextBlock
                                                    Grid.Row="0"
                                                    Width="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ActualWidth}"
                                                    Padding="0,3,0,1"
                                                    VerticalAlignment="Center"
                                                    Foreground="{Binding Item2, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource StringToColorConvert}, ConverterParameter='0:Black;1:Green;2:Red;'}"
                                                    Text="{Binding Item1, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
                                                    TextTrimming="CharacterEllipsis"
                                                    ToolTip="{Binding Text, RelativeSource={RelativeSource Mode=Self}}">
                                                    <TextBlock.Style>
                                                        <Style TargetType="TextBlock">
                                                            <Style.Triggers>
                                                                <Trigger Property="IsMouseOver" Value="True">
                                                                    <Setter Property="Background" Value="#bee6fd" />
                                                                </Trigger>
                                                            </Style.Triggers>
                                                        </Style>
                                                    </TextBlock.Style>
                                                </TextBlock>
                                                <!--  下划线  -->
                                                <Border
                                                    Grid.Row="1"
                                                    Height="0.2"
                                                    Background="Black" />
                                            </Grid>
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Application.Resources>
    </Application>
  3. LogControl.cs

    cs 复制代码
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    
    namespace WPFApp
    {
        [TemplatePart(Name = LOGItemsControl, Type = typeof(ItemsControl))]
    
        public class LogControl:UserControl
        {
            public const string LOGItemsControl = "PART_ItemsControl";
            private ItemsControl logItemsControl;
    
            public ObservableCollection<Tuple<string, int>> Items
            {
                get { return (ObservableCollection<Tuple<string, int>>)GetValue(ItemsProperty); }
                set { SetValue(ItemsProperty, value); }
            }
    
            public static readonly DependencyProperty ItemsProperty =
                DependencyProperty.Register(nameof(Items), typeof(ObservableCollection<Tuple<string, int>>), typeof(LogControl), new PropertyMetadata(default, (d, e) =>
                {
                    var control = (LogControl)d;
                    if (e.NewValue != null && control.Items != null)
                    {
                        control.Items.CollectionChanged += (sender, args) =>
                        {
                            if (args.Action != NotifyCollectionChangedAction.Add) return;
                            control.Dispatcher.InvokeAsync(() =>
                            {
                                control.ScrollToEnd();
                            });
                        };
                    }
                }));
    
            public override void OnApplyTemplate()
            {
                logItemsControl = GetTemplateChild(LOGItemsControl) as ItemsControl;
                base.OnApplyTemplate();
            }
    
            private void ScrollToEnd()
            {
                var scrollViewer = FindScrollViewer(logItemsControl);
                if (scrollViewer != null)
                {
                    scrollViewer.ScrollToEnd();
                }
            }
    
            public ScrollViewer FindScrollViewer(ItemsControl itemsControl)
            {
                var templateRoot = itemsControl.Template.FindName("scrollViewer", itemsControl) as ScrollViewer;
                if (templateRoot != null)
                {
                    return templateRoot;
                }
                return FindVisualChild<ScrollViewer>(itemsControl);
            }
    
            private T FindVisualChild<T>(DependencyObject parent) where T : DependencyObject
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
                {
                    var child = VisualTreeHelper.GetChild(parent, i);
                    if (child is T)
                    {
                        return (T)child;
                    }
                    var foundChild = FindVisualChild<T>(child);
                    if (foundChild != null)
                    {
                        return foundChild;
                    }
                }
                return null;
            }
        }
    }

使用 :

  1. MainWindow.xaml

    cs 复制代码
    <Window
        x:Class="WPFApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:WPFApp"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Title="MainWindow"
        Width="800"
        Height="450"
        mc:Ignorable="d">
        <Window.DataContext>
            <local:MainWindowViewModel />
        </Window.DataContext>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <local:LogControl Items="{Binding Items}" />
            <Button
                Grid.Row="1"
                Click="{DXEvent 'AddItems()'}"
                Content="测试" />
        </Grid>
    </Window>
  2. MainWindowViewModel.cs

    cs 复制代码
    using System.Collections.ObjectModel;
    using ValueConverters;
    
    namespace WPFApp
    {
        public class MainWindowViewModel : BindableBase
        {
            private ObservableCollection<Tuple<string, int>> items;
    
    
            public ObservableCollection<Tuple<string, int>> Items
            {
                get { return items; }
                set { SetProperty(ref items, value); }
            }
    
            public MainWindowViewModel()
            {
                Items = new ObservableCollection<Tuple<string, int>>()
                {
                    new Tuple<string, int>("This is normal message",0),
                    new Tuple<string, int>("This is success message",1),
                    new Tuple<string, int>("This is error message",2),
                };
            }
    
            public void AddItems()
            {
                Items.Add(new Tuple<string, int> ("This is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long message", 1));
            }
        }
    }
相关推荐
多巴胺耐受15 小时前
【WPF】炫酷的科技报警弹窗
科技·c#·wpf
Xin_ye1008618 小时前
C# 零基础到精通教程 - WPF 专题二:数据绑定与 MVVM
开发语言·c#·wpf
Xin_ye1008618 小时前
C# 零基础到精通教程 - WPF 专题一:WPF 入门与 XAML 基础
c#·wpf
qq_4312807018 小时前
生成解决方案将文件生成到根目录或指定文件夹下
wpf
周杰伦fans2 天前
掌握 MVVM Light:.NET 桌面应用开发的 MVVM 利器,掌握 ObservableObject、RelayCommand 和 Messenger
c#·wpf
Ws_2 天前
WPF 面试题 + 参考答案,偏 C# 桌面端开发高频。
开发语言·c#·wpf
LCG元2 天前
现代Web应用高可用架构设计与性能调优实战
前端·wpf
小二·3 天前
向量数据库深度对比:PGVector vs Qdrant vs Milvus vs Chroma(附性能测试数据)
数据库·wpf·milvus
周杰伦fans4 天前
WPF TextBlock 中 Run 元素实战——从密码强度检测到 MVVM 绑定
wpf
largecode4 天前
座机号码认证如何操作?申请热线实名名片,树立统一官方客服形象
linux·sql·华为·c#·.net·wpf·harmonyos