Drawing dynamically positioned overlays on Images in wpf - wpf

I have an Image control in my view bound to BitmapSource prop in my View Model. This property is updated with images from a camera in my Model class. To get started with drawing shapes on images (so 1 control ON another),after
reading a similar post, I tried the following with a simple Rectangle
shape with Zindex=2 so it should act as an overlay over the image. But the
below doesn't work & all I see is the image from the camera
<Canvas>
<DockPanel Width="400" Height="250">
<Label DockPanel.Dock="Top" HorizontalAlignment="Center"
Content="IMAGE FROM CAMERA" Width="Auto"/>
<Image x:Name="CamImageDisplay"
DockPanel.Dock="Left"
Source="{Binding CurrentImage, Mode=OneWay}"
Stretch="None" Width="Auto"/>
<Rectangle Width="10" Height="5"
Fill="CadetBlue"
Panel.ZIndex="2" />
</DockPanel>
</Canvas>
I come from an MFC background where drawing shapes on bitmaps was as
easy as calling Draw3dRect(...). Having said that, my goal is to draw
a collection of shapes (just rectangles & circles) that will have
different co ordinates with each new image.
Could some one please
explain in simple terms or point to some reference that will show how
I can achieve this. Yes, there are other similar questions, but they
are really not quite aligned with my objectives. Thank you & please ask for clarifications if I am unclear in how I have asked my question.

Related

Magnifing glass in WPF

How can I create a non-circular magnifying glass in WPF? This has to work on controls not just an image. Every example I find online is either circular only or only works on images.
For example I have a slider, and I'd like to turn the thumb into a rectangular magnifying region to show enlarged ticks (as my ticks are displayed in the Slider track itself, not below it). I have created all the styles necessary I am just missing the ability to magnify contents underneath the thumb (as the thumb sits on top of the controls / display)
<Slider Ticks="{Binding MyCollection}" />
Thanks
It's pretty easy to just make your own 'magnifying' control. You could use a VisualBrush with a Visual property taken from the source (that you want to magnify) painted onto a plain Rectangle. See the Using VisualBrush to Show a Magnifying Glass page on the Ian G on Tap website as an example.
Better yet, here is a very simple example of a VisualBrush that is painting a Rectangle in the right column of a Grid, magnifying an Image from the left column of a Grid. You can tweak it to your liking:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Name="Image" Source="Images/BlackLogo.ico" Width="150" Height="150" />
<Rectangle Grid.Column="1">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ., ElementName=Image}"
Viewport="50,100,300,300" ViewportUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
</Grid>

Bing WPF Custom Pushpin Template Overlapping

I am using the Microsoft.Maps.MapControl.WPF dll in c# WPF.
Here is my issue in the picture below:
I use a custom template for the pushpin because I need to display some simple information for it. There is no infobox in the WPF version to my knowledge.
Clustering the pushpins together in one is not an option for me, because the pushpins represent a delivery location which needs to be displayed on the map. Zooming out is not an option for me because there could be a delivery on the other side of town which all need to be displayed by a bounding box including all pushpins.
Here is the code for my custom pushpin template:
<ControlTemplate x:Key="RedPushPinTemplate" TargetType="m:Pushpin">
<Grid >
<TextBlock Name="textBlock1" Text="{TemplateBinding Content}" Canvas.ZIndex="2" Height="75" Width="65" TextWrapping="Wrap" Grid.Column="0" Grid.Row="0" Foreground="Black"></TextBlock>
<Rectangle Width="35" Height="50" Margin="0 35 0 0" Canvas.ZIndex="1">
<Rectangle.Fill >
<ImageBrush ImageSource="pack://application:,,,/Images/redpin.jpg"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</ControlTemplate>
My question is, is there anyway to write code for the template that detects an overlap and do something nice to display the information for both pins. Better yet, is there an infobox control that someone is aware of that has this functionality built in?
Thank you very much for your time.
Sorry for the late answer.
How many Pushpins do you have? One Possiblity is to compare the List of Items (X&Y Coordinates + Radius) to find out which Pushpins Intersect eachother. Then you can adjust the X value and interate again.
You can also do this on the control level itself attaching a behavior which is constantly looking for pushpins and then see if they intersect.

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.

