UWP: MapControl Transparent background - c#

I am using MapBox to display a custom map of a specific area. In MapBox: my specific area is yellow and the rest of the map is transparent (see following image).
What I want to achieve:
I want to put a MapControl over a Background Image. So when the tiles of the map are transparents, I can see the background image.
The problem I have:
In my UWP app, the specific area of the map is displayed correctly (yellow) but the rest of the map is black thus the background image is hidden by the map.
There is no problem with MapBox because the generated tiles are transparent. I think the problem is in my app.
I tried to set the background of the MapControl to Transparent with no success.
XAML
<Image x:Name="background"
Stretch="UniformToFill"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
<maps:MapControl x:Name="MyMap"
Background="Transparent"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
MapServiceToken="TOKEN"/>
C#
HttpMapTileDataSource leaflet = new HttpMapTileDataSource(
"URL_TO_MAPBOX_API");
MapTileSource mts = new MapTileSource(leaflet);
mts.IsTransparencyEnabled = true;
mts.AllowOverstretch = true;
mts.IsFadingEnabled = false;
this.MyMap.TileSources.Add(mts);
this.MyMap.Style = MapStyle.None;
Am I doing something wrong or is it simply not possible?
Thanks for your help

The MapControl is a very complicated control. It uses a SwapChainPanel to interop with Direct X. It would suprise me if what you try to do is possible.

Related

How to properly align Canvas with the underlying Image?

My application detects a foreign object (blob, cluster etc) in the live webcam image and displays object's outline on top of the image. To achieve that I employ Image and Canvas elements as follows:
<Border x:Name="ViewportBorder" Grid.Column="0" Grid.Row="1" BorderThickness="3" Background="AliceBlue" BorderBrush="Red">
<Grid>
<Image x:Name="videoPlayer" Stretch="Uniform" MouseDown="videoPlayer_MouseDown"></Image>
<Canvas x:Name="ObjectsCanvas"></Canvas>
</Grid>
</Border>
Border element in the above XAML is used just to draw a thick red line border around the Grid containing videoPlayer and ObjectsCanvas. Stretch="Uniform" is set to preserve image aspect ratio while being able it to stretch when application window gets maximized.
Every time the new frame arrives from the camera videoPlayer.Source gets updated with frame's bitmap whereas blob detection method yields a list of coordinates used for drawing a Polyline. The Polyline object is then added to ObjectsCanvas to be shown on top of the actual image frame.
Here's a part which draws the blob and adds it to the ObjectsCanvas.Children:
private void DrawBlob(List<Point> corners)
{
this.Dispatcher.Invoke(() =>
{
var myPolyline = new Polyline();
myPolyline.Stroke = System.Windows.Media.Brushes.Yellow;
myPolyline.StrokeThickness = 4;
myPolyline.FillRule = FillRule.EvenOdd;
myPolyline.Points = corners;
Canvas.SetLeft(myPolyline, 0);
Canvas.SetTop(myPolyline, 0);
ObjectsCanvas.Children.Clear(); // remove any old blob polyline
ObjectsCanvas.Children.Add(myPolyline); // add new polyline
});
}
When running the application I observe imperfect overlap of the blob object (thick yellow polyline), it gets somewhat right-shifted as shown in the image below.
Observed imperfection is not due to blob detection algorithm! I verified that by drawing the polylines of very same coordinates using old-fashion GDI methods on the actual bitmap.
It gets worse when I maximize the application window, an action causing videoPlayer to stretch:
I tried setting HorizontalAlignment and VerticalAlignment properties of ObjectsCanvas to Stretch but that does not help. Is there any method to align canvas exactly with the actual displayed image region?
I could get back to drawing the polylines using GDI, but I think it's a shame doing so in WPF...
I think I found a solution.
So, in order to stretch your canvas up to your image size you could wrap your canvas in ViewvBox control and bind your Canvas.Height and Canvas.Width to the image source's Height and Width like so:
<Grid>
<Image x:Name="MyFrame" Stretch="Uniform" />
<Viewbox Stretch="Uniform">
<Canvas
x:Name="MyCanvas"
Width="{Binding ElementName=MyFrame, Path=Source.Width}"
Height="{Binding ElementName=MyFrame, Path=Source.Height}">
<Canvas.Background>
<SolidColorBrush Opacity="0" Color="White" />
</Canvas.Background>
</Canvas>
</Viewbox>
</Grid>
However you need to set your Canvas.Background (you can make it transparent like in the example above), or ViewvBox will hide all of the canvas children otherwise.
Here are some screenshots of it working with a yellow polyline:
One more thing to note here - the coordinates of your polyline should be relative to image resolution.
Hope that helps!

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 to programatically change image color?

