Xamarin: Import one page from a different solution using MvvmCross - c#

I've got a Xamarin app using MvvmCross and I would like to exclude one page to a different Solution.
Is that possible at all?
I get following error displayed:
System.Collections.Generic.KeyNotFoundException: 'Could not find view for TestApp.ValidationViewModel2'
Details:
I've got a main app where I would like to navigate to the external page "ValidationViewModel2".
new MvxAsyncCommand(async() => await NavigationService.Navigate<ValidationViewModel2>())
To reach the page in the new solution I added a reference to the 'TestApp' assembly.
The 'TestApp' solution contains a a single C# project containing a "ValidationPage2.xaml" and a "ValidationViewModel2.cs" file. The two files find each other and the project builds successfully.
I can also debug from my main page into the 'ValidationViewModel2' constructor; The error occurs afterwards.
I'm using only Android. My ValidationViewModel2.cs has also references to the main app.
Thanks for helping

If you study the documentation for MvvmCross a bit you will find the documentation about Customizing App and Setup.
This doc describes that if you want to put ViewModels or Views in different assemblies than the default ones MvvmCross expects, you need to tell MvvmCross about it.
This can be done by overriding your Setup.cs file per platform.
For Views:
protected override Assembly[] GetViewAssemblies()
{
var list = new List<Assembly>(base.GetViewAssemblies());
list.Add(typeof(SomeTypeFromAdditionalViewAssembly).Assembly);
return list;
}
For ViewModels:
protected override Assembly[] GetViewModelAssemblies()
{
var list = new List<Assembly>(base.GetViewModelAssemblies());
list.Add(typeof(SomeTypeFromAdditionalViewModelAssembly).Assembly);
return list;
}

Related

XAML MarkupCompilePass2 fails on a WPF project

When I try to build my WPF project I get the folowing error:Samotorcan.Client.WPF.Windows8\Views\MainWindow.xaml(1,17): error MC3074: The tag 'Window' does not exist in XML namespace 'clr-namespace:Samotorcan.Client.WPF.Windows8.Controls'. Line 1 Position 17.The problem only occurs when I try to use linq. If I have a line like this new List<object>().ToArray<object>(); somewhere in the MainWindow.xaml.csfile I get the above error and if I change it to new List<object>().ToArray(); the error disappears and the project builds successfully.I also checked the build log and it contains the same error at task MarkupCompilePass2.I am using .NET Framework 4.5 and Visual Studio 2012.EDITAfter playing with it a bit I managed to find out that it's not specificly related to linq an random changes like removing an unused file from a project or just removing parts of code like a simple string creating string s = new String(); fixes the error.At one point a simple change in a constructor from this
public LoggedEventArgs(string message)
{
Message = message;
}
to this
public LoggedEventArgs(string message)
{
// Message = message;
}
fixed the error.
Managed to find a workaround for the above error by moving all my controls from the project into a separate project just for controls.
Now there are no random errors on build because as it looks like it can always find the window and other controls that are now in a separate assembly.

UIWebView throwing exception on LoadRequest

I have the following code trying to load a web page on my app:
Console.WriteLine("login view class");
NSUrl url = new NSUrl("http://deekor.com");
NSUrlRequest request = new NSUrlRequest(url);
loginWebView.LoadRequest(request);
The last line:
loginWebView.LoadRequest(request);
is throwing an System.Reflection.TargetInvocationException exception.
loginWebView is a UIWebView
Whats going wrong?
Edit
I think I was forgetting this line: loginWebView = new UIWebView(); After adding it the exception is gone... however the page is not loading..
Looking at the locals in debug I see loginWebView is set to null before I call loginWebView = new UIWebView();. Do I want to be creating a new one like this, or is something wrong with my outlet?
LoginViewController.Designer.cs
StoryBoard
#Deekor,
I loaded up a new project, and I tried to make exactly what you were making. I ran into the same issue if I followed these steps:
Create a new iPhone, single view, storyboard project.
Open up the storyboard file and drag a UIWebView onto the UIViewController that is created automatically in the new project.
Go back to Xamarin Studio and in the LoginViewController.cs file that was created for me, try to put in the loginWebView.Request code.
This doesnt work, as you noticed because the web view is null. It should not be. I don't know why, but there was also missing methods in that LoginViewController.cs file that is auto created. I could not override ViewDidLoad() which is where you want to be. Even though the class is inheriting from UIViewController, the override was just not available. So here is how I fixed the problem:
Delete the auto generated UIViewController in the Storyboard.
Delete the auto generated class that came with it (LoginViewController.cs)
Now in the storyboard, drag in a new UIViewController.
In the Custom Class box in interface builder, enter your class name: LoginViewController.
Go back to Xamarin Studio, and let it sync up and create the files for you again.
No go back to Interface Builder/Xcode and drag a UIWebView onto that new LoginViewController you created in step 3.
Drag your outlet for the loginWebView just as you did before.
Go back to Xamarin Studio and let it sync up.
Open your LoginViewController.cs file and now you can override ViewDidLoad().
Now you can simply have this:
public partial class LoginViewController : UIViewController
{
public LoginViewController (IntPtr handle) : base (handle)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
loginWebView.LoadRequest(new NSUrlRequest(new NSUrl("http://deekor.com")));
}
}
I don't know why sometimes the auto-generated files from a new project act strange, but basically all I did was delete what it created, and manually add the same thing again and then it worked. The web view being null when you launched is what made me think something was wrong. Please comment if something is confusing, I will do my best to explain better if I can. I did get this working following the steps above. In the image attached you can see it running in the simulator, showing your page.
Just to see what is happening try the following:
Console.WriteLine("login view class");
var webView = new UIWebView(this.View.Frame);
this.View.Add(webView);
NSUrl url = new NSUrl("http://deekor.com");
NSUrlRequest request = new NSUrlRequest(url);
webView.LoadRequest(request);
If that works it means it is an issue with how the WebView has been added to your Storyboard and then connected as an outlet...

