I'm finding Xamarin.Forms XAML very frustrating.
If I use this syntax...
<ContentView.Resources>
<local:MyConverter1 x:Key="MyConverter1"/>
</ContentView.Resources>
I will get a System.NullReferenceException from InitializeComponent(). Nothing in the stack trace or output window or anywhere else tells me what is wrong.
Note: this syntax works fine in WPF.
After a lot of struggle I discovered I need this syntax...
<ContentView.Resources>
<ResourceDictionary>
<local:MyConverter1 x:Key="MyConverter1"/>
</ResourceDictionary>
</ContentView.Resources>
Likewise for ListView DataTemplate. This throws null reference exception...
<ListView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Converter={StaticResource MyConverter1}}"/>
</DataTemplate>
</ListView.ItemTemplate>
Because the proper syntax is this...
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Converter={StaticResource MyConverter1}}"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
Again this syntax works fine in WPF. I fully realize that Xamarin.Forms is not WPF but I getting weary of being sucker punched by null reference exceptions whenever I use a XAML construct that is valid in WPF.
What is the best way to debug Xamarin.Forms XAML issues?
Right now I am simply commenting stuff out until it starts working. This is akin to putting print statements in imperative code. Declarative code is supposed to be superior to imperative code.
What am I doing wrong?
This has tripped me up a few times too and I've been using Xamarin.Forms for 3 years now.
I mentioned that this was an issue on Twitter and was asked to raise it as an issue on Github.
https://github.com/xamarin/Xamarin.Forms/issues/1486
I added 2 examples which match with yours. If you can think of any more let me know and I'll add them.
Let's hope this gets fixed sooner rather than later.
Yeah, there isn't really a good way of debugging XAML. Turning on Xaml compilation will help. It compiles all your forms code into IL which makes it faster and finds these sorts of problems at compile time. You may also want to look into the new c# markup extensions. They are still in beta, but they let you write your declarative ui in straight c# with full intellisense.
Also, you may wish to switch from using ListView to using the newer CollectionView. It's much more performant and is basically an in-place upgrade. More info here.
I normally have 2 steps
add a try catch in code behind
using System;
using System.Diagnostics;
using Xamarin.Forms;
namespace TestApp.Views
{
public partial class AssetsPage : ContentPage
{
public WelcomePage()
{
try
{
InitializeComponent();
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
}
}
Remove code and keep on checking if the problem disappears
not really a magic solution but it helps the most especially when you have large groups of complicated code
Related
I made an application in WPF (.Net 4.7). For code protection, I am using .Net Reactor.
I am using following syntax to bind textblock to first element of list in my model.
<TextBlock Text="{Binding list[0].property1}"/>
This code works fine but after obfuscation, this code no longer works. I changed it to this
<WrapPanel DataContext="{Binding Path=list}">
<TextBlock Text="{Binding property1}"/>
</WrapPanel>
and this bind textblock to 'property1' of list first element (what I needed). I accidentally got this solution, I don't know if it is a proper way or not. I build application without obfuscation and above also works. Questions I have regarding this are
Why binding is not working like usual after obfuscation?
Using this method, does it always bind to first element of collection? If it always bind to first element, than I will continue deployment of application without wasting more time.
Sorry for bad English!!
I've got a bit of a niche scenario which I'm fully not expecting anyone to solve, but thought I'd give it a shot:
I have a Windows Forms User Control, which contains a single ElementHostcontrol that has it's Child property set to a WPF / XAML user control.
I'm getting some strange behaviour whereby the XAML contains something that looks like this:
<UserControl>
<UserControl.Resources>
<somenamespace:myresource x:Key="foo" />
</UserControl.Resources>
<Grid DataContext="{StaticResource foo}">
...
</Grid>
</UserControl>
I get a XamlParseException at runtime, asking me to Provide a value, even though it's clearly defined above.
I can see InitializeComponent() is being called, but that's as far as I can step.
In my code behind, in the WPF / XAML user control, if before InitializeComponent() is called I add:
this.Resources["foo"] = new myresource() everything works great again.
Just to confuse matters even further, this only happens when I use Visual Studio 2015 to compile the code - compiling using VS2013 (on the same machine/no solution changes whatsoever) works perfectly.
Has anyone got any ideas, or even helps on how to debug this?
I have a MapControl which is supposed to be filled with multiple objects (500+). These objects represent some kind of POI. When the user taps on the object (pushpin) I display more info about the POI. So, I need:
A MapControl capable of handling high amount of child objects
Intercept Tappedevent of the child object
In order to achieve the second goal I decided to define my own pushpin template:
<maps:MapControl x:Name="Map">
<maps:MapItemsControl ItemsSource="{Binding Pushpins}">
<maps:MapItemsControl.ItemTemplate>
<DataTemplate>
<Image Width="40"
Height="40"
Source="{ ... }"
Tapped="OnPushpinTappedAsync"
maps:MapControl.Location="{Binding Location}"
maps:MapControl.NormalizedAnchorPoint="{Binding AnchorPoint}" />
</DataTemplate>
</maps:MapItemsControl.ItemTemplate>
</maps:MapItemsControl>
</maps:MapControl>
This works great except for the fact that.. the visual out of such approach is AWFULL. Every time I move a map, every Pushpin flickers a lot. It's like they are not, I don't know, bound to the position. They are also lagging. It looks really bad. Rendering of those objects is really poor.
The alternative is to add elements to the MapControl's MapElements property. It makes rendering of those objects really nice.
But then I loose binding ability and will have to workaround it - I'm not a big fan of that. There's also a second problem - from what I've read, rendering objects of the MapElements collection is a best effort deal. So it does not guarantee that it will succeed. And that is not an option for me, as in the future I plan to add clustering functionality, so I need to have a full control over what is being rendered on the map and what is not.
Do you have any idea why these MapControl's elements flickers so much? What can I do to prevent it? Thanks in advance for any hint or answer.
I'm facing the exact same problem. Seems to me, that the MapControl is completely broken. There are many more bugs besides performance :(
You cannot really solve the problem, but you can create a "oldschool" WP8.0 Silverlight application and use something like this:
<Page xmlns:map="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps">
<map:Map Grid.Row="1" x:Name="myMap">
<tool:MapExtensions.Children>
<tool:MapItemsControl>
... and so on ...
This performs great but of course you have to change everything from Win(P)RT to Silverlight...
I too faced this problem, but I find this library to be usefull.
Hopefully Microsoft updates the MapControl for Windows 10.
Try this:
Tag="{Binding index_of_collection}"
and this:
OnPushpinTappedAsync()
int index = (int)(sender as Image).Tag; //index_of_collection
I am currently having an issue regarding this component.
This is the xaml usage of it in my app:
<telerikPrimitives:RadPickerBox x:Name="box_change" Width="0">
<StackPanel Background="White">
<StackPanel Height="618">
<PasswordBox Name="NewPassword1" Padding="2,8,2,8" Margin="10,0,10,0" Style="{StaticResource PasswordBoxStyle}" />
</StackPanel>
</StackPanel>
</telerikPrimitives:RadPickerBox>
I am currently in need of retrieving, from my C# code, the value "password" of the field "NewPassword1", still I am unable to do that.
I already tried retrieving it with something like this:
box_change.NewPassword1.Password
but, of course, else I wouldn't be asking this question right now, this way doesn't work.
What would you suggest to retrieve the value?
Thanks in advance,
Guido
this.NewPassword1.Password
Glad to help!
Have you considered using Telerik's RadPasswordBox for WP8? It's optimized for passwords with masking characters and other features (and easily provides you with the password):
var userEnteredPassword = myPasswordBox.Password;
That being said, even though your PasswordBox is the child of two StackPanels, you can access the Password box in the same scope via NewPassword1. If you have more complex controls see the control's documentation on how to get the value of a child element.
I'm trying to databind a Run of a TextBlock in code at runtime, and I can't for the life of me figure out how.
Several sources on the internet suggest this isn't possible without some (not too pretty) additional workarounds, and, more importantly, it should completely fail when you try to do it in XAML.
Yet, in my application I have the following, which works beautifully:
<DataTemplate x:Key="PitchTemplate">
<Grid Width="120" Height="120" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
TextAlignment="Center">
<Run Text="{Binding}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="36"/>
<LineBreak/>
<Run Text="{Binding Frequency, StringFormat=\{0:n2\}Hz}" FontFamily="{StaticResource PhoneFontFamilyNormal}" Foreground="{StaticResource PhoneSubtleBrush}"/>
</TextBlock>
</Grid>
</DataTemplate>
So I figured: If it can be done in XAML, it should be possible to do it in code.
Sofar, to no avail. Using the "regular" way of binding in code won't work; the Run class doesn't inherit from FrameworkElement, so doesn't have a SetBinding method, and it's Text property is not a DependencyProperty.
Using BindingOperations.SetBinding doesn't work because the Text property is not a DependencyProperty.
I'm up to the point that I'm willing to accept that it can't be done at runtime (although not without a last attempt at StackOverflow), but I'm still curious if
This can be done in code at runtime?
And if not:
How come it does work in XAML?
EDIT:
The example shown is just there to show that it can be done in XAML. The reason I need to create the bindings in code, is that I have a control that dynamically creates other elements, which need to be data bound.
UPDATE:
As Pete and I both found out, there is a dependency property for Text, but it's private. I assume that's why it does work through XAML (the xaml parser probably has more rights when it comes to reflection, and more knowledge in general about classes).
The upside is, that this means (tried & tested) it also works through XamlReader.Load(), which is (sofar) the cleanest solution I've come up with.
But if anyone has anything better, I'd be glad to hear about it.
Run.Text is backed by the private TextProperty which means you can't directly set its value without some reflection gimmicks, something like this:
Run r=new Run();
r.Text = "Moo";
var field=r.GetType().GetField("TextProperty", BindingFlags.Static | BindingFlags.NonPublic);
var dp=field.GetValue(null) as DependencyProperty;
BindingOperations.SetBinding(r, dp, new Binding {...});
This is rather ugly, but perhaps it can be useful.
You can find various workarounds for this. This SO post uses a custom attached property to configure binding. The attached property is used because Run is a sealed class in Silverlight so you can't create you own Run that supports binding.
The reason that it works in XAML but not in code-behind might be that there is a dependency property for Text, but it is private. It's a little bit 'black magic' to me though, so that's just a guess! This is a strange one, as in WPF the Run does inherit from FrameworkContentElement and has a SetBinding method...
Could you create a subclass of Run that contains a public DependencyProperty for text? I'm afraid I don't have the Silverlight dev tools to hand to try it out at the moment, but I'll try and take a look later.
Thanks both to Pete & Panagiotis for their efforts and suggestions (both 1 up).
In the end, I decided to go with my own solution (found in the "Update" section of the question): Create dedicated XAML strings containing the Run including the binding, and use XamlReader.Load() to parse it, and return a Run object.
The situation I'm working on is quite specific, so a local solution to the problem is good enough (for now). Reflection, as suggested by Panagiotis, won't work due to restrictions imposed by Silverlight. Lastly, the BindableRuns solutions would need either extensive work to deal with nested properties, or I would have to "uglify" my view model, so I discarded it (also for now).
Thanks all for your input.