I got some strange black magic going on with my app.
I have defined an ImageBrush in a style dictionary:
<classes:MultiResImageChooser x:Key="MultiResImageChooser"/>
<ImageBrush x:Name="SplashScreenImageBrush"
ImageSource="{Binding SplashScreenResolutionImage, Source={StaticResource MultiResImageChooser}}"
Stretch="Fill" />`
The MultiResImageChooser class has a one simple property:
public class MultiResImageChooser
{
public BitmapImage SplashScreenResolutionImage
{
get
{
switch (ResolutionHelper.CurrentResolution)
{
case Resolutions.HD720p:
return new BitmapImage(new Uri("/Images/SplashScreenImage.Screen-720p.jpg", UriKind.Relative));
case Resolutions.WXGA:
return new BitmapImage(new Uri("/Images/SplashScreenImage.Screen-WXGA.jpg", UriKind.Relative));
case Resolutions.WVGA:
return new BitmapImage(new Uri("/Images/SplashScreenImage.Screen-WVGA.jpg", UriKind.Relative));
default:
throw new InvalidOperationException("Unknown resolution type");
}
}
}
}
SplashScreenImageBrush is binded to the background property of a Border element:
<Border x:Name="SplashScreen"
Background="{StaticResource SplashScreenImageBrush}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
So, the problem is that when I debug the application on an WP8 emulator or WP8 device everything works fine.
When launching the app without debugging, the Border background property is rendered White.
The image files are included in the project and have the Build Action set to Content.
Also, if I set the ImageSource directly to an image path, everything works.
So, the problem seems to be the MultiResImageChooser, but I do not know what could be wrong with it.
Any kind of help or hints will be greatly appreciated.
BTW, this issue does not get reproduced on w WP7.1 device and emulator.
My bet: ResolutionHelper.CurrentResolution doesn't work properly for some reason (timing issue?), so the "default" branch of your switch is executed. Your binding therefore fails, the brush doesn't get initialized, and you get a white color instead. From there, I'd start by confirming the execution of the "default" branch, for instance by putting a specific image instead of throwing an exception. Then, if my theory is right, look into the ResolutionHelper to understand what's going on.
Related
I'm struggling with new UWP InkCanvas for my apps.If you are familiar with the new InkCanvas in UWP, I would truly appreciate your help.
I have a UWP apps need to switching between InkCanvas and Canvas, which I wish to use InkCanvas for Drawing, Canvas for creating Contents such as RichEditbox, Image, etc...
My XAML is below
<Grid Margin="100,0,100,0" Background="White" x:Name="MainGrid" PointerMoved="MyCanvas_PointerMoved" PointerReleased="MyCanvas_PointerReleased" PointerPressed="MyCanvas_PointerPressed">
<Canvas x:Name="MyCanvas" />
<InkCanvas x:Name="inkCanvas" Canvas.ZIndex="0" />
<!-- End "Step 2: Use InkCanvas to support basic inking" -->
</Grid>
I tried to make my Canvas ZIndex greater than InkCanvas by using
private void AppBarButton_Click(object sender, RoutedEventArgs e)
{
if(Canvas.GetZIndex(MyCanvas) > 1)
{
Canvas.SetZIndex(MyCanvas, 0);
}
else
{
Canvas.SetZIndex(MyCanvas, 5);
}
}
However I can't make my Canvas come to the front, the InkCanvas keep Capturing my stroke if I Draw on it instead.
Does anyone know how to switch the Canvas and InkCanvas in my Grid without changing the Visibility of my InkCanvas to Collapsed?
By default the Canvas background is empty (null), so it will not capture pointer input and will pass it through to the InkCanvas.
If you want to prevent this, you could set its Background to Transparent.
However, when you start putting some controls on the Canvas itself, they should capture the pen input and not let it through to the InkCanvas.
I'm trying to do something that I thought would be pretty simple, but its not proving that way. I want to play a sound clip from a URI that I'm obtaining from an API. The URI provides an absolute URI to the audio clip.
I've tried using the MediaElement component and that works, except it hangs the UI while the clip is downloading/playing. This means a poor user experience and probably wouldn't get past store certification either.
I've also tried the SoundEffect class from the XNA framework, but that complains about an absolute URI – it seems this only works with relative links and thus wont suffice.
I'm wondering what other options I have for playing a sound clip in a windows phone 8 app that wont hang the UI
Any suggestions welcomed.
Thanks
Using media files on a network or the Internet is going to add latency to the app. You can't start playing the media until the phone has loaded the file. Use the MediaElement.MediaOpened to determine when the media is ready, then call .Play();
Of course, you need to let the users know that the media is downloading. My example uses the SystemTray ProgressIndicator to show the user a message.
XAML
<Grid x:Name="ContentPanel"
Grid.Row="1"
Margin="12,0,12,0">
<StackPanel>
<Button x:Name='PlayButton'
Click='PlayButton_Click'
Content='Play Media' />
<MediaElement x:Name='media1'
MediaOpened='Media1_MediaOpened'
AutoPlay='False' />
</StackPanel>
</Grid>
CODE
private void Media1_MediaOpened(object sender, RoutedEventArgs e) {
// MediaOpened event occurs when the media stream has been
// validated and opened, and the file headers have been read.
ShowProgressIndicator(false);
media1.Play();
}
private void PlayButton_Click(object sender, RoutedEventArgs e) {
// the SystemTray has a ProgressIndicator
// that you can use to display progress during async operations.
SystemTray.ProgressIndicator = new ProgressIndicator();
SystemTray.ProgressIndicator.Text = "Acquiring media - OverTheTop.mp3 ";
ShowProgressIndicator(true);
// Get the media
media1.Source =
new Uri(#"http://freesologuitar.com/mps/DonAlder_OverTheTop.mp3",
UriKind.Absolute);
}
private static void ShowProgressIndicator(bool isVisible) {
SystemTray.ProgressIndicator.IsIndeterminate = isVisible;
SystemTray.ProgressIndicator.IsVisible = isVisible;
}
First, a screenshot:
The title and image explain it pretty well. I have an ad set on the right side of my app's main group view (very very similar to the default grid template in this example), and when I pull up my About screen, the ad bleeds through.
The About screen is a user control set on a SettingsFlyout that I borrowed from some code samples handed out at a dev-camp (below).
class SettingsFlyout
{
private const int _width = 346;
private Popup _popup;
public void ShowFlyout(UserControl control)
{
_popup = new Popup();
_popup.Closed += OnPopupClosed;
Window.Current.Activated += OnWindowActivated;
_popup.IsLightDismissEnabled = true;
_popup.Width = _width;
_popup.Height = Window.Current.Bounds.Height;
control.Width = _width;
control.Height = Window.Current.Bounds.Height;
_popup.Child = control;
_popup.SetValue(Canvas.LeftProperty, Window.Current.Bounds.Width - _width);
_popup.SetValue(Canvas.TopProperty, 0);
_popup.IsOpen = true;
}
private void OnWindowActivated(object sender, Windows.UI.Core.WindowActivatedEventArgs e)
{
if (e.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.Deactivated)
{
_popup.IsOpen = false;
}
}
void OnPopupClosed(object sender, object e)
{
Window.Current.Activated -= OnWindowActivated;
}
}
And, because I know it will be asked for, here is the line of XAML defining the ad on my page:
<ads:AdControl Visibility="{Binding IsTrial, Source={StaticResource License}, Converter={StaticResource BooleanToVisibilityConverter}}" Grid.Row="0" Grid.RowSpan="2" x:Name="LandscapeAdControl" ApplicationId="test_client" AdUnitId="Image_160x600" Width="160" Height="600" VerticalAlignment="Center" HorizontalAlignment="Right"/>
So, why is this happening, and how do I prevent it?
Suspicions
I am still on Consumer Preview b/c I have a show-and-tell Monday and didn't have time to work on migrating the OS on this box without risking being non-functional when I am showing this. As such, upgrading might fix it if it's a bug.
1.a. Update I have upgraded to Release Preview and have the same issue.
Is there some fancy ad-hiding-but-still-getting-impressions prevention technique at play here? Perhaps it thinks I am trying to cover the ad with a ui element and still get credit for it's impression without the user seeing it. If so, how do I manage this entirely legit use case?
Spoiler Alert: ZIndex isn't set anywhere.
It presents the same problem with overlaying the AppBar (top or bottom). I used the Opened and Closed events on the AppBar instance to hide/show the ad. This means the AdControl is bound to a local page property instead of binding directly to a ViewModel. Like you said, it's unfortunate but it works.
private void bottomAppBar_Opened(object sender, object e)
{
if (App.ViewModel.IsTrialVisibility == Visibility.Visible)
this.DefaultViewModel["AdVisibility"] = Visibility.Collapsed;
// else do nothing as we don't want to show it since it's not a trial
}
private void bottomAppBar_Closed(object sender, object e)
{
if(App.ViewModel.IsTrialVisibility == Visibility.Visible)
this.DefaultViewModel["AdVisibility"] = Visibility.Visible;
// else do nothing as it's not shown in the first place (not a trial)
}
There is a property on AdControl named: UseStaticAnchor
Setting this property to true will fix both performance problems with scrolling, as well as the AdControl drawing on top of everything else.
Original answer - this method is now outdated:
The AdControl has two methods on it: Suspend() and Resume().
Whenever you open a popup window or AppBar, you will want to call Suspend(), and Resume() when it is closed again.
I believe under the covers, the AdControl uses a WebView to display the ads. For whatever reason, a WebView will always display on top of everything else in your application. The fix for this is to temporarily disable the WebView, and instead display a WebViewBrush.
(This technique is described here: http://msdn.microsoft.com/library/windows/apps/windows.ui.xaml.controls.webviewbrush) So when you call Suspend() and Resume(), the AdControl is doing this under the covers.
What I've ended up doing is creating a UserControl (named SuspendingAdControl) that simply contains an AdControl and can be used anywhere in the app. Then whenever a window is opened or closed, I use Caliburn Micro's EventAggregator to publish an event. The SuspendingAdControl will subscribe and handle these events, and then appropriately call AdControl.Suspend() or Resume().
I ended up crafting some code to listen to an event on the flyout when it closed so I could high/show the ads manually. It's unfortunate that I had to do a workaround, but it works.
None of this is now necessary, as the flyout in 8.1 now is at the top of the Z-order.
I am still on Consumer Preview b/c I have a show-and-tell Monday and
didn't have time to work on migrating the OS on this box without
risking being non-functional when I am showing this. As such,
upgrading might fix it if it's a bug.
I haven't used any advertisements in my own metro applications yet, so I haven't seen any problems like this occurring. I'm using the Release Preview, and was using Consumer Preview prior to May 2nd.
There were some significant changes between the Consumer Preview and Release Preview. As such, upgrading might fix this, or it may break something else.
You're going to have to upgrade eventually. I'd suggest trying that first before you attempt to solve the problem.
I'm trying to implement something in my app, I need to show an image, and let the user pinch in and out of the images.
I think its possible using the ScrollViewer, but I couldnt get it to work, help?
I hate to oversimplify this, but the WinRT XAML ScrollViewer has gesture manipulation built in.
You can see what I mean here. This might not be what you want. But it's sure a simple approach and might fit a certain % of scenarios. Maybe even yours.
Controls that incorporate a ScrollViewer in compositing often set a value for ZoomMode in the default template and starting visual states, and it is this templated value that you will typically start with. Controls with a ScrollViewer as part of their composition typically use template binding such that setting the attached property at the level of the control will change the scroll behavior of the ScrollViewer part within the control. Otherwise, it may be necessary to replace the template in order to change the scroll behavior of a ScrollViewer part.
Check out Morten Nielsen's article on Building A Multi-Touch Photo Viewer Control. It's for Silverlight/Windows Phone, but if you just enable manipulations on the image and change a few types in manipulation events - it should work great.
A simple solution that might be enough for you is to just put the image in a ScrollViewer, although to see it working - you need a touch screen or run it in a simulator (use the pinch tool, then drag and scroll on the image to zoom in/out).
You can also zoom it with code:
<Grid
Background="{StaticResource ApplicationPageBackgroundBrush}">
<ScrollViewer
x:Name="myScrollViewer">
<Image
Source="/Assets/SplashScreen.png" />
</ScrollViewer>
</Grid>
.
public BlankPage()
{
this.InitializeComponent();
myScrollViewer.ZoomMode = ZoomMode.Enabled; // default
Test();
}
private async void Test()
{
while (true)
{
for (double x = 0; x < 2 * Math.PI; x += Math.PI / 30)
{
await Task.Delay(1000 / 30);
float factor = (float)(1.0 + Math.Sin(x) / 10);
myScrollViewer.ZoomToFactor(factor);
}
}
}
I'm trying to programmatically load a BitmapImage in a XAML Metro app. Here's my code:
var uri = new Uri("/Images/800x600/BackgroundTile.bmp", UriKind.RelativeOrAbsolute);
var imageSource = new BitmapImage(uri);
The second line crashes with a System.ArgumentException:
The given System.Uri cannot be converted into a Windows.Foundation.Uri. Please see http://go.microsoft.com/fwlink/?LinkID=215849 for details.
The link just goes to the MSDN home page, so it's no use.
I've also tried removing the leading /, in case WinRT has different expectations about relative URIs, but I still get the same exception.
Why am I getting this exception for what seems to be a perfectly valid URI?
In the Consumer Preview, the correct URL format has apparently changed to ms-appx:/Images/800x600/BackgroundTile.bmp
Judging from the documentation for Windows.Foundation.Uri, it looks like WinRT doesn't support relative URIs. I tried a pack:// URI, but that gave me a UriFormatException, so apparently that's not the way to do it in WinRT either.
I found the answer on this thread: MS invented yet another URI format for WinRT resources. This works:
new Uri("ms-resource://MyAssembly/Images/800x600/BackgroundTile.bmp")
Note that you don't add your actual assembly name -- the MyAssembly part is literal text.
You will need to use the page's BaseUri property or the image control's BaseUri property like this:
//using the page's BaseUri property
BitmapImage bitmapImage = new BitmapImage(this.BaseUri,"/Images/800x600/BackgroundTile.bmp");
image.Source = bitmapImage;
or
//using the image control's BaseUri property
image.Source = new BitmapImage(image.BaseUri,"/Images/800x600/BackgroundTile.bmp");
you can see the reason and solution here
In case you're still having issues or are being asked to find an app to open the link, are you trying to use a WebView? If so, try using ms-appx-web instead of ms-appx.
An example:
this.webBrowser.Navigate(new Uri("ms-appx-web:///level/level/level/index.html"));
Also note the lack of the URIKind parameter--evidently not needed at all in these instances.
(I believe you may need to vary the leading forward slashes depending on your reference)
This would work in XAML but would not work in code... so each control or page has a BaseUri property which you can use to build the proper uri for assets... here is an example:
imageIcon.Source = new BitmapImage(new Uri(this.BaseUri, "Assets/file.gif"));
// Or use the base uri from the imageIcon, same thing
imageIcon.Source = new BitmapImage(new Uri(imageIcon.BaseUri, "Assets/file.gif"));
also you would need to set the build action to "Content" rather than Embedded Resource... otherwise you need to use the ms-resource:// protocol.
I know this is old but I hope this helps. I wrote this in XAML and it worked for me. The Ide I'm using is vs-2015 with win-10.
<Window>
<Grid>
<Grid.Background>
<ImageBrush ImageSource="NameOfYourImage.JPG or any Image type"/>
</Grid.Background>
<GroupBox x:Name="groupBox" Header="GroupBox" HorizontalAlignment="Left" Height="248" Margin="58,33,0,0" VerticalAlignment="Top" Width="411">
<GroupBox.Background>
<ImageBrush ImageSource="NameOfYourImage.JPG or any Image type"/>
</GroupBox.Background>
</GroupBox>
</Grid>
</Window>
MVVM ;)
public static ImageSource SetImageSource(string uriPath)//.com/image or some path
{
// this method very good for mvvm ;)
try
{
//In Model - public ImageSource AccountPhoto { get; set; }
//AccountPhoto = SetImageSource("some path");
return return new BitmapImage()
{
CreateOptions = BitmapCreateOptions.IgnoreImageCache,
UriSource = new Uri(uriPath)
};
}
catch
{
Debug.WriteLine("Bad uri, set default image.");
return return new BitmapImage()
{
CreateOptions = BitmapCreateOptions.IgnoreImageCache,
UriSource = new Uri("ms-appx:///Avatar/Account Icon.png")
};
}
}