I want to set the border of a grid in a way that it's only on the top of it (this is what I've managed to do) and that it's only in the center of the top (I mean it starts about 30px from the left edge and ends also 30px from the end)
The Code I use for generating Grid (in the .cs file):
Grid NewGrid = new Grid()
{
Height = 90,
Padding = new Thickness { Left = 0, Right = 0, Top = 0, Bottom = 0 },
BorderThickness = new Thickness { Left = 0, Top = 1, Right = 0, Bottom = 0 },
BorderBrush = new SolidColorBrush(Colors.Black),
};
The image of what I want to achieve:
where the gray color is no border and the black is a visible solid border...
You can't do this with Grid.BorderBrush and Grid.BorderThickness; the border always extends to the corners of the element.
Just use a Rectangle in the first row of the Grid to achieve the border you want:
<Grid>
<Grid.RowDefinitions>
<!-- The first row is for the border only -->
<RowDefinition Height="Auto"/>
<!-- Use additional rows as your layout dictates -->
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<!-- The border element in the first row -->
<Rectangle Margin="50,0" Fill="Black" Height="2"/>
<!-- The main content of the Grid in subsequent rows -->
<Button Grid.Row="1" Content="Example 1"/>
<Button Grid.Row="2" Content="Example 2"/>
</Grid>
i think the best approach would be set no border on the Grid, but overlay a Line on top of the grid with the computed width like...
Line newLine = new Line();
{
line1.X2 = NewGrid.Width -60;
}
Related
I am creating shapes at run time on canvas in my app and except all the shapes, ellipse is going out of canvas. How do I restrict it to canvas? All other shapes are contained in canvas because of the control points at their vertices. How do I keep a check as to not let ellipse go out of canvas without clipping. I have used ClipToBounds and it doesn't meet my needs.
Also, an alternate solution is if I can add a controlpoint at the left side of ellipse of radiusX property. I can't add a controlpoint to left side of radiusX on ellipse. If you could help me with either of that?
radiusXcp = new ControlPoint(this, EllipseGeom, EllipseGeometry.RadiusYProperty, 1, true, false);
radiusXcp.RelativeTo = EllipseGeometry.CenterProperty;
shape_ControlPoints.Add(radiusXcp);
radiusXcp = new ControlPoint(this, EllipseGeom, EllipseGeometry.RadiusXProperty, 0, true, false);
radiusXcp.RelativeTo = EllipseGeometry.CenterProperty;
shape_ControlPoints.Add(radiusXcp);
//EllipseGeom.RadiusX = -EllipseGeom.RadiusX;
//radiusXcp = new ControlPoint(this, EllipseGeom, EllipseGeometry.RadiusXProperty, 0, true, false);
//radiusXcp.RelativeTo = EllipseGeometry.CenterProperty;
//shape_ControlPoints.Add(radiusXcp);
//EllipseGeom.RadiusX = -EllipseGeom.RadiusX;
Here is a quick example of what i would do. It could be improved on and the code is mainly written to be easy to read and follow. It also does not handle the possibility to if the shape's size is bigger than the Canvas (not sure if that is a use case in your project).
For the example I used the "Loaded" event on the Canvas, to reset the position before drawing. You would want this check before you draw the Ellipse object.
private void TestCanvas_Loaded(object sender, RoutedEventArgs e)
{
//canvas = 450 x 800
Ellipse test_ellipse = new Ellipse();
test_ellipse.Width = 100;
test_ellipse.Height = 100;
test_ellipse.Fill = Brushes.Red;
Canvas.SetLeft(test_ellipse, 700);
Canvas.SetTop(test_ellipse, -500);
Reset_Ellipse_Bounds(TestCanvas, ref test_ellipse);
TestCanvas.Children.Add(test_ellipse);
}
private void Reset_Ellipse_Bounds(Canvas myCanvas, ref Ellipse myEllipse)
{
var left = Canvas.GetLeft(myEllipse);
var top = Canvas.GetTop(myEllipse);
//handle too far right
if (left + myEllipse.Width > myCanvas.ActualWidth)
Canvas.SetLeft(myEllipse, myCanvas.ActualWidth - myEllipse.Width);
//handle too far left
if(left < 0)
Canvas.SetLeft(myEllipse, 0);
//handle too far up
if (top < 0)
Canvas.SetTop(myEllipse, 0);
//handle too far down
if (top + myEllipse.Height > myCanvas.ActualHeight)
Canvas.SetTop(myEllipse, myCanvas.ActualHeight - myEllipse.Height);
}
For Completeness the XAML:
<Grid>
<Canvas x:Name="TestCanvas" Loaded="TestCanvas_Loaded" />
</Grid>
The idea is to check the bounding box against the Canvas edges. There are ways to improve this, but i figured the simplest solution is easier to follow.
Within each if statement you could add more logic or a method to do further processing, but this should answer the general question of knowing if it is outside the parent.
Just set ClipToBounds="true" to its father control, it avoids the canvas to be drawn outside of it.
In my case I set it to Grid as followed :
<Grid x:Name="MainGrid" Background="WhiteSmoke" ClipToBounds="true">
<Canvas Margin="10" Background="Transparent"
SizeChanged="ViewportSizeChanged"
MouseLeftButtonDown="ViewportMouseLeftButtonDown"
MouseLeftButtonUp="ViewportMouseLeftButtonUp"
MouseMove="ViewportMouseMove"
MouseWheel="ViewportMouseWheel">
<Canvas x:Name="canvas" Width="1000" Height="600"
HorizontalAlignment="Left" VerticalAlignment="Top">
<Canvas.RenderTransform>
<MatrixTransform x:Name="transform"/>
</Canvas.RenderTransform>
</Canvas>
<Canvas x:Name="canvas2" Width="1000" Height="600"
HorizontalAlignment="Left" VerticalAlignment="Top">
<Canvas.RenderTransform>
<MatrixTransform x:Name="transform2"/>
</Canvas.RenderTransform>
</Canvas>
</Canvas>
</Grid>
I try to get two borders in one grid with c# code.
I have one Grid in xaml that looks like this:
<Grid Name="GridKalkAuswahl" ShowGridLines="False" HorizontalAlignment="Left"
Height="Auto" VerticalAlignment="Top" Width="463">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="38px"/>
<ColumnDefinition Width="16px"/>
<ColumnDefinition Width="40px"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
Now I want to insert two Borders into the Grid.
Border myborder = new Border();
myborder.BorderBrush = new SolidColorBrush(Colors.DarkGray);
myborder.BorderThickness = new Thickness(1);
GridKalkAuswahl.Children.Add(myborder);
Grid.SetRowSpan(myborder, noStaffel.Count);
Grid.SetColumnSpan(myborder, 4);
But this ist just one Border. How could i get a second one into the Grid? If I do that the same way the 2 Border are on the same place.
Thank you.
set Margin to inner border. make that Margin equal to outer border Thickness
Border myborder = new Border
{
BorderBrush = Brushes.DarkGray,
BorderThickness = new Thickness(1);
};
GridKalkAuswahl.Children.Add(myborder);
Grid.SetRowSpan(myborder, noStaffel.Count);
Grid.SetColumnSpan(myborder, 4);
Border myborder2 = new Border
{
BorderBrush = Brushes.Orange,
BorderThickness = new Thickness(1),
Margin = myborder.BorderThickness
};
GridKalkAuswahl.Children.Add(myborder2);
Grid.SetRowSpan(myborder2, noStaffel.Count);
Grid.SetColumnSpan(myborder2, 4);
"But this ist just one Border. How could i get a second one into the Grid? If I do that the same way the 2 Border are on the same place." Ofcourse they're on the same place. Everything works as expected with your code. If you will create two borders, add them to the grid as it's children it's fine but if you will set the same columnspan and rowspan they will simply be on the same place. Please take a look at the example below:
Border myborder = new Border();
myborder.BorderBrush = new SolidColorBrush(Colors.DarkGray);
myborder.BorderThickness = new Thickness(1);
GridKalkAuswahl.Children.Add(myborder);
Grid.SetRowSpan(myborder, 1);
Grid.SetColumnSpan(myborder, 4);
Border myborder2 = new Border();
myborder2.BorderBrush = new SolidColorBrush(Colors.Crimson);
myborder2.BorderThickness = new Thickness(1);
GridKalkAuswahl.Children.Add(myborder2);
Grid.SetRowSpan(myborder2, 1);
Grid.SetColumnSpan(myborder2, 3);
Grid.SetColumnSpan and Grid.SetRowSpan is the key to your problem.
I have a grid (which also could be a rectangle) which I want to draw from it's bottom to the top. It's a long lineair bar.
<Grid Grid.Row="2" Background="AliceBlue" x:Name="SkillBar11">
<TextBlock Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,40" FontSize="16">IV</TextBlock>
</Grid>
and I can make it draw from the middle to top and bottom with this code in C#:
Storyboard s = new Storyboard();
DoubleAnimation doubleAni = new DoubleAnimation();
doubleAni.To = SkillBar11.ActualHeight;
doubleAni.From = 0;
doubleAni.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTarget(doubleAni, SkillBar11);
doubleAni.EnableDependentAnimation = true;
s.Children.Add(doubleAni);
Storyboard.SetTargetProperty(doubleAni, "Height");
s.Begin();
But I can't get it to be drawn from the bottom to the top, instead of the middle to bottom and top. Can someone help me out? :)
I have found the anwser. You can orientate how the bar grows by setting a Horizontal or Verticalalignment in the grid properties. This way it will start at the position where you aligned it!
A Button contains a Grid. The structure is like the follows:
<Button>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Viewbox Grid.Column="0">
<TextBlock></TextBlock>
</Viewbox>
<Viewbox Grid.Column="1">
<TextBlock></TextBlock>
</Viewbox>
</Grid>
</Button>
The problem is that the TextBlocks position aren't fixed, so you can see the following situation, where the gridline is moved to the right when the text on left becomes longer. How to make the TextBlocks position fixed inside the grid cell (so the middle grid line stays regardless of the text length)?
EDIT: The above XAML will fix the positons of the TextBlocks as it is, but will not work when the Grid is inside a button. Images below of a Grid with blue background on a silver button: we can see the grid line changes as the text changes (while the ratio stays the same?) primarily because the Grid occupies different region of the Button.
So guess my real question is: How to make the Grid occupy the entire Button? (if the grid stays fixed, so does its grid line.)
EDIT2:
Below is the code that generates the Button, Grid, Viewbox, TextBlock structure represented by the above XAML. This code generates the Buttons as shown below, where the green Grid does not stretch to the entire blue Button and its occupied area differs based on its content. Setting Grid's properties as g.HorizontalAlignment = HorizontalAlignment.Stretch;
g.VerticalAlignment = VerticalAlignment.Stretch; doesn't work.
Button b = new Button();
b.Background = Brushes.DeepSkyBlue;
Grid g = new Grid();
g.Name = "grid";
g.ShowGridLines = true;
g.Background = Brushes.LimeGreen;
g.HorizontalAlignment = HorizontalAlignment.Stretch;
g.VerticalAlignment = VerticalAlignment.Stretch;
//create columns
for (int i = 0; i < 2; i++)
{
int len = i == 0 ? 3 : 1;
ColumnDefinition cd = new ColumnDefinition();
cd.Width = new GridLength(len, GridUnitType.Star);
g.ColumnDefinitions.Add(cd);
}
//viewbox col 0
Viewbox vb = new Viewbox();
TextBlock tb1 = new TextBlock();
vb.Child = tb1;
Grid.SetRow(vb, 0);
Grid.SetColumn(vb, 0);
g.Children.Add(vb);
//viewbox col 1
Viewbox vb2 = new Viewbox();
TextBlock updown = new TextBlock();
vb2.Child = updown;
//specify the Marlett Font
updown.Style = (Style)Application.Current.FindResource("updownBlock");
Grid.SetRow(vb2, 0);
Grid.SetColumn(vb2, 1);
g.Children.Add(vb2);
//add grid to button
b.Content = g;
this should help
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Viewbox Grid.Column="0">
<TextBlock></TextBlock>
</Viewbox>
<Viewbox Grid.Column="1">
<TextBlock></TextBlock>
</Viewbox>
</Grid>
using this example, grid will allot the required space to right column first and then remaining space will be given to left column.
I also removed the row definition as 1 row with * height is the default for grid
EDIT
in order to distribute the space based weighted proportion of available space you may define the weight in star values to both of the columns
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
In above example grid will render left column 3 times bigger then the right column which will be rendered in 1/4 of the total space.
EDIT
set HorizontalContentAlignment="Stretch" & VerticalContentAlignment="Stretch" on the button so that the Grid can occupy whole space, by default it is Center.
Instead of setting the Grid's Alignment, setting the Button's ContentAlignment finally did the trick
b = new Button();
b.HorizontalContentAlignment = HorizontalAlignment.Stretch;
b.VerticalContentAlignment = VerticalAlignment.Stretch;
Now the gridline stays regardless of length of the content :)
Your ColumnDefinition width is 3 and *. * indicates all of the available space, also your textbox or Grid'd width does not seems to be fixed hence it is but obvious that textbloxk's position will change.
Possible steps you can take:
1. Set ColumnDefinition width="Auto"
2. Set the width of textblock and the parent Grid
Buttonobject.HorizontalContentAlignment = HorizontalAlignment.Stretch;
Buttonobject.VerticalContentAlignment = VerticalAlignment.Stretch;
Stretch property will make the content aligned to the button's grid
How to make the green rectangle to be visible only inside the blue one? The blue is a border of a grid. I want to cut off everything that is not inside this grid. Notice that the green rectangle will be moving.
As there is no ClipToBounds property in Silverlight, you would have to set the Clip property to a RectangleGeometry.
When the Grid's size is fixed, you may simply set a fixed size rectangle:
<Grid>
<Grid.Clip>
<RectangleGeometry Rect="0,0,400,600"/>
</Grid.Clip>
...
</Grid>
When the Grid's size can change, you may set the Clip property in a SizeChanged handler:
<Grid SizeChanged="GridSizeChanged">
...
</Grid>
The handler code:
private void GridSizeChanged(object sender, SizeChangedEventArgs e)
{
((UIElement)sender).Clip =
new RectangleGeometry
{
Rect = new Rect(0, 0, e.NewSize.Width, e.NewSize.Height)
};
}
<Grid Width="200" Height="100">
<Grid.Clip>
<RectangleGeometry Rect="0, 0, 200, 100"/>
</Grid.Clip>
source: http://www.scottlogic.co.uk/blog/colin/2009/05/silverlight-cliptobounds-can-i-clip-it-yes-you-can/