cannot get TextBlock ActualWidth value in windows phone 8.1 runtime app - c#

I'm developing wp8.1 runtime app.I need to get a textblock control's actual width to do something before a page(or an usercontrol) loaded. In the wp8 app, I can do this with using the code:
var textBlock = new TextBlock();
textBlock.FontSize = 26;
textBlock.Text = "A";
var width = textBlock.ActualWidth;
but, in the wp8.1 runtime app, the code above cannot get actual width, and it always returns 0.
Could someone tell me how to get textblock actual width before page loaded in wp8.1 runtime app?
Thanks!

I'm actually surprise it worked in WP8.0 SL so I did a little test. You're right it does work. To get it to work in WP8.1 runtime, I would add it to a Container then call UpdateLayout like below:
<Grid x:Name="ContentPanel">
<!--- content xaml --->
</Grid>
private void Page_Loaded(object sender, RoutedEventArgs e)
{
TextBlock tb = new TextBlock();
tb.Margin = new Thickness(-2500, -2500, 0, 0); // hide it using margin
tb.FontSize = 26;
tb.Text = "Test Test Test Test";
this.ContentPanel.Children.Add(tb);
tb.UpdateLayout();
var tb_width = tb.ActualWidth;
var tb_height = tb.ActualHeight;
}

I don't think you can get it before the TextBlock is actually loaded.
The thing is that the default value of ActualWidth is 0 and the default value is what you would get if the TextBlock has not yet been loaded or rendered in the UI. Reference and more details about this property can be found here.
You might be able to catch a SizeChanged event of the TextBlock and do something from there.

Related

How to set the value of ControlTemplate in UWP

