StaticResource is null even though it's defined in XAML? - c#

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?

Related

WPF - xaml's binding not working after obfuscation

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!!

How do I subclass Canvas in WPF (C#) and add it to the main Window through XAML? [duplicate]

This is my first foray into custom controls, and it's not going well. I have a custom graph control derived from Canvas.
namespace Grapher2 {
public class SeriesManager : Canvas {
public SeriesManager() {
...
}
}
}
It's defined in the same project and namespace as my app. I tried adding a reference to the control in XAML as follows:
<Window x:Class="Grapher2.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:graph="clr-namespace:Grapher2"
Title="Grapher" Width="800" Height="600">
<StackPanel Name="container" Width="700" Height="500">
<graph:SeriesManager Name="seriesManager" Width="700" Height="500" />
</StackPanel>
But when I try to reference the control name "seriesManager" in the code-behind for the Window, I get "The name 'seriesManager' does not exist in the current context."
Furthermore, the XAML editor will not render the Window, giving a huge stack trace with the error: "Type 'MS.Internal.Permissions.UserInitiatedNavigationPermission' in Assembly 'PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' is not marked as serializable."
I imagine the solution is something stupidly simple for anyone who's done custom controls. But I'm stumped.
did you try x:Name="seriesManager" in your xaml?
Edit: This may not be the issue seeing how you said your xaml isn't rendering. I'm guessing once you get the xaml to render in the designer... the code behind will work better.
Edit 2: Whenever I've had a problem with the designer rendering, it's because I'm doing something in the constructor of my custom control. Check your SeriesManager to see if you are doing something in its constructor that is causing a problem. Maybe you are referencing something that doesn't exist yet. If you do have extra code in your constructor, consider moving it to the UserControl_Loaded event.
Backing up Scott's answer here, since he helped me solve it:
What I did wrong was trying to access the control BEFORE InitializeComponent(), but was confused by 2 other error messages somewhere else in the code.
Just in case someone else has this error.

How to debug Xamarin.Forms XAML

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

Wpf design ; multiple views in one window

Im building an application where I want to head for a design, that could remind of a dockpanel.
What I want, is having buttons in the left side (or left panel) representing different areas of the application (e.g "Milk", "Bread") and then have different "views" in the middle-panel.
What I already have tried, is making an application with a "Frontpage", and buttons changing the whole window/usercontrol - this however will not give me static areas/panels.
I do not want to use a tabcontrol with the tabtitemstrip being vertical - however it is kinda the same functionality im looking to have.
Any ideas?
Below is a picture with the wished design, to kinda give an idea of my thoughts.. Any help appreciated :)
http://s57.photobucket.com/user/RolleKn/media/wpfdesign_zps3737b014.jpg.html
If you use WPF, use ContainerControl or ContentPresenter for that.
In general, "switching Visibility On/Off" is not a good way to go. It forces the UI to create all objects, even those invisible ones, and to handle their data and events, etc.
And you need to switch it all manually.
WPF provides you with many mechanisms that can save you this. Some are smarter than others, some not.
One of the most basic mechanism in WPF is the Control and its Template property. You can replace whole your Grid+Contents+SwitchingVisibility idea with a single Control and switching its Template:
<Window.Resources>
<ControlTemplate x:Key="panel1"> ..carrots.. </ControlTemplate>
<ControlTemplate x:Key="panel2"> ..cucubers.. </ControlTemplate>
<ControlTemplate x:Key="panel3"> ..donkey.. </ControlTemplate>
...
</Window.Resources>
<Grid x:Name="LayoutRoot">
<Control x:Name="foo" />
</Grid>
Now, if you get the foo and set its .Template and set it to panel1, then the "carrots" will show up. if you set it to panel3, donkeys. And so on.
It's very powerful, but it will not be really handy due to some other things I won't cover. There are books and tutorials that explain Templates in depth. Also, this mechanism is really not designed for such task. It's the most basic one, and a good thing to know if you want to work in WPF, but there are more suitable ones here.
Second next powerful and still basic mechanism is ContentControl/ContentPresenter. They work almost in the same way (actually CC uses CP internally), so I'll skip it.
ContentControl is a smart control that knows how to automatically select a correct Template with respect to the data you are tryng to present.
So:
<Window.Resources>
<DataTemplate DataType="CarrotData"> ..carrots.. </..>
<DataTemplate DataType="CucumberData"> ..cucubers.. </..>
<DataTemplate DataType="DonkeyData"> ..donkey.. </..>
...
</Window.Resources>
<Grid x:Name="LayoutRoot">
<ContentControl x:Name="foo" Content="{Binding ..}" />
</Grid>
Note the change from 'ControlTemplate' to 'DataTemplate'.
Now, with this setting, you don't even need to switch templates manually. You just get the "foo" and set its Content to either:
a CarrotData object, that contains the carrot-related data
a CucumberData object, that contains the cucumber-related data
a DonkeyData object, that contains the donkey-related data
Once you set the data to be shown (i.e. foo.Content = carrots[5]), the ContentControl will pick the relevant template to be shown.
You can bind the Content property to just about anything. If you have some dataclass that contains carrots/donkeys and has a property CurrentThing, you can bind to it and ContentControll will switch the views automatically along with the changes to CurrentThing.
That's basics. There's much more to it, in almost any point I tried to briefly cover. For now, leave ControlTemplates. Read about DataTemplates and Bindings. Read about ContentPresenter (shows 1 template for 1 item) and ItemsControl (shows N items+templates). Then, read a little on MVVM pattern.
You will quickly see that "having everything in one Grid" and "switching Visibility" is an odd way to do it.
However, I wouldn't be fair if I didn't mention that everything has a cost included. Extensive use of templates and bindings makes your app a bit slower compared to what you could get when you do everything manually. But usually, doing it manually is just not really worth it.

WPF cannot access nested control

Wondering if there's any trick to accessing a nested control in the code-behind ?
given some XAML along the lines of
<UserControl>
<textbox />
<DataGrid Name="MyGrid">
<Columns>
<Column field=ABC>
<EditType>
<ComboBox Name="myCombo1"/>
I can access this.MyGrid but cannot access this.myCombo1 !!
Everytime that I have run into this I have be able to resolve it by using x:Name instead of Name. This may not be the issue in your case but give it a try.
In simple cases you can access elements using their name, but looks like combobox is datatemplate part, you can work with visual tree at runtime using VisualTreeHelper, but if you use mvvm & code right usually you don't need to access elements directly. Can you provide more information on general problem or test project to reproduce issue?

Categories