locked
Scalable Control with paths RRS feed

  • Question

  • Hey there,

    Firstly I'm sorry if this is in the wrong place or has been answered before. I've failed to find what I need.

    I'm using blend to create a custom button. I first create an ellipse, which I then convert to a button and delete the contentpresenter. I then instead use two paths to represent down arrows. (It's a button for record movements).The problem I have is that the paths have defined height and widths, which pose a serious problem for scalability.

    How can I achieve a scalable, ellipsical button with paths in blend? I want animations on the paths too - which I've done. I just can't get it to scale.

    Rehards,

    Jib

    Wednesday, March 5, 2014 8:24 PM

Answers

  • Here are the steps I would use:

    1. Set a height/width on the containing grid, in your case it was currently 129.96x276
    2. Remove height/width from the ellipse, now the ellipse is sized by the containing grid (so it can be scaled, everything is going to be scaled by the containing grid)
    3. To make the scaling simpler, I would change the paths to not have a render transform, so your path data would become: M52,0 L104,47 0,47 z
    4. Adjust the gradient with the gradient too to get the look you want
    5. Set the path to Stretch="Uniform" and set margins appropriately so it looks correct

    The resulting xaml as a starting point to see if it meets your needs:

    		<Grid x:Name="LayoutRoot" Height="129.96" VerticalAlignment="Top" Width="276">
    			<Ellipse >
    				<Ellipse.Fill>
    					<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    						<GradientStop Color="#FF6685BB" Offset="0.198"/>
    						<GradientStop Color="#FF2F5AA4" Offset="1"/>
    					</LinearGradientBrush>
    				</Ellipse.Fill>
    			</Ellipse>
    			<Path Data="M52,0 L104,47 0,47 z" Stroke="White" StrokeThickness="3" Stretch="Uniform" Margin="90,10,81,46"	>
    				<Path.Fill>
    					<LinearGradientBrush EndPoint="0.531,-0.122" StartPoint="0.05,0.454">
    						<GradientStop Color="#FF6685BB" Offset="0.115"/>
    						<GradientStop Color="#FF2F5AA4" Offset="0.79"/>
    					</LinearGradientBrush>
    				</Path.Fill>
    			</Path>
    			<Path Data="M52,0 L104,47 0,47 z" Stroke="White" StrokeThickness="3" Stretch="Uniform" Margin="90,33,81,29"	>
    				<Path.Fill>
    					<LinearGradientBrush EndPoint="0.531,-0.122" StartPoint="0.05,0.454">
    						<GradientStop Color="#FF6685BB" Offset="0.115"/>
    						<GradientStop Color="#FF2F5AA4" Offset="0.79"/>
    					</LinearGradientBrush>
    				</Path.Fill>
    			</Path>
    		</Grid>

    • Marked as answer by Jibrohni Friday, March 7, 2014 1:40 PM
    Thursday, March 6, 2014 3:03 PM
    Moderator
  • I see, when you scale it to a very small size they disappear. Here is some code that uses grid rows/cols to control the size of the paths, you can modify the relative sizes of the grid rows/cols to change the arrow sizes:

    <Grid x:Name="LayoutRoot" Height="119.986" VerticalAlignment="Top" Margin="120.5,0,144.076,0">
            			<Grid.RowDefinitions>
            				<RowDefinition Height="1*"/>
            				<RowDefinition Height=".6*"/>
            				<RowDefinition Height="1.6*"/>
    						<RowDefinition Height=".6*"/>
            				<RowDefinition Height="1*"/>
            			</Grid.RowDefinitions>
            			<Grid.ColumnDefinitions>
            				<ColumnDefinition Width="1*"/>
            				<ColumnDefinition Width="2*"/>
            				<ColumnDefinition Width="1*"/>
            			</Grid.ColumnDefinitions>
    			<Ellipse Grid.ColumnSpan="3" Grid.RowSpan="5" >
    				<Ellipse.Fill>
    					<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    						<GradientStop Color="#FF6685BB" Offset="0.198"/>
    						<GradientStop Color="#FF2F5AA4" Offset="1"/>
    					</LinearGradientBrush>
    				</Ellipse.Fill>
    			</Ellipse>
    			<Path Data="M52,0 L104,47 0,47 z" Stroke="White" StrokeThickness="3" Stretch="Uniform" Grid.Column="1" Grid.Row="1" Grid.RowSpan="2"	>
    				<Path.Fill>
    					<LinearGradientBrush EndPoint="0.531,-0.122" StartPoint="0.05,0.454">
    						<GradientStop Color="#FF6685BB" Offset="0.115"/>
    						<GradientStop Color="#FF2F5AA4" Offset="0.79"/>
    					</LinearGradientBrush>
    				</Path.Fill>
    			</Path>
    			<Path Data="M52,0 L104,47 0,47 z" Stroke="White" StrokeThickness="3" Stretch="Uniform" Grid.Column="1" Grid.Row="2" Grid.RowSpan="2">
    				<Path.Fill>
    					<LinearGradientBrush EndPoint="0.531,-0.122" StartPoint="0.05,0.454">
    						<GradientStop Color="#FF6685BB" Offset="0.115"/>
    						<GradientStop Color="#FF2F5AA4" Offset="0.79"/>
    					</LinearGradientBrush>
    				</Path.Fill>
    			</Path>
    		</Grid>

    • Marked as answer by Jibrohni Monday, March 10, 2014 3:16 PM
    Monday, March 10, 2014 2:07 PM
    Moderator