Creating grid of hexagons

I have to do a "grid" like this:
Harmonic table
I'm trying to create a ListView with ItemsSource="List<Note>" where every odd note in the list is moved on the bottom...
Is the ListView the right control?
How can I draw an exact hexagon with faces that is near next object?
EDIT: hexagon drawing is solved... this is the xaml:
<Path d:LayoutOverrides="None"
d:LastTangent="0,0" Stroke="Blue" Fill="Red"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Margin="0" Width="100" Height="100" x:Name="Path"
Stretch="Fill"
Data="M8.660254,0 L17.320508,5 17.320508,15 8.660254,20 0,15 0,5 8.660254,0 z"/>
The container for your notes would be an ItemsControl or a ListBox if you need to select items. Then you give your items a template using ListBox.ItemTemplate where you include your hexagon drawing. You have a nice tutorial on Custom ListBox layout.
At this point, your hexagons are displayed one below the other as a ListBox does by default. To get your special layout, you have to change the ListBox.ItemPanel. Here you have two possibilities:
either you use the Canvas panel that supports absolute positioning. In this case your items must have X and Y properties that you will use to position them.
or you create a custom Panel, probably based on Canvas, that is able to convert your custom coordinate system (for example note name + octave number) into X and Y. A bit more difficult but much more reusable. An example of Custom Panel on CodeProject.
HexGrid: CodeProject article
HexGrid: GitHub repository
The key component of a possible solution is a WPF Panel which can arrange hexagonal elements (Standard Panels operate with rectangular child elements). Take a look my HexGrid project (too large to post here). The cental part of it is a HexGrid (WPF Panel which arranges child elements in a honeycomb pattern). Child elements are represented by HexItems (hexagon-shaped ContentControls). There is also HexList (selector ItemsControl which displays items in HexItem container on a HexGrid panel) which gives hex selection support out-of-box.
example of usage:
<hx:HexList Name="HexColors" Orientation="Vertical"
Grid.Row="1"
Padding="10"
SelectedIndex="0"
Background="{Binding Path=SelectedItem.Background, RelativeSource={RelativeSource Self}}"
RowCount="5" ColumnCount="5">
<hx:HexItem Grid.Row="0" Grid.Column="1" Background="#006699"/>
<hx:HexItem Grid.Row="0" Grid.Column="2" Background="#0033CC"/>
<hx:HexItem Grid.Row="0" Grid.Column="3" Background="#3333FF"/>
<!--...-->
<hx:HexItem Grid.Row="4" Grid.Column="1" Background="#CC9900"/>
<hx:HexItem Grid.Row="4" Grid.Column="2" Background="#FF3300"/>
<hx:HexItem Grid.Row="4" Grid.Column="3" Background="#CC0000"/>
</hx:HexList>

In XAML, how can I keep an ellipse being a circle?

I'm getting XAML-blind I'm afraid. I'm developing a MS Surface application and I have an ellipse inside a ScatterViewItem (a container an end user can resize). I would like to keep the ellipse a circle (width == height) and keep it as big as possible (the lowest value of width/height of the SVI should be taken for both width/height properties of the ellipse).
A XAML only solution (using property triggers or similar) is prefered.
Your help is much appreciated as always.
I stumbled over this question a few minutes ago and found a much better solution than #Paul Betts (I'd comment on his answer if I could, but I can't)
You can simply use <Ellipse Stretch="Uniform" /> to get a circle.
Source: http://forums.silverlight.net/t/160615.aspx
Would a simple Viewbox do the trick? E.g.
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Canvas Width="100" Height="100">
<Ellipse Fill="Red" Width="100" Height="100" />
</Canvas>
</Viewbox>
The Viewbox will scale its contents to fill the area of the Viewbox, and by default does the scaling proportionally. The specified horizontal and vertical alignments keep the Ellipse centered when it cannot be stretched to the full size (because of the proportional scaling).
<Ellipse x:Name="anEllipse" Width={Binding Path=ActualHeight ElementName=anEllipse} />
You could probably get away with not naming this if you did a relative binding as well.

Resources