How to set children position dynamically in WPF - wpf

we have three control inside stackpannel now i want to change the control position dynamically .
we have searching Google but we don't find any solution.
please solve my problem.
thanx in advance.

If you are changing the position of elements inside a container then a StackPanel is the wrong container to use. It's designed to stack (!) elements on top of each other (or along side each other) with a spacing determined by the margins on each element.
If you want to move things around then you'll need a Canvas. With this you can then change the position of the elements on the canvas from code.
For example if you have the following:
<Canvas>
<Rectangle x:Name="Rectangle1" Canvas.Left="40" Canvas.Top="31"
Width="63" Height="41" Fill="Blue" />
<Ellipse x:Name="El;ipse1" Canvas.Left="130" Canvas.Top="79"
Width="58" Height="58" Fill="Blue" />
<Path x:Name="Path1" Canvas.Left="61" Canvas.Top="28"
Width="133" Height="98" Fill="Blue"
Stretch="Fill" Data="M61,125 L193,28"/>
</Canvas>
You can then change the position of elements like this:
Rectangle1.SetValue(Canvas.TopProperty, 45);
Rectangle1.SetValue(Canvas.LeftProperty, 60);

Related

How do you get a Path object to stop clipping to its bounds?

Hopefully I'm missing something simple here. I'm trying to draw arrow geometry using a Path shape in my XAML. However, since some of my lines go right to the edges of the bounding box, plus it having a thick stroke (made thicker for this demo) they are getting clipped.
I have tried setting ClipToBounds to false, but it doesn't have any effect.
Here's the relevant XAML. I've added coloring and a margin to show what it's doing..
<Border Background="LightGreen">
<Path
Margin="10" ClipToBounds="False"
Width="100"
Height="40"
Data="M0,20 L20,0 L20,12 L100,12 L100,28 L20,28 L20,40z"
Fill="Yellow"
Stroke="Black"
StrokeThickness="4" />
</Border>
And here's the results...
So how do you stop a Path shape from clipping?
The way I'd generate this display is to use the container (in your case the border) to control the size of the graphic, and then define the Path with Stretch="Fill" to use as much of the available space as appropriate. That way you can specify the Path's Data value using it's own nominal coordinate system, rather than calculating the exact pixel location for each vertex of the path.
<Border Background="LightGreen" Width="140" Height="60">
<Path
Margin="10"
Data="M 0,3 L 3,0 `L 3,2 L 10,2 L 10,4 L 3,4 L 3,6 z"
Fill="Yellow"
Stroke="Black"
StrokeThickness="4"
Stretch="Fill" />
</Border>
Ok, not exactly what I was afer (because I wanted the graphic to extend outside of the bounds) but a sort-of workaround was found here on S/O:
You clip the path by its own geometry, then you double the stroke thickness, like so:
<Path
Margin="10" ClipToBounds="False"
Width="100"
Height="40"
Data="M0,20 L20,0 L20,12 L100,12 L100,28 L20,28 L20,40z"
Clip="{Binding Data, RelativeSource={RelativeSource Self}}"
Fill="Yellow"
Stroke="Black"
StrokeThickness="8" /> <-- Doubled the thickness here
Notice how I had to double the StrokeThickness from 4 to 8.
The downside of this approach is you can only use it for closed paths that mark the bounds of your geometry. For instance, I couldn't draw a horizontal line down the center as part of the same geometry or it would be stroked at the full thickness of eight, not four, so you'll have to layer two different Path objects if you need such an effect.
I'm going to leave this as unanswered for a few more days in case someone does figure out how to disable clipping, but at least this is a semi-viable work-around for now.

drag items in resizable canvas

