none
CustomControl Panel per CalendarControl RRS feed

  • Domanda

  • Ciao a tutti,
    mi stò avvicinando alla programmazione WPF dopo aver già realizzato alcune applicazioni WinForms...Spero quindi che mi scusiate se scriverò qualche stupidaggine! Ho preso spunto da un CustomControl realizzato da e che potete vedere _QUI_

    Il CustomControl eredita da Panel, quindi permette di disporre al suo interno altri Elementi Figli...Questi Children dovranno occupare un'area proporzionale alla dimensione del Controllo Padre (il Panel appunto).

    Il Controllo funziona! Ma ha un piccolo problema che non riesco a risolvere...

    L'esempio lo allego qui sotto, e lo potete scaricare completo _QUI_, ha una serie di funzionalità ridotte rispetto al progetto originale dell'Autore ma racchiude le sole funzionalità importanti per capire il problema.

    La struttura di esempio è quella che scrivo qui di seguito in pseudo-XAML:

    <RangePanel MINIMUM=0 MAXIMUM=100 ORIENTATION=HORIZONTAL>
       <Border RANGEPANEL.BEGIN=10 RANGEPANEL.END=20>
           <TextBlock ... />
       </Border>
       <Border RANGEPANEL.BEGIN=40 RANGEPANEL.END=60>
           <TextBlock ... />
       </Border>
       <Border RANGEPANEL.BAGIN=80 RANGEPANEL.END=90>
           <TextBlock ... />
       </Border>
    </RangePanel>

    In pratica il RangePanel ha proprietà MINIMUM e MAXIMUN che servono come riferimento... Le dimensioni dei BORDER contenuti nel Panel (i Children) avranno larghezza proporzionale rispetto al Panel secondo le loro proprietà BEGIN END (vedi immagine sotto)...

    Windows larger: Border and text correctly rendered!

    IL PROBLEMA:

    Diciamo che funziona tutto fintanto che non inserisco una TEXTBLOCK all'interno del BORDER...

    Se il testo è abbastanza LUNGO oppure il BORDER è MOLTO STRETTO (il border avrà dimensioni proporzionali al Panel in base alle sue proprietà BEGIN ed END impostate in XAML quindi restringendo la finestra la dimensione dei border si riduce in proporzione) io mi aspetterei che il testo scompaia dietro al border (situazione corretta) ed invece: è il border che viene tagliato!!! (vedi immagine sotto ottenuta dalla precedente restringendo la finestra). Il fatto che viene tagliato si nota molto bene guardando i RAGGI destri del border....

    Windows too small: BORDER CROP and TEXT correctly truncated!!

    Non so come fare in modo che il BORDER si ridimensioni correttamente rimanendo TUTTO visibile ed il testo vada a nascondersi dentro al border....

    Questa altra immagine che trovate _QUI_ forse aiuta a capire ancora meglio...

    E' forse un problema XAML?? O forse sbaglio qualcosa nei metodi ArrangeOverride e MeasureOverride...??

    Ho già provato sia a cambiare il BORDER con altri controlli più complessi (grid, rectangle....ecc, ho provato anche con varie combinazioni delle proprietà Clip...ecc ma NULLA). Ho provato anche a fare alcune modifiche alle Function ArrangeOverride(size...) e MeasureOverride ma ancora nulla.

    Ecco il codice sorgente sia del controllo che della Windows che contiene il RangePanel ed i relativi figli...

    RangePanelWindow.xaml:

    <Window xmlns:controls="clr-namespace:WpfCalendar.Windows.Controls"  
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Horizontal Range Panel Window" Height="300" Width="300">
    
        <controls:RangePanel Minimum="1" Maximum="100" Orientation="Horizontal">
            <Border BorderBrush="Blue" BorderThickness="1,1,1,1" controls:RangePanel.Begin="10" controls:RangePanel.End="20" CornerRadius="5">
                <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="LONG TEXT" Background="#FF99AFF8" />
            </Border>
            <Border BorderBrush="Red" BorderThickness="1,1,1,1" controls:RangePanel.Begin="45" controls:RangePanel.End="60" CornerRadius="5">
                <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="Short" Background="#FFFF6969" />
            </Border>
            <Border BorderBrush="Orange" BorderThickness="1,1,1,1" controls:RangePanel.Begin="75" controls:RangePanel.End="95" CornerRadius="5">
                <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="Long Long Long Long text" Background="#FFFFE13E" />
            </Border>
        </controls:RangePanel>
    </Window>


    RangePanel.cs:

    using System.Windows;
    using System.Windows.Controls;
    
    namespace WpfCalendar.Windows.Controls {
        public class RangePanel : Panel {
            public static DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(RangePanel), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsArrange));
            public static DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(RangePanel), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.AffectsArrange));
            public static DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(RangePanel), new FrameworkPropertyMetadata(Orientation.Vertical, FrameworkPropertyMetadataOptions.AffectsArrange));
            public static DependencyProperty BeginProperty = DependencyProperty.RegisterAttached("Begin", typeof(double), typeof(UIElement), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsArrange));
            public static DependencyProperty EndProperty = DependencyProperty.RegisterAttached("End", typeof(double), typeof(UIElement), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.AffectsArrange));
    
            public static void SetBegin(UIElement element, double value) {
                element.SetValue(BeginProperty, value);
            }
    
            public static double GetBegin(UIElement element) {
                return (double)element.GetValue(BeginProperty);
            }
    
            public static void SetEnd(UIElement element, double value) {
                element.SetValue(EndProperty, value);
            }
    
            public static double GetEnd(UIElement element) {
                return (double)element.GetValue(EndProperty);
            }
    
            public double Maximum {
                get { return (double)this.GetValue(MaximumProperty); }
                set { this.SetValue(MaximumProperty, value); }
            }
    
            public double Minimum {
                get { return (double)this.GetValue(MinimumProperty); }
                set { this.SetValue(MinimumProperty, value); }
            }
    
            public Orientation Orientation {
                get { return (Orientation)this.GetValue(OrientationProperty); }
                set { this.SetValue(OrientationProperty, value); }
            }
    
            protected override Size ArrangeOverride(Size finalSize) {
                double containerRange = (this.Maximum - this.Minimum);
    
                foreach (UIElement element in this.Children) {
                    double begin = (double)element.GetValue(RangePanel.BeginProperty);
                    double end = (double)element.GetValue(RangePanel.EndProperty);
                    double elementRange = end - begin;
    
                    Size size = new Size();
                    size.Width = (Orientation == Orientation.Vertical) ? finalSize.Width : elementRange / containerRange * finalSize.Width;
                    size.Height = (Orientation == Orientation.Vertical) ? elementRange / containerRange * finalSize.Height : finalSize.Height;
    
                    Point location = new Point();
                    location.X = (Orientation == Orientation.Vertical) ? 0 : (begin - this.Minimum) / containerRange * finalSize.Width;
                    location.Y = (Orientation == Orientation.Vertical) ? (begin - this.Minimum) / containerRange * finalSize.Height : 0;
    
                    element.Arrange(new Rect(location, size));
                }
                return finalSize;
            }
    
            protected override Size MeasureOverride(Size availableSize) {
                foreach (UIElement element in this.Children) {
                    element.Measure(availableSize);
                }
                return availableSize;
            }
        }
    }


    Grazie in anticipo per la disponibilità...

     

    • Modificato Andrea Re lunedì 6 maggio 2013 07:54 Correzione al codice.
    giovedì 7 giugno 2012 18:06