F# quotations on Windows Phone - silverlight

I'm using Daniel Mohl's F# templates for Windows phone, but it seems the bundled FSharp.Core doesn't have some of the quotations code. I'm trying to port this code from regular .NET:
open System.ComponentModel
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
[<AbstractClass>]
type ViewModelBase() =
let propertyChanged = new Event<_, _>()
let toPropName expr =
match expr with
| PropertyGet(a, b, list) -> b.Name
| _ -> failwith "Unsupported: " + expr.ToString()
interface INotifyPropertyChanged with
[<CLIEvent>]
member x.PropertyChanged = propertyChanged.Publish
member x.NotityPropertyChanged expr =
propertyChanged.Trigger(x, new PropertyChangedEventArgs(toPropName expr))
But the compiler complaints about Microsoft.FSharp.Quotations.Patterns and PropertyGet. It seems it doesn't even know the Expr type.
Any idea on how to solve this?

I replaced the FSharp.Core file that comes in the template by the one that comes in the F# April 2011 CTP in the WindowsPhone7\Silverlight\4.0\bin folder, and with this version it now compiles fine

I've compared FSharp.Core.dll from Template you've mentiond and those one which is referenced if you create a F# Silverlight library with .Net Reflector and they are different! :) Thouse one which added to template's dependencies folder doesn't have Quotations.
So my first two thoughts is either add F# SCL and create your view model there or not to use this template at all. But I actually like this template or how it looks at least... so thanks you for the mentioning it anyway :)

Related

XAML How to get a project name

Im learning XAML with microsoft visual studio 2013 wpf application.
I want to make a textblock display my Project Name from a some kind of resource(?) - I want to make a template :) .
Thank you for help in advance :) .
string name = Assembly.GetEntryAssembly().GetName().Name;
or
string name = Assembly.GetExecutingAssembly().GetName().Name;
Alternatively, you can get the Assembly object from any known type in the assembly:
Assembly assy = typeof({class name here}).Assembly;
This also allows another option to get the the name only:
string name = typeof({class name here}).Assembly.GetName().Name;
Here's the link

Can't find file with UserControl but not (in this case) Label

I have a UserControl in a the DLL Controls, a converter in the DLL Base and language resources in the DLL Languages.
When I combine everything the following way, everything works fine:
<Label Content="{Binding FallbackValue='[Design] Name', ConverterParameter='Name', Converter={StaticResource Translate}}"
ContentStringFormat="{}{0}:"/>
No errors and when I run my application the correct word for the parameter Name is loaded (in my case Naam for Dutch).
I also try this on my WatermarkTextBox like this:
<c:WatermarkTextBox Watermark="{Binding FallbackValue='[Design] Name *', ConverterParameter='Name', Converter={StaticResource Translate}}" />
But then I get the following error:
Could not load file or assembly 'file:///C:...\Languages.dll' or one of its dependencies. The system cannot find the file specified.
Why does this happen with my WatermarkTextBox in Controls DLL and not with the Label?
The first step here is to make sure, that the assembly file Languages.dll is actually present in the application directory (usually, bin/Debug/). If it isn't - as the error message says - the system cannot find the file specified... The solution in this case is to reference the assembly Languages.dll in your application project. To avoid this, make sure that every time you add a reference to an assembly, you also add references to this assembly's dependencies. I.e. if you have an application project App which references a library LibA.dll and LibA references a library LibB.dll, you should add a reference to LibB.dll in your App project as well. That way, all required assemblies will always be copied to the output directory.
If the assembly is correctly located in the output directory, but you still get the error message, in 99% of the cases the problem is a mismatch in the building targets, alas the platform for which the assemblies were built. Make sure all projects target the same platform (x86, for example). You can check the target in the projects Properties tabs.
EDIT:
Ok, I just now understood you're talking about the design time error in Visual Studio's XAML Designer :) The issue is the name of the assembly: Noru.Languages.dll. I suppose, the ending .Languages is considered a resource name and Visual Studio prohibits resource names in assembly names. There's a registry entry HKLM\Software\Microsoft\VisualStudio\12.0\Designers\AllowResourcesInFilename, maybe experimenting with that can resolve the issue. Not 100% sure, though. Anyway, if you rename the assembly to Nori.Language.dll in the project's properties and rebuild everything, design time support is back and the controls show up correctly in the designer.
EDIT 2:
Really strange behavior altogether... Well, this line in the Class Language might very well be the cause? Try specifying the full string here... Does this work?
ResourceManager rm = new ResourceManager("Noru.Languages.Language", System.Reflection.Assembly.LoadFrom("Noru.Languages.dll"));
EDIT 3:
Obviously, the problem was the line I mentioned above in Edit 2. I've experimented a bit:
/// <summary>
/// Will return the requested text in the language the application is in. Case sensitive.
/// </summary>
/// <param name="s">Provide a listed String from the language files.</param>
/// <returns>Will return a System.String in the language of the application.</returns>
public static string GetText(string s)
{
//return Culture.ToString();
//return Assembly.GetExecutingAssembly().FullName;
//ResourceManager rm = new ResourceManager("Noru.Lang.Resource1", Assembly.GetAssembly(typeof(Language)));
//ResourceSet rs = rm.GetResourceSet(Culture, true, true);
var rs = LanguageResource.ResourceManager;
try
{
return rs.GetString(s);
}
catch (Exception)
{
return "not found";
}
}
The last version (not commented out) works, because I've generated code for the resource files by setting AccessModifier to public in the resource editor (double click on the resource file, you'll find it in the toolbar).
This version (never mind about the resource name, I tried different versions here):
ResourceManager rm = new ResourceManager("Noru.Lang.Resource1", Assembly.GetAssembly(typeof(Language)));
threw another error, saying it cannot find the resource inside the assembly. I think there was something wrong about the usage of ResourceManager here. I'm not an expert here, so I can't tell why. I just know that the last version seems to work as expected... I hope, you'll find the same ;)