Is it possible to use Gephi compiled with IKVM in a website?

I'm currently trying to load and use the Gephi Toolkit from within a .Net 4 C# website.
I have a version of the toolkit jar file compiled against the IKVM virtual machine, which works as expected from a command line application using the following code:
var controller = (ProjectController)Lookup.getDefault().lookup(typeof(ProjectController));
controller.closeCurrentProject();
controller.newProject();
var project = controller.getCurrentProject();
var workspace = controller.getCurrentWorkspace();
The three instances are correctly instantiated in a form similar to org.gephi.project.impl.ProjectControllerImpl#8ddb93.
If however I run the exact same code, with the exact same using statements & references, the very first line loading the ProjectController instance returns null.
I have tried a couple of solutions
Firstly, I have tried ignoring the Lookup.getDefault().lookup(type) call, instead trying to create my own instances:
var controller = new ProjectControllerImpl();
controller.closeCurrentProject();
controller.newProject();
var project = controller.getCurrentProject();
var workspace = controller.getCurrentWorkspace();
This fails at the line controller.newProject();, I think because internally (using reflector) the same Lookup.getDefault().lookup(type) is used in a constructor, returns null and then throws an exception.
Secondly, from here: Lookup in Jython (and Gephi) I have tried to set the %CLASSPATH% to the location of both the toolkit JAR and DLL files.
Is there a reason why the Lookup.getDefault().lookup(type) would not work in a web environment? I'm not a Java developer, so I am a bit out of my depth with the Java side of this.
I would have thought it possible to create all of the instances myself, but haven't been able to find a way to do so.
I also cannot find a way of seeing why the ProjectController load returned null. No exception is thrown, and unless I'm being very dumb, there doesn't appear to be a method to see the result of the attempted load.
Update - Answer
Based on the answer from Jeroen Frijters, I resolved the issue like this:
public class Global : System.Web.HttpApplication
{
public Global()
{
var assembly = Assembly.LoadFrom(Path.Combine(root, "gephi-toolkit.dll"));
var acl = new AssemblyClassLoader(assembly);
java.lang.Thread.currentThread().setContextClassLoader(new MySystemClassLoader(acl));
}
}
internal class MySystemClassLoader : ClassLoader
{
public MySystemClassLoader(ClassLoader parent)
: base(new AppDomainAssemblyClassLoader(typeof(MySystemClassLoader).Assembly))
{ }
}
The code ikvm.runtime.Startup.addBootClassPathAssemby() didn't seem to work for me, but from the provided link, I was able to find a solution that seems to work in all instances.
This is a Java class loader issue. In a command line app your main executable functions as the system class loader and knows how to load assembly dependencies, but in a web process there is no main executable so that system class loader doesn't know how to load anything useful.
One of the solutions is to call ikvm.runtime.Startup.addBootClassPathAssemby() to add the relevant assemblies to the boot class loader.
For more on IKVM class loading issues see http://sourceforge.net/apps/mediawiki/ikvm/index.php?title=ClassLoader

WPF resource loading fails in LoadFrom loading context

