none
Automatisches Skalieren von Inhalt in einer RichTextBox/TextBox RRS feed

  • Frage

  • Ich habe folgendes Problem:

    Ich möchte eine RichTextBox in einem UserControl so erweitern, dass der Inhalt der RichTextBox bestmöglichst skaliert, so dass keine Scrollbalken erscheinen und auch keine Änderungen an dem Inhalt notwendig sind (z.B. Fontgrößen, Einzug).

    Zu diesem Thema gab es bereits in einigen Foren fragen, allerdings bezogen sich die Autoren darauf, dass der User selbst den entsprechenden Zoom-Faktor wählt (mittels Slider). Woran ich arbeite ist eine automatische Berechnung des entsprechenden Scalings, damit der komplette Inhalt in der RichTextBox Platz findet.

    Der aktuelle Stand sieht folgendermaßen aus:

    Ich habe die ControlTemplate der RichTextBox so modifiziert, dass der innere AdornerDecorator ein LayoutTransform vom Typ ScaleTransform hat. Das ganze wird von einem ScrollViewer gehalten, so dass ich im Code-Behind auf entsprechende Höhenänderungen reagieren kann.

    Wenn der Inhalt kleiner als der verfügbare Platz der RTB ist, soll der Inhalt zunächst nicht scalen. Sobald allerdings die Größe des Inhalts den ViewPort überragt, möchte ich mit dem Scaling-Parameter entsprechend eingreifen.

    Das funktioniert solange ganz gut, bis wir es mit Text zutun haben der entsprechenden "wrappt", da kein Zeilenumbruch eingeschoben wurde (mit anderen Worten Fließtext). Dieser forciert (da ich sowohl X als auch Y Scale gleichmäßig verändern möchte), dass die Größe des Inhalts wiederum modifiert wird, da nun evtl. einige zusätzliche Zeilen durch den neuvorhandenen Platz nicht mehr benötigt werden.

    Ich habe an dieser Stelle mal ein kurzes Demo aufgesetzt und hoffe, das klar wird, was ich machen möchte. Vielleicht hat jemand eine Idee?

    <Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <ScaleTransform x:Key="ScaleTransform" ScaleY="{Binding ScaleFactor}"
                                               ScaleX="{Binding ScaleFactor}"/>
    </Window.Resources>
    <Grid>
        <RichTextBox AcceptsTab="True" 
                     Background="Transparent" 
                     BorderBrush="Transparent" 
                     VerticalScrollBarVisibility="Auto"
                     HorizontalScrollBarVisibility="Disabled"
                     HorizontalAlignment="Stretch" 
                     VerticalAlignment="Stretch">
            <RichTextBox.Template>
                <ControlTemplate TargetType="{x:Type TextBoxBase}">
                    <Border CornerRadius="2" 
                            Background="{TemplateBinding Background}" 
                            BorderThickness="{TemplateBinding BorderThickness}" 
                            BorderBrush="{TemplateBinding BorderBrush}">
                        <ScrollViewer ScrollChanged="ScrollViewer_ScrollChanged">
                            <AdornerDecorator x:Name="PART_ContentHost" Focusable="False"
                                              LayoutTransform="{StaticResource ScaleTransform}"/>
                        </ScrollViewer>
                    </Border>
                </ControlTemplate>
            </RichTextBox.Template>
        </RichTextBox>
    </Grid>
    
    

    Der zugehörige Codebehind:

    public partial class Window1 : Window, INotifyPropertyChanged
    {
        public Window1()
        {
            InitializeComponent();
            this.DataContext = this;
        }
    
        private double scaleFactor = 1.0;
        public double ScaleFactor
        {
            get { return scaleFactor; }
            set
            {
                scaleFactor = value;
                OnPropertyChanged("ScaleFactor");
            }
        }
    
        private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if (e.ExtentHeightChange == 0)
                return;
    
            if (e.Source.GetType() == typeof(RichTextBox))
                return;
    
            var missingHeight = e.ExtentHeightChange;
            var heightWithoutScaling = e.ExtentHeight / ScaleFactor;
    
            if (e.ViewportHeight <= heightWithoutScaling)
            {
                ScaleFactor = ((e.ViewportHeight / heightWithoutScaling));
            }
    
        }
    
        #region INotifyPropertyChanged Members
    
        /// <summary>
        /// Raised when a property on this object has a new value
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
    
        /// <summary>
        /// Raises this object's PropertyChanged event.
        /// </summary>
        /// <param name="propertyName">The property that has a new value.</param>
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(this, e);
            }
        }
    
        #endregion
    
    

    Donnerstag, 24. November 2011 14:20