F# WPF events: "Block following this 'let' is unfinished. Expect an expression"

This is driving me nuts. I am looking here at Microsoft's function examples.
I can't see what I am doing wrong.
So, I am trying to use F# with WPF, I found a working online project template for it. Here it is .I was about to get started. Unfortunately, the designer does not work for generating events in the F# code by double clicking an element like it does in C#. But oh well, I can set what the Click does anyway. I decided I would do it all manually.
Here is my flawed attempt:
module MainApp
open System
open System.Windows
open System.Windows.Controls
open FSharpx
let mutable doc = ""
type MainWindow = XAML<"MainWindow.xaml">
let loadWindow() =
let window = MainWindow()
// Your awesome code code here and you have strongly typed access to the XAML via "window"
window.Root
let make (sender:Object, e:RoutedEventArgs) =
doc<- doc +"<?xml version=\"1.0\" standalone=\"no\"?>"
0
[<STAThread>]
(new Application()).Run(loadWindow()) |> ignore
In any event, It does not like the line with let make on it. It gives me this error:
Block following this 'let' is unfinished. Expect an expression
And yet, clearly I read on the MSDN
The compiler uses the final expression in a function body to determine the return value and type
So, it has a return, how is it an unfinished expression?
You are supposed to return window.Root from loadWindow. Right now the last bit of code inside loadWindow is the declaration of a make function, which is not valid. Remember, indentation determines scope in F#.
If you wanted to add a new function make, but leave the body of loadWindow basically empty, you need to align the indentation properly:
let loadWindow() =
let window = MainWindow()
// Your awesome code code here and you have strongly typed access to the XAML via "window"
window.Root
let make (sender:Object, e:RoutedEventArgs) =
doc<- doc +"<?xml version=\"1.0\" standalone=\"no\"?>"
0

Reflection error when using F# sprintf "%A" on Windows Phone

