Silverlight 4 - FontSize automatisch skalieren



  • Hallo,

    ist es möglich, die FontSize eines TextBlocks bzw. einer TextBox automatisch zu skalieren? Bisher fange ich immer das SizeChanged Event des ParentWindows ab und errechne mir so die neue FontSize. Gibt es da einen eleganteren Weg?



  • Wenn du weißt wie groß dein Text ist (Höhe, Breite) kannst auch versuchen zu Zoomen also RenderTranformation mit ScaleTransform entsprehend belegen. Dazu könnte ein eigenes Control sehr nützlich sein. (AutoZoomBoxPanel-z.B.) das geht dann auch mit siverlight 2.0

    Edit: +++Zoom



  • Also ich hatte mir sowas vorgestellt:

    public class FontScaleBehavior : Behavior<TextBlock>
    {
        protected Size _OldSize = new Size();
    
        protected override void OnAttached()
        {
            base.OnAttached();
    
            this._OldSize.Width  = (AssociatedObject.Parent as FrameworkElement).ActualWidth;
            this._OldSize.Height = (AssociatedObject.Parent as FrameworkElement).ActualHeight;
            (AssociatedObject as TextBlock).SizeChanged += this.Object_SizeChanged;
        }
    
        protected override void OnDetaching()
        {
            base.OnDetaching();
            (AssociatedObject as TextBlock).SizeChanged -= this.Object_SizeChanged;
        }
    
        protected void Object_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            uint Old = (uint)this._OldSize.Height + (uint)this._OldSize.Width,
                 New = (uint)e.NewSize.Height + (uint)e.NewSize.Width;
    
            (AssociatedObject as TextBlock).FontSize *= New / Old;  
            this._OldSize = e.NewSize;
        }
    }
    
    <TextBlock Text="TextBlock">
    	<i:Interaction.Behaviors>
    		<AutoFontScale:FontScaleBehavior/>  
    	</i:Interaction.Behaviors>
    </TextBlock>
    

    Allerdings startet so nie die Website; scheint also etwas falsch an meiner herangehensweiße zu sein.

    EDIT:
    Es liegt daran, dass das AssociatedObject als Parent immer "null" hat, obwohl ads eigentlich nicht sein kann. Offensichtlich wird das Parent Property nicht an AssociatedObject weitergegeben ... sehr merkwürdig wie ich finde.



  • public class FontScaleBehavior : Behavior<Panel>
    {
        protected Size _OldSize = new Size();
        protected List<TextBlock> _Childs = new List<TextBlock>();
        protected bool _FirstTime = true;
    
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.SizeChanged += this.Object_SizeChanged;
        }
    
        protected override void OnDetaching()
        {
            this.AssociatedObject.SizeChanged -= this.Object_SizeChanged;
            base.OnDetaching();
        }
    
        protected void Object_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (this._FirstTime)
            {
                foreach (var child in this.AssociatedObject.Children)
                {
                    if (child is TextBlock)
                        this._Childs.Add(child as TextBlock);
                }
    
                this._OldSize.Width = this.AssociatedObject.ActualWidth;
                this._OldSize.Height = this.AssociatedObject.ActualHeight;
                this._FirstTime = false;
            }
            else
            {
                double factor = (e.NewSize.Height + e.NewSize.Width) / (this._OldSize.Height + this._OldSize.Width);  
    
                foreach (TextBlock obj in this._Childs)
                    obj.FontSize *= factor;
    
                this._OldSize = e.NewSize;
            }
        }
    }
    

    So habe ich es nun gelöst. Etwas schade ist, dass die Templates in C# nicht so schön funktionieren, wie in C++. Leider muss man T schon grob einen Typ zuordnen (z.B. where T : UserControl).

    Ich hätte das gut gebrauchen können, da auch die TextBox ihren Font automatisch skalieren soll. Wenn da jemand noch eine Möglichkeit kennt, wäre ich ihm dankbar. Da TextBox und TextBlock jedoch unterschiedliche Generalisierungen haben sehe ich da bisher keine Möglichkeit, außer noch eine Liste mit TextBox-Elementen zu führen.



  • Edit: Shullbit - hier stand was dummes

    @ FrEEzE2046 - wie wäre es mit zwei Behaiours nur eines für eine TextBox und die andere für TextBlock?



  • Rhombicosidodecahedron schrieb:

    @ FrEEzE2046 - wie wäre es mit zwei Behaiours nur eines für eine TextBox und die andere für TextBlock?

    Wäre sicherlich der korrektere Weg. Ein Behavior für TestBox schenke ich mir, da man das mit Control gut zusammenfassen kann (inkl. Button etc.).

    Mal eine andere Frage: Ich hab einen WCF WebService mit einer Methode, deren Rückgabewert ich inzwischen geändert habe. Ich habe mehrfach die Reference auf den Service aktualisiert, aber er nimmt immer noch den alten Wert an. Was ist zu tun?


Anmelden zum Antworten