I have a WPF assembly that i use in an interop scenario from native code using the LoadFrom loading context like this:
AppDomain.CreateInstanceFrom("c:\mydlls\mywpfstuff.dll", "myclass")
Note that mydlls is not the same folder as where the executable is located. This works fine for regular non-ui .NET dlls that i also load, but when I try to do this I get an error. I attached the AppDomain.CurrentDomain.AssemblyResolve event handler and a get a an event where it fails to load. The Name in the ResolveEventArgs is "mywpfstuff.resources" and the RequestingAssembly is empty. I have no file named "mywpfstuff.resources" and could not figure out how to do this assembly resolving myself.
The code line that triggers the error is the InitializeComponent(); call in my main user controls constructor.
It seems to me that the internal XAML (BAML?) mechanisms tries to load some resources, but uses that standard Load context instead of the LoadFrom context.
Is there any way around this problem, preferably by getting WPF to use the LoadFrom context or if that is not possible how to do the assembly resolving manually?
I had similar problem in the past, due to localization issues and missing resx.
If the XAML uses resources from that assembly, double-check that the resources for the culture of the UI are actually available in the proper subfolder of c:\mydlls .
I had a similar scenario when I created this Unused References – VS2010 Add-in – top to bottom.
The problem is that the resources already loaded, and you cannot reload another resources.
Hope this helps...
I created a Start method to be accessed:
public static void Start()
{
if (Application.Current == null)
{
// create the Application object
App a = new App();
var l = a.Resources["Locator"] as Locator;
// do something with l
a.Run();
}
else
{
var locator = new Locator();
// do something with l
Application.Current.Resources.Remove("Locator");
Application.Current.Resources.Add("Locator", locator);
MainWindow main = new MainWindow();
main.Show();
}
}

Silverlight C# - ComponentOne Spellchecker not loading dictionary

This may be a long shot, but I'm using ComponentOne's Spellchecker control for Silverlight. I made a test project, added a plain textbox and a button to it, added the references to the C1.Silverlight and C1.Silverlight.SpellChecker bits, and added the dictionary file to my project.
In the code, I called up the spellchecker on button1's click event and it worked SPLENDIDLY. The spellchecker dialog shows up, and works exactly as it should.
Since that test was successful, I then tried to implement this into my existing project. I've had no success for absolutely NO reason that I can determine, since I used the EXACT SAME code.
Here's the code I use to call the component:
using C1.Silverlight;
using C1.Silverlight.SpellChecker;
using C1.Silverlight.Resources;
public partial class MainPage : UserControl
{
C1SpellChecker spellChecker = new C1SpellChecker();
public MainPage()
{
InitializeComponent();
spellChecker.MainDictionary.LoadAsync("C1Spell_en-US.dct");
}
private void btnSpelling_Click(object sender, RoutedEventArgs e)
{
var dlg = new C1SpellDialog();
spellChecker.CheckControlAsync(txtArticle, false, dlg);
}
The references to C1.Silverlight and C1.Silverlight.Spellchecker are added to this project as well, and the dictionary as been added in the same fashion as well. The issue seems to be that for whatever reason the dictionary is not loading, because the spellChecker.Enabled method returns whether or not the main dictionary has been loaded. If I call MessageBox.Show("SpellChecker Enabled = " + spellChecker.Enabled.ToString()); it shows false, even though the call to load the dictionary is there (as you can see).
What would cause the dictionary to not load? Have I added it to my project incorrectly somehow?
EDIT: I suspect that I have added the dictionary to the project incorrectly, because the ComponentOne reference states:
If C1SpellChecker cannot find the
spelling dictionary, it will not throw
any exceptions. The Enabled property
will be set to false and the component
will not be able to spell-check any
text.
I just don't know what's wrong though because it was added in the same way that it was in the test project (Right clicked on the project.web->Add->Existing Item)
As always, thank you!
-Sootah
You could add the dictionary to the Silverlight app as an embedded resource and then load it using this code:
public MainPage()
{
InitializeComponent();
// load C1SpellChecker dictionary from embedded resource
var asm = this.GetType().Assembly;
foreach (var res in asm.GetManifestResourceNames())
{
if (res.EndsWith(".dct"))
{
using (var s = asm.GetManifestResourceStream(res))
{
sc.MainDictionary.Load(s);
break;
}
}
}
}
I think this post is duplicated in our forum as well, but will answer first here. Please try this:
1) Try to access the .dct file using your browser. If you cannot see it, it's probably because your web server is not serving that type of files. You need ton configure the web server to allow it.
2) verify the URL you are using is correct.http://helpcentral.componentone.com/CS/silverlight_161/f/78/p/86955/241328.aspx#241328
3) Check you are setting everything correctly: http://helpcentral.componentone.com/CS/silverlight_161/f/78/p/81924/227790.aspx#227790
Hope this helps!

Categories