I have a set of F# record types like this:
type Course =
{ Id : int
Title : string
Instructor : string
Duration : string
StartDate : string
IconUrl : string
Url : string
LectureSections : LectureSection list }
and LectureSection =
{ Title : string
Completed : bool
Lectures : Lecture list }
and Lecture =
{ Title : string
VideoUrl : string }
and at some point I call
sprintf "%A" course
where course is an instance of the Course record
On a regular .NET project this works fine, but on a Windows Phone 7.1 / Silverlight 4 F# project (I'm using Daniel Mohl's templates), I get this error:
Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
The problem seems to be the lists. Does anyone know of any way around this problem?
The templates should come with a custom built FSharp.Core.dll that disable features that are not available on Windows Phone. Are you sure you are compiling against this dll, and not the Windows PC one?
I had similar problems with Xbox360 and XNA. The F# team sent me a dll suitable for use for the Xbox360, along with some brief instructions on the settings used to build the dll.
Here is the propertygroup we've used to compile FSharp.Core:
<PropertyGroup Condition="'$(TargetFramework)'=='Xbox360\CompactFramework\3.7'">
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
<XnaPlatform>Xbox 360</XnaPlatform>
<XnaProfile>HiDef</XnaProfile>
<XnaCrossPlatformGroupID>a8d70e6b-9a75-4aec-80f8-62cf373f7368</XnaCrossPlatformGroupID>
<XnaOutputType>Game</XnaOutputType>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<DefineConstants>$(DefineConstants);FX_NO_ARRAY_LONG_LENGTH;FX_NO_DEBUG_PROXIES;FX_NO_EXIT;FX_FSLIB_IOBSERVABLE;FX_NO_WEB_CLIENT;FX_NO_WEB_REQUESTS;FX_NO_CHAR_PARSE;FX_NO_DEFAULT_DEPENDENCY_TYPE;FX_SIMPLE_SECURITY_PERMISSIONS;FX_NO_TRUNCATE;FX_NO_CULTURE_INFO_ARGS;FX_NO_REFLECTION_MODULE_HANDLES;FX_NO_OPERATION_CANCELLED;FX_NO_TO_LOWER_INVARIANT;FX_NO_EXIT_CONTEXT_FLAGS;FX_NO_BASED_ARRAYS;FX_NO_DOUBLE_BIT_CONVERTER;FX_NO_BINARY_SERIALIZATION;FX_NO_ASCII_ENCODING;FX_NO_DEFAULT_ENCODING;FX_NO_FILE_OPTIONS;FX_NO_NONBLOCK_IO;FX_NO_COMMAND_LINE_ARGS;FX_NO_ENVIRONMENT;FX_NO_PROCESS_START;FX_NO_APP_DOMAINS;FX_NO_PROCESS_DIAGNOSTICS;FX_FSLIB_STRUCTURAL_EQUALITY;FX_FSLIB_LAZY;FX_FSLIB_TUPLE;FX_NO_REFLECTION_EMIT</DefineConstants>
<Tailcalls>false</Tailcalls>
<!-- It would be better to use MSBuild resolution here, but the TargetFrameworkIdentifier etc. aren't set up quite correctly as yet -->
<OtherFlags>$(OtherFlags) --simpleresolution -r:"C:\Program Files\Microsoft XNA\XNA Game Studio\v4.0\References\Xbox360\mscorlib.dll"</OtherFlags>
</PropertyGroup>
and the new .targets we use:
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.targets" Condition="'$(TargetFramework)'=='Xbox360\CompactFramework\3.7'"/>
The dll they sent me was working fine, and I never had to use these instructions, but they might be useful to someone who wants to build an FSharp.Core.dll for a new platform. Note in particular the DefineConstants part.

How-to: Load a type from a referenced assembly at runtime using a string in Silverlight

I have tried this, specifying the assembly name:
Type.GetType(string.Format("{0}.{1}, {0}", typeToLoad.AssemblyName, typeToLoad.ClassName));
Which throws the following:
The requested assembly version conflicts with what is already bound in the app domain or specified in the manifest
Trying the same without including the trailing assembly name like this:
Type.GetType(string.Format("{0}.{1}", typeToLoad.AssemblyName, typeToLoad.ClassName));
-- returns null.
So, I am looking for a way to instantiate a class by providing its fully qualified name in Silverlight 4.0.
Any ideas would be greatly appreciated, Thanks.
I had the same issue and it worked when I tried the assembly qualified type name in the following format :
", , Version="", Culture=, PublicKeyToken="

Resources