When using the exact same code in a UWP App an Xamarin Forms app, I get the following error on the Xamarin.Forms program but not on the UWP program.
Error CS0012 The type 'IAsyncOperation<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'Windows.Foundation.FoundationContract, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime'.
Here is my code.
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
Task task = CopyAssetsDatabase();
}
private async Task CopyAssetsDatabase()
{
StorageFile file;
var root = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
var dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "ExpressEMR.db");
try
{
file = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFileAsync("ExpressEMR.db");
}
catch
{
StorageFile Importedfile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/ExpressEMR.db"));
file = await Importedfile.CopyAsync(Windows.Storage.ApplicationData.Current.LocalFolder);
}
throw new NotImplementedException();
}
'IAsyncOperation<>' Xamarin Forms
The problem is that you have missed System.Runtime.WindowsRuntime assembly, you could add it manually. right click the Dependencies Add reference-> Browse -> find it from this path (C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll).
Update
That assembly should be added automatically to a Xamarin Forms app, correct? I mean I have never had to add it manually before.
Sure, but in early version, we need add the reference manually. And I checked your thread again, I found you used StorageFile in forms app class. However, StorageFile is specific class for uwp platform please avoid use it in forms, if you want to file access, you could dependency service to access file for each platform.
Related
I am using Visual Studio for Mac 7.6.6 to create a Xamarin.Forms app targeting macOS (to be shared with something running on Windows). I create a new Project and select
Multiplatform App | Blank Forms App. Click Next
Configure your Blank Forms App. There are target platforms: Android and iOS.
(There is nothing for macOS). Since I have not installed the build toolkits for either iOS and android, both of these checkboxes are disabled. Therefore the Next button on this wizard page is disabled.
How do I proceed? I assume there is no way to use the New Project wizard for this.
I came across an old post for starting with a Xamarin Cocoa app and using NuGet to put the Xamarin Forms functionality but don't understand the code
LoadApplication(new App()); // <-- don't know what App is
I suspect the VS Mac and Xamarin.Forms are out of sync being on the bleeding edge. Has anyone gotten this to work?
I would suggest following SushiHangover's suggestion since that is simpler which is what you have done already:
Add a new CocoaApp project to your solution.
Install Xamarin.Forms NuGet package into your CocoaApp.
Reference the shared project or .NET Standard project from your CocoaApp project.
Edit info.plist and remove the source entry (NSMainStoryboardFile).
Change the AppDelegate to derive from Xamarin.Forms.Platform.MacOS.FormsApplicationDelegate.
Update Main.cs to initialize the AppDelegate
In the AppDelegate's DidFinishLaunching add the code to initialize Xamarin.Forms.
Create a new NSWindow which should be returned from the MainWindow property in the AppDelegate.
Main.cs:
static class MainClass
{
static void Main(string[] args)
{
NSApplication.Init();
NSApplication.SharedApplication.Delegate = new AppDelegate();
NSApplication.Main(args);
}
}
AppDelegate.cs:
[Register("AppDelegate")]
public class AppDelegate : Xamarin.Forms.Platform.MacOS.FormsApplicationDelegate
{
NSWindow window;
public AppDelegate()
{
var style = NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Titled;
var rect = new CoreGraphics.CGRect(200, 1000, 1024, 768);
window = new NSWindow(rect, style, NSBackingStore.Buffered, false);
window.Title = "Xamarin.Forms on Mac!";
window.TitleVisibility = NSWindowTitleVisibility.Hidden;
}
public override NSWindow MainWindow
{
get { return window; }
}
public override void DidFinishLaunching(NSNotification notification)
{
Xamarin.Forms.Forms.Init();
LoadApplication(new App());
base.DidFinishLaunching(notification);
}
public override void WillTerminate(NSNotification notification)
{
// Insert code here to tear down your application
}
}
However Visual Studio for Mac does include a Mac project with the Xamarin.Forms project templates. However it does not expose this in the New Project dialog currently. You can create a Mac Forms project from this template but it is a bit more work than what SushiHangover suggested and you have used.
Install the Xamarin.Forms project template into the .NET Core project templates
dotnet new --install "/Applications/Visual Studio.app/Contents/Resources/lib/monodevelop/AddIns/Xamarin.Forms.Addin/Templates/Xamarin.Templates.Multiplatform.0.0.1.nupkg"
Create a new Forms project including the Mac project (you may want to review and set other template parameters - the following creates a blank Forms app with Android, iOS, Mac, UWP and a Shared project).
dotnet new forms-app --CreateMacProject -k blank
Create a new blank solution (Other - Miscellaneous - Blank Solution) in the parent directory of the projects you just created.
Add all those projects created to the solution.
Then you can build and run the Mac project which includes Xamarin.Forms.
Note you may want to remove the Xamarin.Forms project template from the .NET Core project templates which you can do by running the following:
dotnet new --debug:reinit
In addition to the approved answer, which is incomplete with recent updates, now you have to do one more step.
Link the delagate in the Mac project main class
main.cs:
static class MainClass
{
static void Main(string[] args)
{
NSApplication.Init();
NSApplication.SharedApplication.Delegate = new AppDelegate();
NSApplication.Main(args);
}
}
nota. My edit was refused and I'm not allowed to add comments. So I added a complementary answer to help those looking for help now.
Recently I asked a question over trying to get my theme recognized within the android test project: Unit testing a Xamarin Forms Android specific code project
I'm not running into a conflict that shows up within xunit / nunit as the testing strategy. I feel like it's because the FormsAppCompatActivity with an older activity type, but I'm new to Xamarin and am unsure on how to approach this.
I get a lot of these type of errors:
Attribute "layout_anchorGravity" already defined with incompatible format.
The full list of the similar Attribute errors is:
fabSize
tabMode
expandedTitleGravity
layout_scollFlags
layout_collapseMode
collapsedTitleGravity
tabGravity
showDividers
displayOptions
showAsActions
actionBarSize
finally I have the addition error:
Found tag styles where item is expected
//Within the Android Forms project, I have this inheritance:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity {
// typical code
}
//within the Android UITest project
public class MainActivity : Xunit.Runners.UI.RunnerActivity {
// tests can be inside the main assembly
AddTestAssembly(Assembly.GetExecutingAssembly());
AddExecutionAssembly(typeof(ExtensibilityPointFactory).Assembly);
// or in any reference assemblies
//AddTestAssembly(typeof(PortableTests).Assembly);
// or in any assembly that you load (since JIT is available)
#if false
// you can use the default or set your own custom writer (e.g. save to web site and tweet it ;-)
Writer = new TcpTextWriter ("10.0.1.2", 16384);
// start running the test suites as soon as the application is loaded
AutoStart = true;
// crash the application (to ensure it's ended) and return to springboard
TerminateAfterExecution = true;
#endif
// you cannot add more assemblies once calling base
base.OnCreate(bundle);
}
I downloaded a copy of the current Xamarin Forms master branch, compiled it, and then I added these compiled assemblies as references to a test project:
Xamarin.Forms.Core
Xamarin.Forms.Platform
Xamarin.Forms.Platform.Android
Xamarin.Forms.Xaml
The test project was created using the Visual Studio Xamarin Forms project template, the only thing I modified is the references in the Core.csproj and Android.csproj to point to the compiled assemblies.
I used the first 3 from the bin\debug\ folder of the Xamarin.Forms.Platform.Android project, and the last one from the Xamarin.Forms.Xaml bin\debug folder.
I run the test project, and it runs fine, I can see the label from the default generated code "Welcome to Xamarin Forms!"
Next, I just modified the MainPage like this:
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new ContentPage());
}
}
When I run the app, it gives me an error
System.ArgumentException: element is not of type Xamarin.Forms.View
Parameter name: element
thrown on this line:
void IVisualElementRenderer.SetElement(VisualElement element)
{
if (!(element is TElement))
throw new ArgumentException("element is not of type " + typeof(TElement), nameof(element));
SetElement((TElement)element);
}
which is strange.
The type of the element is Xamarin.Forms.NavigationPage and the stack trace is
Can someone help me running the test project with the compiled assemblies?
UPDATE #1:
The 2nd entry in the call stack shows that it's not able to get the registered renderer(NavigationPageRenderer) for the NavigationPage element and instead it's creating a default renderer(DefaultRenderer), which can't handle the type of element(NavigationPage) so it's throwing the exception I see.
So it appears that for NavigationPage, it doesn't find its renderer(NavigationPageRenderer) in the Registrar.
public static IVisualElementRenderer CreateRenderer(VisualElement element)
{
UpdateGlobalContext(element);
IVisualElementRenderer renderer = Registrar.Registered.GetHandler<IVisualElementRenderer>(element.GetType()) ?? new DefaultRenderer();
renderer.SetElement(element);
return renderer;
}
My feeling is there's a build step I'm not aware about when building Xamarin Forms.
Its crashing as you are calling InitializeComponent on something which doesn't derive from a Forms.Page (i.e. ContentPage etc).
The application itself is not a Page, if you had a page, lets call it 'MyCustomPage' which has some Xaml behind the class would look something like this:
public partial class MyCustomPage : ContentPage
{
public MyCustomPage()
{
InitializeComponent ();
// Some other setup...
}
}
Then in your App constructor you would call
MainPage = new MyCustomPage();
Since you are creating a blank content page from the root of your app, you do not need to call InitializeComponent.
Hope this helps.
You also need to reference
Xamarin.Forms.Platform.Android (Forwarders)
from your Android project.
I am working on a tool to generate assemblies for WP7. I am doing this from the full framework. Since Reflection.Emit doesn't work with WP7 but either CCI or Mono.Cecil do I am wondering if there is a way to create new assemblies from scratch. I already know that I can modify existing assemblies, but being able to create one would be pretty useful.
I guess a workaround would be to generate an empty assembly in visual studio and keep it as a template, but I think that there should be a better way.
It's pretty easy to do with Mono.Cecil:
using Mono.Cecil;
using Mono.Cecil.Cil;
class Demo
{
static void Main()
{
var winphoneAssemblies = #"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\Profile\WindowsPhone";
var assemblyResolver = new DefaultAssemblyResolver();
assemblyResolver.AddSearchDirectory(winphoneAssemblies);
var winphoneCorlib = assemblyResolver.Resolve("mscorlib");
var module = ModuleDefinition.CreateModule("Test", new ModuleParameters
{
AssemblyResolver = assemblyResolver,
Runtime = TargetRuntime.Net_2_0,
Kind = ModuleKind.Dll,
});
// trick to force the module to pick the winphone corlib
module.Import(winphoneCorlib.MainModule.GetType("System.Object"));
var type = new TypeDefinition("Test", "Type", TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract, module.TypeSystem.Object);
module.Types.Add(type);
var method = new MethodDefinition("Identity", MethodAttributes.Public | MethodAttributes.Static, module.TypeSystem.Int32);
method.Parameters.Add(new ParameterDefinition("i", ParameterAttributes.None, module.TypeSystem.Int32));
type.Methods.Add(method);
var il = method.Body.GetILProcessor();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
module.Write("Test.dll");
}
}
A few things to note:
The need to create the module with an assembly resolver targeting the winphone assemblies.
A little trick to make sure the module picks up the proper winphone mscorlib (will be fixed in the next version of Cecil).
Silverlight assemblies have the metadata version of the .net 2.0 framework.
It's worth pointing out that while you may be able to generate dynamic assemblies from within the phone's runtime using alternate framework's, you're not goint to be able to load / execute them. Those APIs will throw an exception if executed by application code.
First, I know Silverlight project can't reference to non-Silverlight based project like Windows class library or Asp.net MVC project. But I need to create my projects which can support both Silverlight-based project & Asp.net MVC project.
So, I created Silverlight-based project for my sharing source code. It works fine on VS.net 2008 & .Net 3.5 SP1. However, I found some error when I try to use some method of Silverlight-based project from .Net-based project like the following code.
Silverlight-based Method
public static void InitializeInstance(object obj)
{
// Initialize Field Value
foreach (FieldInfo fi in obj.GetType().GetFields())
{
foreach (Attribute attr in fi.GetCustomAttributes(true))
{
if (attr is DefaultValueAttribute)
{
DefaultValueAttribute dv = (DefaultValueAttribute)attr;
fi.SetValue(obj, dv.Value);
}
}
}
// Initialize Property Value
foreach (PropertyInfo pi in obj.GetType().GetProperties())
{
foreach (Attribute attr in pi.GetCustomAttributes(true))
{
if (attr is DefaultValueAttribute)
{
DefaultValueAttribute dv = (DefaultValueAttribute)attr;
if (pi.CanWrite)
{
pi.SetValue(obj, dv.Value, null);
}
}
}
}
}
.Net-based Method
private void Form1_Load(object sender, EventArgs e)
{
InitializeInstance(this);
}
Error Detail
System.IO.FileNotFoundException:
Could not load file or assembly
'System, Version=2.0.5.0,
Culture=neutral,
PublicKeyToken=7cec85d7bea7798e' or
one of its dependencies. The system
cannot find the file specified. File
name: 'System, Version=2.0.5.0,
Culture=neutral,
PublicKeyToken=7cec85d7bea7798e' at
InitializeInstance(Object obj)
Finally, I try to solve this problem by copying system.dll of Silverlight to output directory and reference it. It still shows same error. So, I think this error may be limitation of both .Net & Silverlight platform. Do you have any idea for avoid this issue?
PS. I know I can use this technique for a few sharing code. But it’s impossible to do this for my projects. Because it’s very complicate & very complex more than directly create Silverlight-based or .Net-based class library.
Thanks,
The trouble here is that those types share an assembly with a different strong name: System.Windows in Silverlight, PresentationFramework or PresentationCore on the desktop CLR.
So at runtime, the intended type cannot be loaded, and there are no type forwarders for the Silverlight-to-desktop types.
My recommended solution
Consider using file links, instead of actually trying to reference the same built binary.
This way, you can have a source structure for your project that may look like this:
MyApp\
Silverlight\
Page.xaml
Page.xaml.cs
(link) ..\AspMvc\MySharedDataFile.cs
AspMvc\
MySharedDataFile.cs
MyApp.cs
This way, the source will be re-compiled with both projects. We use this on the Silverlight Toolkit to build many controls, including the charting and data visualization controls, for both WPF and Silverlight. This is by rebuilding for each platform, instead of referencing the binaries from both.
To insert a link in Visual Studio, just right-click on your project or one of its folder, Add Existing Item, then find it in the explorer open file dialog. however, instead of just clicking the button, click on the little down arrow drop-down on the Add file button, and select the "Add as link" option.
Then, it simply builds that file from another location, but it is not a copy, so you can maintain it in one place and use in both.
A crazy solution
You can use .NET reflection from your desktop app that is of a much higher trust to actually create a new app domain, hook up to the assembly resolution event, and see what that does. You may be able to instead return the type from the desktop CLR, or just no-op these warnings.
No clue if it works.