Same issue as Adding MapControl in xaml results in a "Catastropic failure" , the bing map control cannot be collapsed without causing a catastrophic exception. Worse, just put a map inside a collapsed container and it will crash too. It means that every parent, grandparent, and so on MUST be collapsed using code behind. breaking mvvm pattern for no reason just to display and hide a map.
Is there someone who found a workaround ? It's crazy that MS didn't fix their own control for such a long time even when they know it doesn't behave as intended..
Any help is appreciated !
This is the first time I've heard of this issue. It's worth noting that the map control in WP8.1 wasn't created by Microsoft, but Nokia. In Windows 10 Microsoft took the Nokia control and combined with the features of the Windows 8 map control and made it much more stable.
Update:
I've taken a look at this issue. It's not easy to figure out what is causing the error as the map control is written in native C++ and the error that is thrown has inaccessible properties that show up as "?". That said, I did manage to figure out a workaround. Collapsing a control is not much different than giving a control a width and height of 0. With this in mind here is a code sample of how to show/hide the map using width/height instead of visibility.
<Page
x:Class="WP81App.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WP81App"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:Maps="using:Windows.UI.Xaml.Controls.Maps"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Maps:MapControl Name="MyMap" Height="0" Width="0" />
<Button Content="Show Map" Click="ShowMapBtn_Clicked" HorizontalAlignment="Center"/>
</Grid>
</Page>
Button handler:
private void ShowMapBtn_Clicked(object sender, RoutedEventArgs e)
{
var mapContainer = MyMap.Parent as FrameworkElement;
MyMap.Width = mapContainer.ActualWidth;
MyMap.Height = mapContainer.ActualHeight;
//Hide the button
(sender as Button).Visibility = Visibility.Collapsed;
}
Related
I have a ListView in my Xamarin Android app where I have over 100 list items. Each item has a Google Maps component showing a map of an area. I have realized that this causes the vertical scrolling of the ListView to lag (due to each component is pretty computational heavy I suppose). Each area is about Width x 128 pixels.
I am now thinking of how I can show the map of the area and still have good performance in the scrolling. One idea is to generate a small image of each area and bind it to the ListView item instead. However, as far as I understand, it is not technically possible to generate images from the Google Maps API (map + marker).
How would you recommended to solve this? Do you think I have some other bottleneck rather than the 100 instances? In my tests its pretty obvious it started to lag when I added the component. However, the component is hidden (IsVisible="False") unless you expand the List Item, but still its "there" and the lag persist. Is it normal to have so many components first of all?
My map is part of a Grid and looks like this:
<Frame Grid.Row="4" x:Name="expandArea" BackgroundColor="Transparent" IsVisible="False" Padding="0" Margin="0" HasShadow="True">
<maps:Map x:Name="userMap" MinimumHeightRequest="128" HeightRequest="128" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"/>
</Frame>
I am developing a Selfie Cam App for Windows Phone 8, I don't want to use the PhotoCamera library and Video Brush etc... to manually get the front facing cam.
I want to use the CameraCaptureTask to show the camera. As all know better, that when we launch the CameraCaptureTask, it shows the Primery(Back) camera, but I need that when the Task launch it shows the Front Facing Cam first.
Plz help in this regards.
CameraCapture task don't have option to select front-facing camera.
you've to write your own code to Launch front-facing camera by default.
Possibilities:
CameraCaptureTask is WP8 API, and i don't think that Microsoft is going to provide any option in future with CameraCaptureTask.
But in WP8.1 (wp Store apps), there are no alternative for CameraCaptureTask yet, so in future Microsoft might come out with something similar to CameraCaptureTask which might contain option to launch front-facing camera by default.
Edit:
Capture Image/Video with exact orientation:-
If you're facing issue of image capture orientation while capturing image or recording video, you should have to rotate the VideoBrush to 90 degree. So that the recorded video/Image will be captured as you wish.
Check the code for this function.
You need to edit the XAML code where you've created the VideoBrush control.
<Canvas x:Name="CanvasLayoutRoot" Background="Transparent">
<!--Camera viewfinder >-->
<Rectangle x:Name="viewfinderRectangle"
Width="{Binding ActualHeight, ElementName=CanvasLayoutRoot}"
Height="{Binding ActualWidth, ElementName=CanvasLayoutRoot}"
RenderTransformOrigin="0.5 0.5" Margin="-144 145" >
<Rectangle.RenderTransform>
<CompositeTransform Rotation="90"/>
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
Here main thing to notice is <Rectangle.RenderTransform> part and two tags RenderTransformOrigin="0.5 0.5" and Margin="-144 145" of control.
after setting the UI, assign VideoCaptureDevice to rectangle and you're done..!!
Hope that helps..
I am trying to display a GIF file stored in a Windows Phone 8.1 (RT) application's local folder. Until now, I have tried several approaches:
Load the GIF in a WebView control. This is not a solution since I want to display the images in a FlipView control (I cannot flip to another image). Also, it is quite slow.
Get the GIF frames using the BitmapDecoder class and animate them using a storyboard.
The code is as follows:
using (var stream = await storageFile.OpenReadAsync())
{
//I don't specify the type since I would like to load other type of images also
//It doesn't make any difference if I would use "BitmapDecoder.GifDecoderId"
var decoder = await BitmapDecoder.CreateAsync(stream);
uint frameCount = decoder.FrameCount;
for (uint frameIndex = 0; frameIndex < frameCount; frameIndex++)
{
var frame = await decoder.GetFrameAsync(frameIndex);
var writableBitmap = new WriteableBitmap((int)decoder.OrientedPixelWidth,
(int)decoder.OrientedPixelHeight);
var pixelDataProvider = await frame.GetPixelDataAsync
(BitmapPixelFormat.Bgra8,
decoder.BitmapAlphaMode, new BitmapTransform(),
ExifOrientationMode.IgnoreExifOrientation,
ColorManagementMode.DoNotColorManage);
var pixelData = pixelDataProvider.DetachPixelData();
using (var pixelStream = writableBitmap.PixelBuffer.AsStream())
{
pixelStream.Write(pixelData, 0, pixelData.Length);
}
_bitmapFrames.Add(writableBitmap);
}
}
The problem is that the frames I get from the GIF image are messed up
Am I doing something wrong in this approach? What should I modify in order to get good results?
I wouldn't like to use SharpDX since it seems to be very complicated and I am a beginner.
ImageTools is available only for Silverlight
I made a very basic GifImage control that you can start from. This is a starting point, you'll have to improve it to make it more usable as a reusable control. Check it out here.
EDIT
Do you have any idea how to improve the loading speed (parallelization, etc.)?
I assume you're referring to the process of preparing the frames. From what I tested, it seems to load instantly anyway, so there shouldn't be a need for drastic performance improvements. However, if perhaps the animation has hundreds of frames, then it could be a bottleneck maybe? More testing needs to be done to assess whether or not optimisations are necessary.
I also don't think it can be paralleled easily since each frame needs to be rendered in sequence from the previous frame. My only suggestion would be to run the loading code on a background thread so the UI thread doesn't block for large images.
If I have this control as a FlipViewItem, how can I release the memory after the item is flipped away?
I'm not sure whether or not you're using MVVM or not, but anyway, here's some suggestions:
Set the Source of the GifImage to null if it's not currently visible (inspect the SelectedIndex of the flip view). Note that currently the code in my repo doesn't handle setting Source to null. Like I said before, it needs lots of improvements. You'll have to make sure that the control doesn't hold any references to the frames so that the garbage collector can free them from memory (that is, call animation.KeyFrames.Clear() to clear all references to the frames).
Use a VirtualizingStackPanel inside the flip view. This will ensure that only the previous, current, and next flip view items are created in memory. You set it like this:
<FlipView>
<FlipView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</FlipView.ItemsPanel>
</FlipView>
I had a similar problem. I was trying to display an animated GIF loaded from an external source inside a ScrollViewer for Windows Phone 8.1 app. Since the web control takes over the events the scrolling did not work.
I used this trick: I placed the web control inside a grid and put another grid over the webcontrol. The grid over the web control was set to be the exact same size and I set the background to transparent. This way the grid receives the events and the scrolling works again.
<ScrollViewer Visibility="Visible" HorizontalAlignment="Left" VerticalAlignment="Top" Width="380">
<Grid>
<StackPanel>
<!--
Some items ...
-->
<Grid >
<WebView x:Name="animationWebView" HorizontalAlignment="Left" Height="315" Width="390" Visibility="Visible" />
<Grid Width="390" Height="315" Background="Transparent" />
</Grid>
<!--
Some other items ...
-->
</StackPanel>
</Grid>
</ScrollViewer>
I'm trying to capture the content of a WebBrowser control that is not in the visible tree, but the WriteableBitmap.Render() is capturing a (correctly sized) bitmap of all black pixels. If I put the WebBrowser into the visual tree, the capture works fine.
WriteableBitmap doc is emphatic that it works on controls not in the visual tree, and I'm making the required calls to Measure() and Arrange(). Relevant code (originally in WebBrowser_LoadCompleted event, for demo moved to renderButton_OnClick)
hiddenBrowser.Measure(new Size(hiddenBrowser.Width, hiddenBrowser.Height)); // pretend there's plenty of space.
hiddenBrowser.Arrange(new Rect(0.0, 0.0, hiddenBrowser.Width, hiddenBrowser.Height)); // pretend we know where this is going.
//noHelp hiddenBrowser.UpdateLayout();
WriteableBitmap _bitmap = new WriteableBitmap((int)theImage.Width, (int)theImage.Height);
_bitmap.Render(hiddenBrowser, new ScaleTransform());
_bitmap.Invalidate();
theImage.Source = _bitmap;
A complete project demonstrating the problem is available at: https://skydrive.live.com/redir?resid=193BF22F5BBA1A84!10526&authkey=!AGeH6YC_NttOmj0
Press Unhide (webBrowser shows in visual tree), then Go, then Render --> render captures OK.
Then press Hide (webBrowser disappears), then Go, then Render --> Black Screen of Ignorance.
Originally, I thought this was a timing issue (e.g maybe browser hadn't finished painting the web page even though LoadComplete event fired), but it cannot be; in the demo, I wait for 10s of seconds before pressing 'render' button which does the render, and still get black image.
I reproduced your problem. It seems like the Control isn't rendered if not necessary.
Do you really need the WebBrowser to be in the Visual Tree?
If you just want it to be invisible, setting the Visibility to Collapsed won't work either (I tried).
An ugly trick that works for the WebBrowser to be invisible to the user but still allows a WriteableBitmap rendering is to translate the control out of the ViewPort. To do that, just use a TranslateTransform:
hiddenBrowser = new WebBrowser();
hiddenBrowser.Width = theImage.Width;
hiddenBrowser.Height = theImage.Height;
hiddenBrowser.LoadCompleted += hiddenBrowser_LoadCompleted;
hiddenBrowser.NavigationFailed += hiddenBrowser_NavigationFailed;
hiddenBrowser.LayoutUpdated += hiddenBrowser_LayoutUpdated;
hiddenBrowser.RenderTransform = new TranslateTransform { X = 2000, Y = 2000 }; // this is the code I added.
Ugly but working solution!
This turns out to have been doomed from the start.
You can't run the WebBrowser control in the background on WP8, period. It's an Unsupported API.
And, as noted above, there's the issue (maybe not a bug?) that WebBrowser won't provide a bitmap when it's not in the visual tree, anyway.
I have an application that switched between different graphs in Flex. Each graph is it's own state. In the MXML I have it set so that the source of the image change when the state changes:
<s:Image id="chartImage"
source.all="{ callImages.all }"
source.classA="{ callImages.classB }"
source.classB="{ callImages.classA }"
/>
I have buttons that successfully change the images. However, I have a small bug which occurs because after the line
this.currentState = chartName;
My code expected the graph image source to be changed, however the actual change to the s:Image element doesn't appear to happen until after the function ends and the screen updates, I assume. So when it grabs chartImage.height, it uses the old one from the state I just left.
Is there a way to have it get the new image (and thus it's dimensions) so I can do calculations with those dimensions on the next line? So far, chartImage.height returns the height from before the state change, but it is different after the function executes.
I could run a timmer after a fraction of a second then execute the lines there, and it would work. However, I'd rather tell it to render the screen and then continue my code. Is this possible? It just seems more elegant.
Is there a way to have it get the new image (and thus it's dimensions)
so I can do calculations with those dimensions on the next line?
Each Flex component must go through it's own validation cycle, which is built on top of the Flash Player's rendering mechanism. There are some great posts out on this, if you perform a Google search for the Flash/Flex Elastic Racetrack.
However, you can force a component to run through it's validation methods in a linear manner by calling the validateNow() method.
It is possible--especially if you have a state transition--that the properties on your Image have not changed yet after you set the currentState variable.
You generally can't change the source of an image in Flex and then immediately check ("on the next line") it's height — the exception might be when the source is a raw bitmap, but even then Flex's layout framework will vary depending on different factors so I wouldn't rely on this.
This is the classic problem with Flex: the beauty (and misery) of the framework is that it progressively renders it's changes to maximize the responsiveness of the app. Google "flex component life cycle" for a ton of resources about the details of this process.
There are a couple of ways to deal with this. Usually you'll want to use binding expressions, since they are designed for exactly this reason: asynchronous layout changes. Don't overuse them but they are a solid tool to keep the codebase simple and flexible.
You can bind to the height of a SparkImage via mxml:
<s:Image id="chartImage" />
<s:Label id="debugLabel" text="{ 'Height of chartImage: ' + chartImage.height }" />
but if you need to run logic I'd recommend using the BindingUtils (in the script block):
import mx.binding.utils.BindingUtils;
protected function someOtherFunctionBlock():void
{
BindingUtils.bindSetter( handleHeigtChange, image, "height" );
}
protected function handleHeigtChange( value:Number ):void
{
// Deal with value change
}