All replies

  • You should remove the height/width and have the size set by margins.

    1. Remove height="", width=""
    2. Set HorizontalAlignment and VerticalAlignment to stretch
    3. Set the margins as appropriate

    Does that do what you want?

    Wednesday, March 5, 2014 9:44 PM
    Moderator
  • Chuck,

    It's probably easier if I just post you the control:

    <Grid x:Name="LayoutRoot">
    		<Ellipse HorizontalAlignment="Left" Height="129.96" VerticalAlignment="Top" Width="276">
    			<Ellipse.Fill>
    				<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    					<GradientStop Color="#FF6685BB" Offset="0.198"/>
    					<GradientStop Color="#FF2F5AA4" Offset="1"/>
    				</LinearGradientBrush>
    			</Ellipse.Fill>
    		</Ellipse>
    		<Path HorizontalAlignment="Left" Height="71.338" Margin="92,59.268,0,0" Stroke="White" StrokeThickness="3" VerticalAlignment="Top" Width="93.536" RenderTransformOrigin="0.485,0.533" Data="M94.5,2.5 L75.305182,68.838335 5.9639838,55.50006 z" Stretch="Fill">
    			<Path.RenderTransform>
    				<TransformGroup>
    					<ScaleTransform/>
    					<SkewTransform/>
    					<RotateTransform Angle="-150"/>
    					<TranslateTransform X="10.94" Y="-34.11"/>
    				</TransformGroup>
    			</Path.RenderTransform>
    			<Path.Fill>
    				<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    					<GradientStop Color="#FF6685BB" Offset="0.198"/>
    					<GradientStop Color="#FF2F5AA4" Offset="1"/>
    				</LinearGradientBrush>
    			</Path.Fill>
    		</Path>
    		<Path HorizontalAlignment="Left" Height="71.338" Margin="92,38.268,0,0" Stroke="White" StrokeThickness="3" VerticalAlignment="Top" Width="93.536" RenderTransformOrigin="0.485,0.533" Data="M94.5,2.5 L75.305182,68.838335 5.9639838,55.50006 z" Stretch="Fill">
    			<Path.RenderTransform>
    				<TransformGroup>
    					<ScaleTransform/>
    					<SkewTransform/>
    					<RotateTransform Angle="-150"/>
    					<TranslateTransform X="10.941" Y="7.889"/>
    				</TransformGroup>
    			</Path.RenderTransform>
    			<Path.Fill>
    				<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    					<GradientStop Color="#FF6685BB" Offset="0.198"/>
    					<GradientStop Color="#FF2F5AA4" Offset="1"/>
    				</LinearGradientBrush>
    			</Path.Fill>
    		</Path>
    	</Grid>

    That's just within a usercontrol. The set sizes, especially for the paths are causing all sorts of grief.

    Regards,

    Jib

    Thursday, March 6, 2014 8:30 AM
  • I'm not really sure how I can achieve these paths using margins etc.
    Thursday, March 6, 2014 1:19 PM
  • Here are the steps I would use:

    1. Set a height/width on the containing grid, in your case it was currently 129.96x276
    2. Remove height/width from the ellipse, now the ellipse is sized by the containing grid (so it can be scaled, everything is going to be scaled by the containing grid)
    3. To make the scaling simpler, I would change the paths to not have a render transform, so your path data would become: M52,0 L104,47 0,47 z
    4. Adjust the gradient with the gradient too to get the look you want
    5. Set the path to Stretch="Uniform" and set margins appropriately so it looks correct

    The resulting xaml as a starting point to see if it meets your needs:

    		<Grid x:Name="LayoutRoot" Height="129.96" VerticalAlignment="Top" Width="276">
    			<Ellipse >
    				<Ellipse.Fill>
    					<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    						<GradientStop Color="#FF6685BB" Offset="0.198"/>
    						<GradientStop Color="#FF2F5AA4" Offset="1"/>
    					</LinearGradientBrush>
    				</Ellipse.Fill>
    			</Ellipse>
    			<Path Data="M52,0 L104,47 0,47 z" Stroke="White" StrokeThickness="3" Stretch="Uniform" Margin="90,10,81,46"	>
    				<Path.Fill>
    					<LinearGradientBrush EndPoint="0.531,-0.122" StartPoint="0.05,0.454">
    						<GradientStop Color="#FF6685BB" Offset="0.115"/>
    						<GradientStop Color="#FF2F5AA4" Offset="0.79"/>
    					</LinearGradientBrush>
    				</Path.Fill>
    			</Path>
    			<Path Data="M52,0 L104,47 0,47 z" Stroke="White" StrokeThickness="3" Stretch="Uniform" Margin="90,33,81,29"	>
    				<Path.Fill>
    					<LinearGradientBrush EndPoint="0.531,-0.122" StartPoint="0.05,0.454">
    						<GradientStop Color="#FF6685BB" Offset="0.115"/>
    						<GradientStop Color="#FF2F5AA4" Offset="0.79"/>
    					</LinearGradientBrush>
    				</Path.Fill>
    			</Path>
    		</Grid>

    • Marked as answer by Jibrohni Friday, March 7, 2014 1:40 PM
    Thursday, March 6, 2014 3:03 PM
    Moderator
  • TREMENDOUS!!!! That is spot on, thank you very much.

    Out of interest how did you go about creating that? Did you use Blend or did you just create those paths yourself?

    Thanks again,

    Jib

    Friday, March 7, 2014 1:40 PM
  • I created the path data by hand, I took the points from yours, figured out the lengths of the sides of the triangle and drew it on paper, sometimes low tech works the best.
    Friday, March 7, 2014 2:35 PM
    Moderator
  • Ah, makes sense. I'm very grateful.
    Friday, March 7, 2014 4:18 PM
  • Just testing it and the margins cause the scaling to fail sadly...
    Friday, March 7, 2014 4:41 PM
  • It scaled for me, what is it doing/not doing that isn't correct? Screenshots might help.
    Friday, March 7, 2014 5:09 PM
    Moderator
  • So the image shows two buttons (the original on the right, and the one you created on the left). It's housed within a dockpanel and renders fine in the usercontrol:

    With RecordButtonUp.xaml being a usercontrol.

    Regards,

    Jib

    Monday, March 10, 2014 10:20 AM
  • I see, when you scale it to a very small size they disappear. Here is some code that uses grid rows/cols to control the size of the paths, you can modify the relative sizes of the grid rows/cols to change the arrow sizes:

    <Grid x:Name="LayoutRoot" Height="119.986" VerticalAlignment="Top" Margin="120.5,0,144.076,0">
            			<Grid.RowDefinitions>
            				<RowDefinition Height="1*"/>
            				<RowDefinition Height=".6*"/>
            				<RowDefinition Height="1.6*"/>
    						<RowDefinition Height=".6*"/>
            				<RowDefinition Height="1*"/>
            			</Grid.RowDefinitions>
            			<Grid.ColumnDefinitions>
            				<ColumnDefinition Width="1*"/>
            				<ColumnDefinition Width="2*"/>
            				<ColumnDefinition Width="1*"/>
            			</Grid.ColumnDefinitions>
    			<Ellipse Grid.ColumnSpan="3" Grid.RowSpan="5" >
    				<Ellipse.Fill>
    					<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    						<GradientStop Color="#FF6685BB" Offset="0.198"/>
    						<GradientStop Color="#FF2F5AA4" Offset="1"/>
    					</LinearGradientBrush>
    				</Ellipse.Fill>
    			</Ellipse>
    			<Path Data="M52,0 L104,47 0,47 z" Stroke="White" StrokeThickness="3" Stretch="Uniform" Grid.Column="1" Grid.Row="1" Grid.RowSpan="2"	>
    				<Path.Fill>
    					<LinearGradientBrush EndPoint="0.531,-0.122" StartPoint="0.05,0.454">
    						<GradientStop Color="#FF6685BB" Offset="0.115"/>
    						<GradientStop Color="#FF2F5AA4" Offset="0.79"/>
    					</LinearGradientBrush>
    				</Path.Fill>
    			</Path>
    			<Path Data="M52,0 L104,47 0,47 z" Stroke="White" StrokeThickness="3" Stretch="Uniform" Grid.Column="1" Grid.Row="2" Grid.RowSpan="2">
    				<Path.Fill>
    					<LinearGradientBrush EndPoint="0.531,-0.122" StartPoint="0.05,0.454">
    						<GradientStop Color="#FF6685BB" Offset="0.115"/>
    						<GradientStop Color="#FF2F5AA4" Offset="0.79"/>
    					</LinearGradientBrush>
    				</Path.Fill>
    			</Path>
    		</Grid>

    • Marked as answer by Jibrohni Monday, March 10, 2014 3:16 PM
    Monday, March 10, 2014 2:07 PM
    Moderator
  • Chuck,

    Thanks again. The only change I had to make was to wrap the grid in a Viewbox which handles the re-sizing:

    <Viewbox>
            <Grid x:Name="LayoutRoot" VerticalAlignment="Top">
            <Ellipse >
                <Ellipse.Fill>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#FF6685BB" Offset="0.198"/>
                        <GradientStop Color="#FF2F5AA4" Offset="1"/>
                    </LinearGradientBrush>
                </Ellipse.Fill>
            </Ellipse>
            <Path Data="M52,0 L104,47 0,47 z" Stroke="White" StrokeThickness="3" Stretch="Uniform" Margin="90,10,81,46"	>            
                <Path.Fill>
                    <LinearGradientBrush EndPoint="0.531,-0.122" StartPoint="0.05,0.454">
                        <GradientStop Color="#FF6685BB" Offset="0.115"/>
                        <GradientStop Color="#FF2F5AA4" Offset="0.79"/>
                    </LinearGradientBrush>
                </Path.Fill>
            </Path>
            <Path Data="M52,0 L104,47 0,47 z" Stroke="White" StrokeThickness="3" Stretch="Uniform" Margin="90,33,81,29"	>
                <Path.Fill>
                    <LinearGradientBrush EndPoint="0.531,-0.122" StartPoint="0.05,0.454">
                        <GradientStop Color="#FF6685BB" Offset="0.115"/>
                        <GradientStop Color="#FF2F5AA4" Offset="0.79"/>
                    </LinearGradientBrush>
                </Path.Fill>
            </Path>
        </Grid>
        </Viewbox>

    Monday, March 10, 2014 3:15 PM