I have a method that is triggered every time a user performs an action, within this method I want to trigger the color of an image to change color/illuminate every time the method is called.
Is there a simple way to change the color an image programmatically? I can't see any obvious methods or properties to do this attached to the image.
So the method below is as follow just not sure how to set the image color for BoxBagImage
void matcher_GestureMatch(Gesture gesture)
{
lblGestureMatch.Content = gesture.Name;
scoreCntr++;
boxBagImage. // <-- don't see any color or background property belonging to the image
lblScoreCntr.Content = scoreCntr;
}
What would setting it do? How WPF should guess what "background" you have in mind? There's couple of things that could be called 'background'. Also, how would WPF guess how large area you consider to be the background?
Let's start with the fact that Image displays a bitmap (or such) all over its area, so direct Foreground or Background are rather meaningless here. They would be overdrawn by the bitmap immediately. It's not like TextBox or Canvas.
That's probably why Image does not have such property.
--
If your bitmap itself has a "background" (ie. a drawing of a Tree on a blue sky, sky=background), it is still the content of the bitmap. WPF is not an image-editing program and will not change it for you easily. If you want to change the "background" withing your image, you can load the bitmap, modify its pixels, and load the modified bitmap into Image control. Or apply some smart filter (so-called "effect") at rendering stage.
Or, if your bitmap is transparent (for example, PNG with alpha channel, a Tree on a completely-alphaized-transparent pixels), and you want the "some background" to be seen through that "transparent gaps", then you have to set the background of not the image itself, but the component that the image lies on. So, if you have for example:
<Grid> <Image Source=.... /> </Grid>
then apply the Background on the Grid. Transparent-Image placed on a Blue-Grid will look as if were on blue background, just like drawing on a glass placed on blue table. In fact, the Grid here simply forms the background. You can get any layout or effect in that way. If you dont want to have whole grid in that color, you can inject another grid:
<Grid>
<Grid Background="Blue" Margins="30,30,30,30"> <Image Source=.... /> </Grid>
</Grid>
or whatever you like.
Or, if you meant the "background" of the Image control that shows up when the Image has its Stretch property set in a such way, that the bitmap does not fill the whole area (Stretch=Uniform likes to do that unless you carefully set Width/Height) - then simply look above. The "area" is simply transparent, so just add some color to the component beneath Image.

How to Set Background Color of Viewport

I'd like to use a specific color for the background of a Viewport control in my app page (#2B2B2B).
<ViewportControl
x:Name="Viewport"
Grid.Row="0" Grid.RowSpan="2"
SizeChanged="Viewport_SizeChanged">
<Image
x:Name="Image"
Stretch="Uniform"
CacheMode="BitmapCache"
ManipulationStarted="Viewport_ManipulationStarted"
ManipulationDelta="Viewport_ManipulationDelta"
ManipulationCompleted="Viewport_ManipulationCompleted">
</Image>
</ViewportControl>
Adding Background="#2B2B2B" within ViewportControl has no effect.
My requirement is to create a bitmap of the Viewport containing the image, and since the image usually doesn't cover the entire Viewport I'd like to have a soft dark background behind the image.
WriteableBitmap wb = new WriteableBitmap((int)Viewport.ActualWidth, (int)Viewport.ActualHeight);
wb.Render(Viewport, null);
wb.Invalidate();
You can put Viewport in a stackpanel and give color to the background color to the stackpanel and if color is also covering the image use Zindex .

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