WPF Custom shaped button - c#

I have a circle shaped button and I like to add a pair of Angel Wings to it, but I can't seem to draw it correctly.
I'd like to draw a border with an angel wing on the left and a circle in the middle and an angel wing on the right, in one custom shape..
the Custom shape is the border of the button.
The button is a resizable button, it means it can change Height & Width with the Window, and still maintain the same position.
this button is just an example of what I have made so far.
I've searched for a solution on Google and this site but can't find anything that can help me..

You can use software like Inkscape and with that you can open most image format and from images you can use the trace bitmap option to trace a path. This will create a <path> object in a <canvas>. It can then be used as a background.
things to note :
The quality highly depends on the image source quality and precision. So if your image have lots of color and gradient, huge line thickness and uses anti aliasing you will get very bad result because of a huge amount of vector on the path result. if you use thinner lines and very little color with no gradient you can get amazing conversion result.
You can also hand trace over the image and use that instead of the automatic option. You will get better result like that but it require more work.
With this path created you can create a resource in your application dictionary and use it for icon or background on anything you want. It is scalable in any direction without quality lost as it is now a vector "image".

try looking for image/Photoshop/any other image or drawing method to Xaml converter
you can create an image and convert it to xaml
see http://vectormagic.com
taken form here

Can you try this if it helps
Create Custom control , something like this
<Grid ClipToBounds="True" HorizontalAlignment="Center" VerticalAlignment="Center">
<ed:Arc x:Name="KnobA" ArcThickness="1" ArcThicknessUnit="Percent" EndAngle="360" Height="120" Stretch="None"
Stroke="Black"
StartAngle="0" Width="120" RenderTransformOrigin="0.5,0.5" StrokeThickness="0">
<ed:Arc.Fill>
<ImageBrush ImageSource="/Gazelle;component/Resources/Images/image.png" Stretch="UniformToFill" />
</ed:Arc.Fill>
</ed:Arc>
</Grid>
Use it in your other XAML
<controls:BoundRotaryButton Grid.Column="1" Margin="0,0,35,30"
VerticalAlignment="Bottom" HorizontalAlignment="Right" Opacity="0.2"
Grid.ColumnSpan="2"
BoundRotaryButtonState="{Binding myvm.RotaryPressed, Mode=OneWayToSource,
NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged}" />
Create the dependency in code behind of the button control and the handler for mouse clicks.
public static readonly DependencyProperty KnobAPushButtonStateProperty = DependencyProperty.Register("KnobAPushButtonState", typeof (bool), typeof (KnobA));
public bool KnobAPushButtonState
{
get { return (bool) GetValue(KnobAPushButtonStateProperty); }
set { SetValue(KnobAPushButtonStateProperty, value); }
}
private void KnobA_MouseDown(object sender, MouseEventArgs e)
{
Mouse.Capture(this);
KnobAPushButtonState = true;
private void KnobA_MouseUp(object sender, MouseEventArgs e)
{
Mouse.Capture(null);
KnobAPushButtonState = false;
}
In your viewmodel you will know when this dependency property changes the button is pressed or released and invoke the command you need.
I have something like a circular button, which you can rotate and press and so on. But you can use any shape you like with Blend.

Related

How to move a control along with your mouse WPF? [duplicate]

This question already has answers here:
Make Object Follow Mouse On MouseDown and "Stick" On MouseUp
(3 answers)
Closed 2 years ago.
I am making a Space Invaders clone where you control your ship with your mouse. I found online solutions for dragging and dropping a control, which worked but I couldn't manage to translate it to just moving the control with only your mouse.
private void Window_MouseMove(object sender, MouseEventArgs e)
{
Mothership.Body.Margin = new Thickness(Mouse.GetPosition(gridSpace).X, Mouse.GetPosition(gridSpace).Y, 0, 0);
}
To clarify, I want the ship's(Image control) location to be exactly where to cursor is, without an offset. I don't even know where this offset comes from or how to get it.
Here is a screenshot of my mouse moving, you can see the image itself it very far away from the actual cursor. How do I fix this? If you need more information I will try to provide it. image
I guess that yours image control inside the grid have HorizontalAlignment="Stretch" and VerticalAlignment="Stretch" (The default values), that cause the unwanted offset. So as Clemens suggested you must use a canvas. otherwise if you can't change your parent control set the image HorizontalAlignment="Left" and VerticalAlignment="Top" and your code will be work. But as the Clemens and Ostas suggested moving a object by margin is not a good way and if you must use grid you can use a TranslateTransform (also see this).
So just set RenderTransform property of image control and set it's X and Y properties in Window_MouseMove.
Sample xaml:
<Grid x:Name="gridSpace">
<Image x:Name="Body" Source="*.png" Width="100" Height="100" HorizontalAlignment="Left" VerticalAlignment="Top">
<Image.RenderTransform>
<TranslateTransform x:Name="mTransform"/>
</Image.RenderTransform>
</Image>
</Grid>
Sample code:
private void Window_MouseMove(object sender, MouseEventArgs e)
{
//Body.Margin = new Thickness(Mouse.GetPosition(gridSpace).X, Mouse.GetPosition(gridSpace).Y, 0, 0);
Point pos = e.GetPosition(gridSpace);
mTransform.X = pos.X;
mTransform.Y = pos.Y;
}

How to continue scaling the image visually?

I have a ScrollViewer with Image in it. I attached listener to MouseWheel event so I could zoom in/out the image. The code looks like this:
private void ImageMouseWheel(object sender, MouseWheelEventArgs e)
{
Matrix matrix = image.LayoutTransform.Value;
if (e.Delta > 0)
matrix.ScaleAt(1.5, 1.5, e.GetPosition(image).X, e.GetPosition(image).Y);
else
matrix.ScaleAt(1.0 / 1.5, 1.0 / 1.5, e.GetPosition(image).X, e.GetPosition(image).Y);
image.LayoutTransform = new MatrixTransform(matrix);
}
It pretty much works, but it has odd quirk -- when the image is so zoomed out that is at state "fit to parent" visually I cannot it zoom out more (visually), but the matrix is scaled still.
This is bad in sense that any computation after this point is wrong, and also it has strange effect in UI, say user starts from "fit to parent" zoom:
zoom out --> visually no change, internally matrix is zoomed out
zoom in --> surprise, visually no change, internally matrix is zoomed in
zoom in --> visually zoom in, matrix is also changed (OK)
Because of those problems I would like either to continue zooming out visually in order to keep both things (internal and visual) in sync.
How to achieve this?
Xaml:
<DockPanel>
<ScrollViewer Name="imageScrollViewer" Grid.Column="1" MouseWheel="ImageMouseWheel"
CanContentScroll="true" HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<Image MouseWheel="ImageMouseWheel" Name="image" Source="{Binding Path=Bitmap}"
MouseMove="Image_MouseMove"></Image>
</ScrollViewer>
</DockPanel>
Update: Originally I asked how to continue scaling visually or stop internally, but I found out that the last step of zooming out, when the image hits the state "fit to parent" is already out of sync internally-visually. For example position of the mouse is not correctly decoded above such image when moving the mouse around. Only when I zoom in a little the positions are correct. So the only way I see is to scale it visually correctly.
Hmm, I am tempted to delete this embarrassing question, but on the other hand maybe someone will have the same problem in future.
The problem is image is zoomed out, but later the dock panel zoom it in back. The image does not know about it so the math goes astray. The solution is to add some container which does not do additional scaling on itself, like stack panel.
Thus the solution lies in xaml:
<DockPanel>
<StackPanel>
...
</StackPanel>
</DockPanel>

How to use the horizontal scrollbar while keeping the UniformToFill property of the ViewBox inside the ScrollViewer?

I have a ViewBox containing a few stackpanels which I want to stretch when I resize my window. I was able to get this behavior using the property Stretch="UniformToFill"
However resizing causes some items to get outside the window, I have thus implemented a ScrollViewer to solve this.
The vertical scrollbar works fine, but once I enable the horizontal scrollbar, the viewbox stops stretching the way I want.
I have researched and tried to solve this, 2 solutions came up, none of which worked:
Solution in xaml:
<ScrollViewer HorizontalScrollBarVisibility="Auto" >
<Viewbox x:Name="MainViewBox" Stretch="UniformToFill" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollViewer}}, Path=ActualWidth}" >
...
</Viewbox>
</ScrollViewer>
This solution shows the horizontal bar while keeping the stretching property, but the scrollbar does not change size while I resize, which makes it useless.
Solution using code in C# (after defining a scrollbar in the xaml code):
bool need_scrollbarH = false;
private void ScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (((ScrollViewer)sender).ActualWidth < MainViewBox.ActualWidth)
need_scrollbarH = true;
}
private void hScrollBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (need_scrollbarH)
{
this.Left = (hScrollBar.Value - hScrollBar.Minimum) / (hScrollBar.Maximum - hScrollBar.Minimum) * (this.Width);
}
}
I have tried to shift the content of the window using this code, but it only shifted the entire window's position...
I have run out of solutions, hope someone could give me some insight into this.
I can't share the entire code or the design, this is however the document outline:
Document Outline
And the general design:
Design