I'm designing a spline editor which is composed of two parts (usercontrols)
The left control is the DesignerControl and the right one is the InfoControl. They share the same DataContext: DesignerVM with an
ObservableCollection<SplineVM> SplineVMList;
DesignerControl is an ItemsControl templated as a Canvas ("mycanvas") with ItemsSource bound to SplineVMList and ItemTemplate set as SplineControl.
InfoControl is a ListBox displaying the SplineVMs and a Grid displaying the SplineVMs' Properties.
In SplineControl I have a Canvas containing 4 draggable Points (Rectangle) and 2 Lines that will be bound to these Points. Everything works, I can drag my points, my lines move.
<UserControl>
<Canvas Width="300" Height="300" x:Name="mycanvas" Background="Transparent">
<Path x:Name="curve" Stroke="#F02828" StrokeThickness="3">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure>
<PathFigure.Segments>
<PathSegmentCollection x:Name="pathsegment"/>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Rectangle x:Name="curvePoint1" Width="10" Height="10" Canvas.Bottom="0" Canvas.Left="0" />
<Rectangle x:Name="curvePoint2" Width="10" Height="10" RadiusX="4" RadiusY="4" Canvas.Bottom="0" Canvas.Left="{Binding ElementName=mycanvas, Path=ActualWidth, Converter={StaticResource mathconverter}, ConverterParameter=(#VALUE/4)}"/>
<Rectangle x:Name="curvePoint3" Width="10" Height="10" RadiusX="4" RadiusY="4" Canvas.Bottom="0" Canvas.Left="{Binding ElementName=mycanvas, Path=ActualWidth, Converter={StaticResource mathconverter}, ConverterParameter=(#VALUE/2)}"/>
<Rectangle x:Name="curvepoint4" Width="10" Height="10" Canvas.Bottom="0" Canvas.Left="{Binding ElementName=mycanvas, Path=ActualWidth, Converter={StaticResource mathconverter}, ConverterParameter=(#VALUE)}"/>
<Line x:Name="line1" Stroke="#dfdfdf" StrokeThickness="1"/>
<Line x:Name="line2" Stroke="#dfdfdf" StrokeThickness="1"/>
</Canvas>
</UserControl>
My first problem is that I have to use a container (here a Canvas) to hold the path, rectangles and lines.
When i add a SplineControl in mycanvas, it's well placed and i can instantly drag my points but when i add another UserControl, it's placed above the previous one and i can't select the first Usercontrol's points.
I don't want to use IsHitTestVisible since I want to select points from the first userControl through the second.
My Second problem:
Since I use a Canvas to hold my things in the SplineControl, i can drag points outside of the canvas and still interact with it, and at first sight it was great.
But thinking it again, i'd like to resize my Canvas when i move a point to always have my point in the canvas. but also have my other points positions updated respecting the ratio of mycanvas.
Do you know any control that have this behavior and can replace my Canvas?
Should i use CustomControl instead of UserControl?
May I have to think again my project's conception?
Looking at your application details using Canvas makes sense to me. I have worked on a similar application and created a DesignerCanvas allowing items movement, resizing etc. and worked well.
First problem: I also faced similar problem and decided to add a delta to the position of my control's; so say location of first control is 0,0 then next control will be placed at 10,10; and next at 20,20; this way all the controls have visible area and are slectable(as soon as it's selected it comes to top).
Second problem: It's not a big problem to increase the width and height of Canvas when a control is dragged and making sure that control is not allowed to place outside Canvas. Will try to see if I can find the code related to that.
Look at this article series having similar implementation -
WPF Diagram Designer - Part 4, Part 3, Part 2, Part 1
In Fact I've found a way to get around my first problem of item selection through other items.
Canvas that were under the selected one were unclickable because the Color of every Canvas was set to Transparent. So I could see them but not interact with them.
Since I've set the Background property to Null (or haven't set it explicitly), I can click through and select the items under the top one.
It's a strange behavior of WPF...
Does someone have an explanation?
It will solve my 2nd problem too, 'cause I'll set my UserControl with the size I want and still select other UserControls in my View.
It's a dirty trick but I'll avoid the CustomPanel thing then.
thx anyway akjoshi and Danny Varod for your concern ^^
your answers were still useful since I'll use them in the other project I'm working on.
it's just that time is short on this one.

wpf use ellipse for progress

curious about using ellipse for showing progress, probably as the progress bar uses IsIndeterminate. I'll have ellipse where either color or opacity create an effect of moving
from left to right, but instead of a sold bar, ellipse controls spread apart. I'm not looking
for a working example, just hoping for some direction in the best way to pursue this.
<Canvas VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Name="canvas1" >
<Ellipse Height="15" Name="ellipse1" Fill="DodgerBlue" Stroke="DodgerBlue" Width="15" />
<Ellipse Height="15" Name="ellipse3" Fill="DimGray" Stroke="DodgerBlue" Width="15" Canvas.Left="21" Canvas.Top="0" />
<Ellipse Height="15" Name="ellipse2" Fill="DimGray" Stroke="DodgerBlue" Width="15" Canvas.Left="42" Canvas.Top="0" />
</Canvas>
I'd probably start by creating a UserControl that contains an animated ellipse that "pulses" -- becomes brighter and then fades back, waits a second, and then brightens again, and so on.
I'd put multiple instances of that control into a UniformGrid.
To get the desired effect of left-to-right, you'd want to expose some property that would be bound to the start time for the animation, so that the leftmost instance starts at 0, next slightly later, next slightly later, and so on. I'd expect to play with that timing until I get the desired left-to-right "flow".

How to prevent the Visual Brush from stretching its content

In my project I want to display a small logo on the side of a custom control. Since I have no canvas I thought maybe a Visual Brush would be a good Idea to place the logo in the background.
<VisualBrush>
<VisualBrush.Visual>
<Rectangle Width="200" Height="200" Fill="Red" />
</VisualBrush.Visual>
</VisualBrush>
But the Rectangle I am using right now is not 200x200. It takes the complete available space. Thats not what I want. I also tried a Viewbox and set the stretch property but the result is the same because in the end I don't need a simple Rectangle but a canvas with many path objects as children. A Viewbox supports only one child.
This there any way to get around this problem?
You need to set TileMode, Stretch, AlignmentX and AlignmentY properties on your VisualBrush:
<VisualBrush TileMode="None" Stretch="None" AlignmentX="Left" AlignmentY="Top">
<VisualBrush.Visual>
<Rectangle Height="200" Width="200" Fill="Red"></Rectangle>
</VisualBrush.Visual>
</VisualBrush>
Add Grid and this Set Vertical alligment to Top and Horizontal alignment to Right
Sample code
<VisualBrush x:Key="myVisual">
<VisualBrush.Visual>
<Grid>
<Rectangle Height="200" Width="200" Fill="Red" HorizontalAlignment="Right" VerticalAlignment="Top" ></Rectangle>
</Grid>
</VisualBrush.Visual>
</VisualBrush>
For me, I set the following attribute on the VisualBrush, and the VisualBrush now looks exactly like a MediaElement:
Stretch="Uniform"

How do I position an element within a WPF Grid column?

Let's say I want to position an element at the coordinates x=20, y=5 within the 3rd column of a Grid control. How do I do this? Do I need to add a Canvas panel to the column and then add the controls to it?
You can do it that way, but have a look at this..
Attached Property
<Grid Background="Yellow">
<Rectangle Fill="Red" Margin="20,10,0,0" Width="50" Height="30"
HorizontalAlignment="Left" VerticalAlignment="Top" />
<Rectangle Stroke="Green" Margin="30,15,0,0" Width="20" Height="30"
HorizontalAlignment="Left" VerticalAlignment="Top" />
</Grid>
You can use the Margin property to simulate absolute positioning.
Not sure whether this would help you, but in any case an interesting read.

Resources