wpf use ellipse for progress - wpf

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".

Related

How to set children position dynamically in 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);

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.

Why ZIndex is not considered in arrange override of a stackpanel

Here is what I tried to to:
Added a stackpanel to my window (Orientation: Horizontal)
Added a set of buttons to it
Set the first button's ZIndex to be higher than the second one
Increased the width of the first button
What I expected:
I expected the first button to be on top of the second button (atlest overlay)
StackPanel's width should not change unless the width of the first button is no more sufficient
What is happening actually:
First button's width increases and the second button moves towards the right accordingly. They stay on the same plane
StackPanel's width increases with increase in the first button's width
Here is my question:
I know that stackpanel has not considered ZIndex while arranging the items within itself, BUT WHY?? Shouldn't it consider the ZIndex of its children while arranging them???
The Stackpanel 'stacks' its children based on their widths, i.e. if you increase the width of an item (or increase its margin), the stackpanel will simply expand to accomodate this. If you want to force items within a stackpanel to overlap, you will have to change their location after the layout has been computed. You can perform this using a RenderTransform. See the example below:
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<Button Content="One" Canvas.ZIndex="10">
<Button.RenderTransform>
<TranslateTransform X="10"/>
</Button.RenderTransform>
</Button>
<Button Content="One"/>
<Button Content="One"/>
<Button Content="One"/>
</StackPanel>
And yes, the ZIndex is respected. This is an attached proepry of Canvas, however, it seems to be used by the rendering engine directly rather than by Canvas, hence it works in the above code.
I tried to find some relevant info about how to set the z index of wpf layout elements and panels. Using a Canvas comes with a different set of positioning issues which I simply hadn't the time to investigate. Here is a simple solution using the Panel.ZIndex property in xaml.
<Grid>
<Border Width="100" Height="100" Margin="0,0,50,50" Panel.ZIndex="1" Background="Navy" Opacity="0.3"
VerticalAlignment="Top" HorizontalAlignment="Left">
</Border>
<Border Width="100" Height="100" Margin="50,50,0,0" Background="Fuchsia" Opacity="0.3">
</Border>
The resulting two square border elements will overlap. One can use stackpanels instead of borders and use this logic to overlap anything easily.
Here is the same code adapted to the button problem:
<Grid>
<StackPanel Panel.ZIndex="10" Margin="20,20,0,0" HorizontalAlignment="Left">
<Button Content="One" Width="50" Height="40">
</Button>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="50,0,0,0" >
<Button Content="Two" Width="50" Height="40"/>
<Button Content="Three" Width="50" Height="40"/>
<Button Content="Four" Width="50" Height="40"/>
</StackPanel>
</Grid>

WPF zoom canvas and maintain scroll position

I have a Canvas element, contained within a ScrollViewer, which I'm zooming using ScaleTransform. However, I want to be able to keep the scroll position of the viewer focused on the same part of the canvas after the zoom operation has finished. Currently when I zoom the canvas the scroll position of the viewer stays where it was and the place the user was viewing is lost.
I'm still learning WPF, and I've been going backwards and forwards a bit on this, but I can't figure out a nice XAML based way to accomplish what I want. Any help in this matter would be greatly appreciated and would aid me in my learning process.
Here is the kind of code I'm using...
<Grid>
<ScrollViewer Name="TrackScrollViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Canvas Width="2560" Height="2560" Name="TrackCanvas">
<Canvas.LayoutTransform>
<ScaleTransform ScaleX="{Binding ElementName=ZoomSlider, Path=Value}"
ScaleY="{Binding ElementName=ZoomSlider, Path=Value}"/>
</Canvas.LayoutTransform>
<!-- Some complex geometry describing a motor racing circuit -->
</Canvas>
</ScrollViewer>
<StackPanel Orientation="Horizontal" Margin="8" VerticalAlignment="Top" HorizontalAlignment="Left">
<Slider Name="ZoomSlider" Width="80" Minimum="0.1" Maximum="10" Value="1"/>
<TextBlock Margin="4,0,0,0" VerticalAlignment="Center" Text="{Binding ElementName=ZoomSlider, Path=Value, StringFormat=F1}"/>
</StackPanel>
</Grid>
This is not a purely XAML way of doing it, but there is a very nice piece of work on Joeyw's blog titled Pan and Zoom (DeepZoom style) in WPF with links to the source. He has taken some inspiration from DeepZoom and it gives you smooth/animated panning and zooming of content. And if you're using WPF 4 you could probably modify it a little to add some easing functions to the animations to give it an even nicer feel.

