I'm learning drawing shapes in WPF. I want draw a Path programmatically, not through XAML. I don't know what can assign to Data property.
Path p = new Path();
p.Data = ???
Look at the sample in the MSDN:
//Add the Path Element
myPath = new Path();
myPath.Stroke = System.Windows.Media.Brushes.Black;
myPath.Fill = System.Windows.Media.Brushes.MediumSlateBlue;
myPath.StrokeThickness = 4;
myPath.HorizontalAlignment = HorizontalAlignment.Left;
myPath.VerticalAlignment = VerticalAlignment.Center;
EllipseGeometry myEllipseGeometry = new EllipseGeometry();
myEllipseGeometry.Center = new System.Windows.Point(50,50);
myEllipseGeometry.RadiusX = 25;
myEllipseGeometry.RadiusY = 25;
myPath.Data = myEllipseGeometry;
myGrid.Children.Add(myPath);
It is the line myPath.Data = myEllipseGeometry; that you are looking for. Just assign it a Geometry object.
Here's an example of something I was experimenting with:
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Shapes;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Data;
namespace GridNineExperiment
{
public class Hamburger : Button
{
static GeometryCollection DataHamburger = new GeometryCollection
{
new RectangleGeometry {Rect = new Rect{X = 0, Y = 0, Width = 20, Height = 5 }},
new RectangleGeometry {Rect = new Rect{X = 0, Y = 10, Width = 20, Height = 5 }},
new RectangleGeometry {Rect = new Rect{X = 0, Y = 20, Width = 20, Height = 5 }},
};
static Path PathHamburger = new Path
{
Fill = new SolidColorBrush(Colors.White),
Stroke = new SolidColorBrush(Colors.Black),
StrokeThickness = 1.0,
Data = new GeometryGroup { Children = DataHamburger }
};
public Hamburger()
{
Content = PathHamburger;
}
}
Related
I'm trying to render a UserControl as an image, and then assign it to a secondary tile and pin it. The resulting URI is
isostore:/Shared/ShellContent/CustomTile.jpg
However, I get the following error:
ExceptionObject = {System.ArgumentException: Value does not fall within the expected range.
at
Windows.UI.StartScreen.SecondaryTileVisualElements.put_Square150x150Logo(Uri value)
at NestWP.ActionTiles.d__1.MoveNext()
I have this piece of code
var customTile = new ActionTileControl();
customTile.Measure(new Size(150, 150));
customTile.Arrange(new Rect(0, 0, 150, 150));
var bmp = new WriteableBitmap(150, 150);
bmp.Render(customTile, null);
bmp.Invalidate();
const string filename = "/Shared/ShellContent/CustomTile.jpg";
using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!isf.DirectoryExists("/CustomLiveTiles"))
{
isf.CreateDirectory("/CustomLiveTiles");
}
using (var stream = isf.OpenFile(filename, System.IO.FileMode.OpenOrCreate))
{
bmp.SaveJpeg(stream, 336, 366, 0, 100);
stream.Close();
}
bool ex = isf.FileExists(filename);
ex = ex;
}
string urilink = "isostore:" + filename;
SecondaryTile secondaryTile = new SecondaryTile()
{
TileId = "tileid",
DisplayName = "title",
Arguments = "args"
};
//Error on the line below
secondaryTile.VisualElements.Square150x150Logo = new Uri(urilink, UriKind.Absolute);
secondaryTile.VisualElements.ShowNameOnSquare150x150Logo = false;
bool isPinned = await secondaryTile.RequestCreateAsync();
I checked FileExists and the bool returns true.
How can I get the image to be set as secondary tile?
Hi maybe this source will help you
http://www.windowsapptutorials.com/windows-phone/how-to-create-secondary-tiles-on-windows-phone-start-screen-using-c/
Is it possible to animate the "old school" way, in codebehind, instead of xaml?
I just want an arrow that points to something with a 'bounce effect' which I could easily do in my own for loop. But I do not know how to refresh or do a timer delay, inside the loop. I already placed the image into position in codebehind. All I want to do is this simple animation...
public void validationArrow()
{
var validationArrow = new Image();
validationArrow.Source = new BitmapImage(new Uri("/SlProject;component/arrow.png", UriKind.RelativeOrAbsolute));
LayoutRoot.Children.Add(validationArrow);
validationArrow.Stretch = Stretch.None;
validationArrow.VerticalAlignment = System.Windows.VerticalAlignment.Top;
validationArrow.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
var arrowPosition = new TranslateTransform { X = 0, Y = 0 };
validationArrow.RenderTransform = arrowPosition;
validationArrow.Name = "validationArrow";
for (int i = 150; i >= 0; i--)
{
arrowPosition.X = i;
validationArrow.RenderTransform = arrowPosition;
// how can I refresh screen and do some timing here?
}
}
There's no school like the old school ;)
Here, this should help you on your way. You can play with the millisecond and Y translation values being passed to the BuildEasing method to change the 'bounce' effect's speed and distance.
private void RunStoryboard()
{
var arrowImage = new Image();
arrowImage.RenderTransform = new CompositeTransform();
arrowImage.Source = new BitmapImage(new Uri("/SlProject;component/arrow.png", UriKind.RelativeOrAbsolute));
LayoutRoot.Children.Add(arrowImage);
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(BuildKeyFrame(arrowImage));
storyboard.Begin();
}
private DoubleAnimationUsingKeyFrames BuildKeyFrame(Image target)
{
DoubleAnimationUsingKeyFrames kf = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(kf, target);
Storyboard.SetTargetProperty(kf, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)"));
kf.KeyFrames.Add(BuildEasing(100, 10));
kf.KeyFrames.Add(BuildEasing(200, 0));
kf.KeyFrames.Add(BuildEasing(300, 10));
kf.KeyFrames.Add(BuildEasing(400, 0));
kf.KeyFrames.Add(BuildEasing(500, 10));
kf.KeyFrames.Add(BuildEasing(600, 0));
return kf;
}
private EasingDoubleKeyFrame BuildEasing(int ms, int value)
{
return new EasingDoubleKeyFrame()
{
KeyTime = KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, ms)),
Value = value
};
}
Is there any way to draw actual WPF vectorgraphics (DrawingContext, VisualBrush, DrawingBrush, RenderTargetBitmap etc.) with Freezables in a separate thread offscreen?
The following solution almost has it, excpet that the drawing is a bitmap and is not scalable when this.label becomes big you'll the the pixels.
private void Draw()
{
this.dispatcher = Dispatcher.CurrentDispatcher;
Thread t = new Thread(this.DrawAsync);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
private void DrawAsync(object state)
{
var b1 = new Button
{
Width = 50,
Height = 50,
Content = new TextBlock
{
FontSize = 16, FontFamily = new FontFamily("Arial"), FontWeight = FontWeights.Bold, Text = "Hello"
}
};
b1.Measure(new Size(50, 50));
b1.Arrange(new Rect(0, 0, 50, 50));
PixelFormat pixelFormat = PixelFormats.Default;
var elementBrush = new VisualBrush(b1);
var visual = new DrawingVisual();
using (var dc = visual.RenderOpen())
{
// preferably I'd like to draw controls too, but shapes and text would suffice too
dc.DrawRectangle(elementBrush, null, new Rect(0, 0, 50, 50));
dc.DrawEllipse(Brushes.Green, new Pen(Brushes.Black, 2), new Point(75, 25), 25, 15);
dc.Close();
}
var bitmap = new RenderTargetBitmap(100, 50, 96, 96, pixelFormat);
bitmap.Render(visual);
bitmap.Freeze();
var br = new ImageBrush(bitmap) { Stretch = Stretch.Uniform };
br.Freeze();
this.dispatcher.Invoke((ThreadStart)delegate { this.label.Background = br; });
}
You could use DrawingImage which is a type of freezeable. Load or fill it in a BackgroundWorker, freeze it and pass it to an Image in the Completed Event.
It seems not all bindings are to evaluated when printing. For example, in the code below, only the first button has content = "100", other buttons have content = "0".
var doc = new XpsDocument("test.xps",FileAccess.Write);
var writer = XpsDocument.CreateXpsDocumentWriter(doc);
var collator = writer.CreateVisualsCollator();
collator.BeginBatchWrite();
for (int i = 0; i < 3; i++)
{
var button = new Button();
button.SetBinding(ContentControl.ContentProperty,
new Binding
{
RelativeSource = new RelativeSource(RelativeSourceMode.Self),
Path = new PropertyPath("ActualWidth")
});
button.Measure(new Size(100, 100));
button.Arrange(new Rect(0, 0, 100, 100));
button.Width = 100;
button.Height = 100;
collator.Write(button);
}
collator.EndBatchWrite();
doc.Close();
Is there a workaround?
For example, is there a way to force the binding to evaluate?
Have you tried making sure the dispatcher is idle before the call to collator.EndBatchWrite().
Something like:
Dispatcher.CurrentDispatcher.Invoke(
new Action( delegate { } ), DispatcherPriority.ApplicationIdle, null );
I have an image 800x600 and I would show a thumbnail 90x30 with some offset x=12 and y 12.
I have created a brush but I am struggling to apply an offset.
var source = new ImageBrush(groundSource);
source.Stretch = Stretch.None;
source.AlignmentX = AlignmentX.Left;
source.AlignmentY = AlignmentY.Top;
source.RelativeTransform = new TranslateTransform(0.5, 0);
var grid = new Grid();
grid.ClipToBounds = true;
grid.Background = source;
grid.VerticalAlignment = System.Windows.VerticalAlignment.Top;
grid.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
grid.Margin = new System.Windows.Thickness(12, 12, 0, 0);
grid.Width = SpriteSize.SpriteWidht + 33;
grid.Height = SpriteSize.SpriteHeight;
grid.SnapsToDevicePixels = true;
I would appreciate any suggestions.
There is a hacky solution for this problem:
Add Image as a child to the Grid.
Set Grid attribute as ClipToBounds=true
Set Image margin to control thumbnail offset.