I working on Xamarin project and made custom renderer for my custom control in UWP project. I found how to set the ControlTemplate by using xml code.
XML Way:
var tb = new TextBox(); // or what I do in Xamarin var tb = Control;
var ct = (Controls.ControlTemplate)XamlReader.Load(#"
<ControlTemplate TargetType=""TextBox"" xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Grid>
....
</Grid>
</ControlTemplate>");
tb.Template = ct;
But how I can do the same in code?
var tb = new TextBox(); // or what I do in Xamarin var tb = Control;
var ct = new ControlTemplate();
ct.TargetType = typeof(TextBox);
var grid = new Grid();
ct.VisualTree = grid // This is how it was done in wpf but there is no such option in UWP
tb.Template = ct;
It's not supported in UWP, and I previously found no way to directly set it. As per the MS docs.
ControlTemplate: this is used as the value of the Control.Template
property, which defines the visuals of a control by applying the
template. You almost always define a ControlTemplate as a XAML
resource, using an implicit key TargetType that is the same as a Style
that sets Control.Template with a Setter. You rarely if ever assign a
value for Control.Template directly on a control instance.
Besides possibly delving into reflection, or using the XAMLReader as per your first example, I have never found another way to do it, like you do in WPF.

DesiredSize of a button and radio button in UWP XAML

I need to measure the DesiredSize or ActualHeight/Width of a button (and radio button) without actually putting it onto the visual tree but I keep getting back non-sense values. This same approach works when measuring other controls such as TextBlock.
var button = new Button
{
Content = "Hello World",
FontSize = 15
};
button.Measure(new Size(maxWidth, double.PositiveInfinity));
var height = button.DesiredSize.Height;
var width = button.DesiredSize.Width
I'm getting back 21px for height and 0px for width. Any idea why I'm getting 0 back for width?
I need to measure the DesiredSize or ActualHeight/Width of a button (and radio button) without actually putting it onto the visual tree but I keep getting back non-sense values.
If you assign a string value to Button.Content, the value will be assigned to the inside TextBlock through Binding in runtime, which happens after the Button.Measure (You can see this by adding the button to the page and check the LiveProperty Explorer):
So you get the wrong desired size.
As a workaround, you can create a TextBlock and assign this TextBlock to the button:
var tbContent = new TextBlock()
{
Text = "Hello World",
FontSize=15
};
var button = new Button
{
Content = tbContent,
};
var h= button.DesiredSize.Height;
button.Measure(new Size(200, double.PositiveInfinity));
var height = button.DesiredSize.Height;
var width = button.DesiredSize.Width;
Then you will get the correct Size of this button.
I'm guessing that this isn't possible. You're measuring the button before it has loaded its template.
I can only suggest doing something like this:
var but = new Button();
but.Content = "Hello";
var popup = new Popup();
popup.Child = but;
popup.IsOpen = true;
popup.Visibility = Visibility.Collapsed;
but.Loaded += (s, e) =>
{
System.Diagnostics.Debug.WriteLine(but.RenderSize);
popup.IsOpen = false;
};
But it's kind of hacky, and the button won't load until some later time, making this whole process asynchronous which might be difficult to manage.

Can't Get WP 8.1 AdControl to Engage on User Click

I have a universal app project for Windows/WP 8.1, and I am attempting to get the Ads to work on both platforms. In the OnApplyTemplate function of my control, I have an #ifdef to dynamically create the AdControl for either Windows or WP. The code works great on Windows, and on WP the ad shows up just fine; but when I click on it, nothing is happening. I have tried replacing the code with a dynamic Button to make sure something else isn't intercepting the clicks, and the Button works just fine. Any ideas?
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
var baseGrid = (Grid)GetTemplateChild("_BaseGrid");
var bannerGrid = (Grid)GetTemplateChild("_BannerGrid");
#if WINDOWS_APP
bannerGrid.Height = 450;
// Create the ad
var ad = new Microsoft.Advertising.WinRT.UI.AdControl()
{
ApplicationId = "0b7b7910-f56d-477c-b0e9-3def577b6359",
AdUnitId = "10056707",
Height = 90,
Width = 728,
Visibility = AdVisibility,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Center
};
baseGrid.Children.Add(ad);
#else
// Set the margins appropriately for WP
bannerGrid.Margin = new Thickness(0, 55, 0, 50);
/* This works just fine!
var button = new Button()
{
Content = "Try This!",
Height = 50,
Width = 320,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Center
};
button.Click += (object sender, RoutedEventArgs args) =>
{
Nova.Utilities.Logger.Info("User tapped on button.");
};
baseGrid.Children.Add(button);*/
// Create the ads
var ad = new Microsoft.Advertising.Mobile.UI.AdControl("f854ae91-1c0e-469c-8387-6c90ef8fa6a2", "11388154", true)
{
Height = 50,
Width = 320,
Visibility = AdVisibility,
IsEnabled = true,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Center
};
ad.IsEngagedChanged += (object sender, RoutedEventArgs args) =>
{
Nova.Utilities.Logger.Info("User tapped on Ad.");
};
baseGrid.Children.Add(ad);
#endif
}
So it seems like this may possibly still be a bug in the system:
This is a bug in our system. We are still actively working on a fix
and work out a release plan. But here is a workaround I found. BTW,
this workaround hasn't been fully tested in our team.
https://social.msdn.microsoft.com/Forums/en-US/053fe091-8ffb-4d6f-a5ca-f39cff4af618/ads-not-responding-to-tap-or-click?forum=aiaforwinphone
Per the comments, some digging showed it might be related not setting the current Context to a Frame correctly:
MonoGame people have run into this problem too with the new Microsoft
Advertising SDK for Windows 8.1. They had to make changes to make the
ads work again. Maybe the prime31 June plugin needs a similar update?
I am asking in the prime31 support forums too.
https://monogame.codeplex.com/discussions/467336
Also I have found other peoples released Unity Windows Store 8.1 games
that suffer from the freezing problem after the ad is displayed
sometimes. I guess they didn't notice it. Example: (the first ad
popping up froze the game graphics for me):
http://apps.microsoft.com/windows/e...mulator/04eea1ba-8792-437f-a7c2-faec620da6bf#
Following the links seem to show some success with setting it to a Grid:
Add Width and Height and Background to and also place it
where you want your Ad to appear. If you do not set Width and Height
and give your Grid a background color if floods all the screen.
https://monogame.codeplex.com/discussions/467336
Best answer I can find on this issue, no one seems to have been able to resolve it any other way.

Render CheckBox to Image for Tile