Use UIElement as Clip in WPF

Please pardon my ignorance- I'm very new to WPF.
I am looking to implement a minor, visual effect in my application that gives the look of "inner" rounded corners. The window in question has a dark border that encapsulates several UIElements, one of which is a StatusBar, located at the bottom of the window. This StatusBar has a dark background that matches the window's border. Above the StatusBar is a content view, which is currently a Grid- its background is semi-transparent (I think that this is something of a constraint- you can see through the content view to the desktop below). I would like for the content view (represented by the transparent, inner area in the figure below) to have the look of rounded corners, though I expect to have to sort of create the illusion myself.
(Can't post the image because I'm a lurker and not a poster- please find the drawing here)
My first approach was to add a Rectangle (filled with the same, dark color as the border) immediately above the StatusBar and to assign a Border with rounded corners to its OpacityMask (similar to the solution proposed by Chris Cavanagh**). Sadly, the effect that is produced is the exact opposite of that which I am trying to achieve.
I understand that the Clip property can be of use in this sort of situation, but it seems to me that using any sort of Geometry will prove to be inadequate as it won't be dynamically sized to the region in which it resides.
EDIT: Including my XAML:
<Grid Background="{StaticResource ClientBg}" Tag="{Binding OverlayVisible}" Style="{StaticResource mainGridStyle}">
<DockPanel LastChildFill="True">
<!-- Translates to a StackPanel with a Menu and a Button -->
<local:FileMenuView DockPanel.Dock="Top" />
<!-- Translates to a StatusBar -->
<local:StatusView DockPanel.Dock="Bottom" />
<!-- Translates to a Grid -->
<local:ContentView />
</DockPanel>
</Grid>
Any pointers are more than welcome- I'm ready to provide more indepth detail if necessary.
** http://www.dotnetkicks.com/wpf/WPF_easy_rounded_corners_for_anything
EDIT: Now I got what you mean. In fact you can use Path + OpacityMask approach. You have to draw "inverted" path, to use it as opacity mask. But I have simpler and faster solution for you :). Use Border + CornerRadius, and fill the gaps with solid paths. Just try the following code in Kaxaml and let me know if this is what you were looking for:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="240"
Height="320"
AllowsTransparency="True"
Background="Transparent"
WindowStyle="None">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="24"/>
<RowDefinition Height="*"/>
<RowDefinition Height="24"/>
</Grid.RowDefinitions>
<Border Background="Black"/>
<Border Grid.Row="1" BorderBrush="Black" BorderThickness="5">
<Grid>
<Border Background="White" CornerRadius="0, 0, 5, 5" Opacity="0.7"/>
<Path
Width="15"
Height="15"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Data="M10,10 L5,10 L5,5 C4.999,8.343 6.656,10 10,10 z"
Fill="Black"
Stretch="Fill"/>
<Path
Width="15"
Height="15"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Data="M10,10 L5,10 L5,5 C4.999,8.343 6.656,10 10,10 z"
Fill="Black"
Stretch="Fill">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="-1"/>
<TranslateTransform X="15"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Grid>
</Border>
<Border Grid.Row="2" Background="Black"/>
</Grid>
</Window>
PS: You can simplify this solution by avoiding render transforms, but you got the idea.

Resources