Fitting Lines to Fill Available Space

Answered Fitting Lines to Fill Available Space

  • mercredi 6 septembre 2006 22:10
     
     

    Hi,

     

    I would like to be able to have a line be able to fit to the available height. For example,

     

    <StackPanel Background="SlateGray" Height="100" Width="100">

    <Line X1="50" X2="50" Y1="0" Y2="100" Stroke="Yellow" StrokeThickness ="5" StrokeDashArray="3,3" />

    </StackPanel>

     

    But without having to specify the Y2 value. Clearly, in this simple case I could bind to the parent width, but I would like to have it do it automatically.

     

    Does anyone know of a way to do this?

     

    Thanks!

Toutes les réponses

  • mercredi 6 septembre 2006 22:23
    Modérateur
     
     Traitée
    Binding seems to be the best way
  • mercredi 6 septembre 2006 22:39
     
     

    Thanks, but I would really like to find a way to do it so I don't have to bind it, even if it isn't the "best" way. Rectangles automatically expand, and you could bind their sizes too...

    Any ideas?

     

    Thanks!

  • jeudi 7 septembre 2006 00:53
     
     Traitée

    Your intuition is right. There is a better way. You need to set the Stretch property of the Line to "Fill":

    <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <Grid Background="SlateGray" Height="200" Width="100">

    <Line X1="0" X2="0" Stretch="Fill" Y1="0" Y2="1" Stroke="Yellow" StrokeThickness ="5" StrokeDashArray="3,3" />

    </Grid>
    </Page>

    Note that due to the layout properties of StackPanel, you actually need something like a Grid to do vertical stretching. Horizontal stretching (X1="0" X2="1" Y1="0" Y2="1" works as you'd expect, though).

     

  • jeudi 7 septembre 2006 17:25
     
     

    Sweeeetness! Very Very Cool. Thanks Anthony!

    Now for the untimate question...I have a panel with custom logic that I need to add these to. How can I implement the layout properties of Grid in my own panel? (Note that I need to inherit my panel from an existing custom panel class, which inherits from Panel, so directly inheriting from Grid will not work.)

    Thanks!

    [Edit: I meant the layout properties of Grid, not StackPanel (I got it backwards in my original reply). I think this says what I mean now... :-) ]

  • jeudi 7 septembre 2006 21:21
     
     Traitée

    The key methods that you want to investigate are MeasureOverride and ArrangeOverride -- these determine how a FrameworkElement divies up space to its children. A very simple implementation would be:

    public class MyPanel : Panel
    {
        // Default public constructor
        public MyPanel()
            : base()
        {
        }

        // Override the default Measure method of Panel
        protected override Size MeasureOverride(Size availableSize)
        {
            Size childSize = availableSize;
            foreach (UIElement child in InternalChildren)
            {
                child.Measure(childSize);
            }
            return availableSize;
        }
        protected override Size ArrangeOverride(Size finalSize)
        {
            foreach (UIElement child in InternalChildren)
            {
                child.Arrange(new Rect(finalSize));
            }
            return finalSize; // Returns the final Arranged size
        }
    }

    By the way: if you use thick pens (try setting StrokeThickness = 10) you'll notice that the line doesn't quite go across the entire container and there'll be little gaps on either side. This is because we leave room for line caps, whether they are present or not. Try setting the StrokeStartLineCap and StrokeEndLineCap properties to "Square" to get rid of these.

    For more information, check out the following links:

    http://windowssdk.msdn.microsoft.com/en-us/library/system.windows.frameworkelement.measureoverride.aspx
    http://windowssdk.msdn.microsoft.com/en-us/library/system.windows.frameworkelement.arrangeoverride.aspx

    http://windowssdk.msdn.microsoft.com/en-us/library/ms771626.aspx

  • jeudi 7 septembre 2006 21:33
     
     

    Thanks for the note about the line caps...I didn't know about that.

    I have written custom panels already, though, and have tinkered with trying to allow the lines to fit to the page (as the grid does), but I haven't figured out how to do that -- all my panels lay out like the stackpanel, and I can't figure out how to mimic the Grid's effect. Is there anywhere you can point me to on that note?

     

    Thanks!

  • jeudi 7 septembre 2006 22:28
     
     Traitée

    The MeasureOverride/ArrangeOverride I specify in my previous post should give the line-stretching behavior you're looking for.

  • vendredi 8 septembre 2006 00:34
     
     Traitée

    Sure enough.

    The trick that I wasn't seeing was the call to child.Arrange with a specifically fixed size (i.e. "finalSize"). I had always been calling it with "new Size(Double.PositiveInfinity, Double.PositiveInfinity)". It isn't intuitive, but the latter prevents lines from stretching; I assume that is because it Line.Arrange doesn't know what to stretch them to when given infinite room.

    My reason was to use my panel to allow children to be as large as they wanted. However, with enough juggling sizes around, I was able to use my panel for both.

    Thanks so much for your help!

     

    P.S. Your code actually will crash if given infinite room (e.g. placed in a scrollviewer). The reason is because elements cannot return infinity from a call to measure or arrange, and your code just returns whatever it is given. I figure you know that, but I thought I would mention it in case someone else wonders...

  • vendredi 8 septembre 2006 00:52
     
     Traitée

    Glad you got it working. I meant to explicitly mention the PositiveInfinity stuff in my previous post, but it looks like I didn't . You're absolutely right that the Line element defaults back to its "natural size" when it encounters an infinite dimension.

    W.R.T the crashing bug: Touche. I was actually just grabbing code from the SDK and tweaking it, and the bug remained. I'll forward your comments on to the SDK guys. Thanks!