Change the Color of a Rectangle Windows Phone 8

I am creating a Windows Phone 8 app that has a grid of rectangles. Each of the rectangles starts at a particular color using the fill property. I want to be able to change the color of the rectangle by tapping on it, however, I am unable to find a way to modify the fill property from my c# code side. Is there a way to make this possible? I have seen lots of information about the Brush class, but it does not seem to be supported on windows phone 8.
Example of xaml.
<Rectangle x:Name="mon9a" Fill="#FFD69F50" HorizontalAlignment="Left" Height="48" Margin="58,94,0,0" Stroke="Black" VerticalAlignment="Top" Width="73" Tap="mon9a_Tapped"/>
Something like this should do the trick. Obviously you need to set the colour of the solidcolourbrush to your desired colour.
private void rectangle_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
// Change this colour to whatever colour you want.
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Color.FromArgb(255, 255, 255, 0);
System.Windows.Shapes.Rectangle rect = (System.Windows.Shapes.Rectangle)sender;
rect.Fill = mySolidColorBrush;
}
The best way to achieve this would be to create a ViewModel for your page and bind the rectangle Fill property to a property there.
E.g.
<Rectangle x:Name="mon9a" Fill="{Binding MyFillProperty, Mode=OneWay}" HorizontalAlignment="Left" Height="48" Margin="58,94,0,0" Stroke="Black" VerticalAlignment="Top" Width="73" Tap="mon9a_Tapped"/>
You either need a property for each rectangle in your ViewModel, or a bit more elegantly you'd have a collection of rectangles in your page's ViewModel that you are binding to in order to render your rectangles on the page (so you don't need to add each on manually). Each of these rectangle objects in your collection will also be a ViewModel object that raises the appropriate Property Changed events so your XAML automatically updates itself with any changes to the Fill color property when set on the tap event.
ViewModels are well worth the effort in learning about in Windows Phone as they'll make life a lot easier by removing a lot of manual code plumbing and will keep your code cleaner.

How do I drag an element in Windows 8 XAML app?

XAML/C# Windows 8 app...
I have used MouseDragElementBehavior in XAML/C# to drag an element around on the screen.
Unfortunately the interactions assembly doesn't work while developing app for Windows 8.
How do I drag an element in Windows 8 XAML app?
Thanks.
EDIT: I found a sample example here: http://code.msdn.microsoft.com/windowsapps/Input-3dff271b/sourcecode?fileId=44758&pathId=962809525
Just copy the code and am able to drag my element. Having some issues will update, if need help.
You need to handle the manipulation events on the element you wish to drag. And also, set ManipulationMode to a value other than None on the element.
Handle ManipulationStarted to initialize your drag code
Handle ManipulationDelta, inspecting the e.Delta values, and offset your element using a RenderTransform, or if in a Canvas, use the canvas coordinates.
Hope that helps.
Here is a overly simplified example based on ColinE's answer.
Consider a Canvas that has an ellipse:
<Canvas Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Ellipse Fill="Red"
Canvas.Left="100"
Canvas.Top="100"
Width="100"
Height="100"
ManipulationMode="All"
ManipulationDelta="Ellipse_ManipulationDelta_1"/>
</Canvas>
Now in the code behind, you handle the ManipulationDelta:
private void Ellipse_ManipulationDelta_1(object sender, ManipulationDeltaRoutedEventArgs e)
{
Ellipse myEllipse = (Ellipse)sender;
Canvas.SetLeft(myEllipse, Canvas.GetLeft(myEllipse) + e.Delta.Translation.X);
Canvas.SetTop(myEllipse, Canvas.GetTop(myEllipse) + e.Delta.Translation.Y);
}

Categories