I want to display one or more CheckBoxes on a tile in my Windows Phone app. This works already for TextBlocks, but with a CheckBox it shows only the Text of the CheckBox and not the Checkmark itself.
This is a sample of my code:
public void CreateTile()
{
StackPanel panel = new StackPanel();
panel.VerticalAlignment = VerticalAlignment.Top;
panel.Margin = new Thickness(7.0, 7.0, 7.0, 0);
panel.Width = 336;
panel.Height = 336;
panel.Orientation = Orientation.Vertical;
// Create and add a CheckBox for each task
foreach (var task in _tasks)
{
TextBlock textBlock = new TextBlock();
textBlock.TextWrapping = TextWrapping.Wrap;
textBlock.Style = App.Current.Resources["PhoneTextLargeStyle"] as Style;
textBlock.Foreground = new SolidColorBrush(Colors.White);
textBlock.Text = task.Text;
CheckBox checkBox = new CheckBox();
checkBox.IsChecked = task.IsDone;
checkBox.Content = textBlock;
panel.Children.Add(checkBox);
}
Grid layoutRoot = new Grid();
layoutRoot.Background = new SolidColorBrush(Colors.Blue);
layoutRoot.Width = 336;
layoutRoot.Height = 336;
layoutRoot.Children.Add(panel);
layoutRoot.Measure(new Size(336, 336));
layoutRoot.Arrange(new Rect(0, 0, 336, 336));
layoutRoot.UpdateLayout();
// Render grid into bitmap
WriteableBitmap bitmap = new WriteableBitmap(336, 336);
bitmap.Render(layoutRoot, null);
bitmap.Invalidate();
// Save background image for tile to isolated storage
Uri backgroundImage = TileHelper.SaveTileImage(bitmap);
}
If I create a tile with a background image created by the method above, the tile will look like this:
As you can see the text is displayed but there is no checkmark/square before the text.
I personally like to use Segoe UI Symbol as the Font Family in such situations. This gives me the flexibility to use Text and Symbols together while not messing around too much with code / images. SUS has great modern icons (or characters if you may call them) that are very much Metroish, I'd say.
Just open up Charmap (Win + R and type in charmap) and in the Font Select -> Segoe UI Symbol. Now you can select any character you like and paste into Visual Studio Editor itself. Yes, it works!
The symbol may not display properly in the Editor itself but it will at Runtime
Here are some suggestions:
Here are the corresponding characters:
☑

✅

Don't worry about them not looking right HERE. They should when you follow the above steps.
You can always "hack" it by using images of checkbox controls. Did you try to show created control in UI? i.e. adding it to page? Just to see if your code is executed correctly.
Or another solution would be to use check mark character - http://www.fileformat.info/info/unicode/char/2713/index.htm
I'll try to replicate this problem in my test app since it is strange that it does not work.

Adding image to a button in WPF C#, image not appearing

I want to create a button in my windows 8 desktop app, which will have an image and a text block. I have to do this using C# coding.
My code is as follows,
Button btn = new Button();
StackPanel btnContentPanel = new StackPanel();
btnContentPanel.Orientation = Orientation.Horizontal;
Image img = new Image();
img.Source = new BitmapImage(newUri(#"C:\Users\Desktop\Images\download.jpg"));
img.Stretch = Stretch.Uniform;
btnContentPanel.Children.Add(img);
TextBlock txBlock = new TextBlock();
txBlock.Text = "My Button";
btnContentPanel.Children.Add(txBlock);
btn.Content = btnContentPanel;
This is not giving any error but the image is not getting displayed. If I add another text block in place of the image, then its appearing, but not the image.
Am I missing anything ? Please help, thank you.
Try building your button like this:
Button btn= new Button
{
Width = 30,
Height = 30,
Content = new Image
{
Source = new BitmapImage(#"C:\Users\Desktop\Images\download.jpg"))
}
};
In the case of a 'missing' image there are several things to consider:
When Xaml can't locate a resource it might ignore it (when it won't throw a XamlParseException)
The Resource must be properly added and defined:
make sure it exists in your project where expected.
Make sure it is built with your project as a Resource.
(Right click -> Properties -> BuildAction='Resource')
Another thing to try in similar cases, which is also useful for reusing of the image (or any other resource):
Define your Image as a Resource in your Xaml:
<UserCondrol.Resources>
<Image x:Key="MyImage" Source.../>
</UserControl.Resources>
And later use it in your desired control/controls:
<Button Content={StaticResource MyImage} />

Categories

Resources