I know I can build a WPF application with FSharp.ViewModule or FSharp.Desktop.UI. In this case I'm trying to build the GUI part in C# and access it from F#. I can start the C# application from F#, and it shows the MainWindow however I cannot access any control on it from code. How would I refer to the Button (Name:button) on this form? MainWindow or App doesn't show it in my initial setup.
The C# View is just a MainWindow with a Button on it.
The F# code is this:
open System
open WpfView
[<STAThread>]
do
let app = App()
let win = MainWindow()
app.Run(win) |> ignore
The controls on your WPF are 'internal'. That is they are only visible to code in the same assembly.
see: Internal access modifier
Your F# and C# code are in separate assemblies so your F# code cannot access the internal members of classes in your C# code.
The controls are automatically generated by the xaml compiler so you can't change them directly however a simple fix would be to create public access methods and/or properties in your C# class that access the internal properties.
Additionally, while you may have reasons to structure your code the way you have, it might be better to have the main entry point to the application in the C# assembly along with the WPF code and have that reference your logic in the F# assembly. That way you can use data binding to bind to models you have written in F#.
By default, the controls in a WPF form are declared as internal and are not visible outside the assembly of the form. You can change that in the XAML of the WPF form by specifying the x:FieldModifier attribute like this:
<Button x:Name="button" Content="Button" x:FieldModifier="public" />
However, it would be a better design to give the form your own properties to access the data in the form and not directly deal with the controls from outside.
Related
Short story : can you make 2 XAML to reference into single C# class? If so, how do you add the reference in the XAML?
Long story : I'm currently making an Universal App for 8.1 in VS. After investigating the code-behind, both platform have same codes (identical). So my plan is to put the class for code-behind in the Shared folder, but I still don't know how to make both XAML (Windows 8.1 and WP8.1) to refer to this class as code-behind.
I've read this one : How do you reference a class through xaml?
But this is for WPF, and it specified the class as static
edit : I'm not making the XAML into shared file, since I've designed them platform-specific
You are probably looking for the x:Class attribute of the Page element in XAML
However, it would be better to use two xaml.cs files for each xaml page in the windows store and windows phone projects, and have the common code in a separate class in the Shared Project.
Still better, you could keep all your code in the shared project, and use a single xaml page and single xaml.cs class for both phone and tablet, by using the VisualStateManager. This is what you will have to do when you port your app to Windows 10, which is a truly universal app.
You can probably just put the xaml.cs file in the shared project, or create a third file for the shared code and declare it as partial. Then implement the differences in the projects.
However, if you do this, I think you'll have problems with adding event handlers to the xaml, much as you do if you create a base class and derive from it, as the handlers will be added to the local project, not the shared one.
Try to use code-behind as less as possible. XAML is designed with MVVM in mind, so code-behind should be minimal, ideally empty. Besides MVVM, there're attached behaviors, custom controls etc. which help moving code from code-behind.
If you can't get rid of code-behind completely, use your usual tactics of sharing a common piece of code — just move the code into a separate class, for example, or use class hierarchy.
Note that besides XAML and code-behind, there's a generated file which connects control names to control fields etc., so there's more code than you see. Code-behind relies on this generated code, so it can't be shared within the same project, even if the code is the same.
Just some ideas (may not be perfect):
Add the UI of both controls into one XAML file and then just hide/remove the unnecessary one.
Use a template (custom) control.
Files in the shared project count as part of the other projects that reference the shared project. When you're building the configuration specific project it doesn't matter if a file is in that project directly or if it is in the shared project.
That means that you can leave the .xaml files in the target-specific projects and move the .xaml.cs file to the shared folder.
For Universal Windows apps in Windows 10 it's even easier: the controls will all be the same so you don't need separate code. If you do want to tailor your experience to different devices you don't need a shared project but can use device qualifiers to provide separate xaml files for different targets.
I discuss using partial classes and resource dictionaries to share code in my blog entry Strategies for sharing code in XAML-based Universal apps
My first time asking a question here so apologies upfront if I'm not doing this right. I could not find anything with the search.
I inherited a VB.NET legacy Windows Application project. Any and all new additions as far as possible I would like to code in C#, including new Windows Forms. So, I have a new Windows form in a C# assembly (not sure if this is the best way) being referenced by the VB.NET Windows application.
On initialising the C# form from the referenced assembly I pass it all the necessary parameters from which I will build up my grid columns and records in the C# Windows Form. No problems here so far.
On the cell-double click event of the C# grid, I would like to show an existing VB.NET Winform from the application referencing the C# assembly.
My question is: How do I get a handle on the VB.NET Windows Form to show it, or do anything else with it for that matter? Circular reference is obviously not allowed so how can I achieve this if at all possible, C# or otherwise?
You should be able to add an event handler to the object.
http://msdn.microsoft.com/en-us/library/6yyk8z93%28v=vs.90%29.aspx
One way would be to pass a generic form creation handler to your C# Form, given that it is instantiated from your VB.NET code. This way the form wouldn't have to know what exact type of form it must create and show; all it would know is that it's a Form, which is good enough if all you have to do is showing it.
You may also consider exposing your C# Form cell double click event as a public event that can be handled by your VB.NET code.
If it makes sense in your design, a third option would be to use a third assembly that acts as a bridge. This assembly could be referred by both your VB.NET and C# assemblies and hold interface types implemented / used in these.
In winforms – there's a message pump waiting for an event to happen – when that happens – the appropriate event handler in C# is called.
In WPF there's also XAML. When is that executed? Does the C# code call it or does it call the C# code? In other words: Does an event trigger C# code to run, or does it trigger XAML to be executed?
It seems (please correct me if I'm wrong) that WPF is not really different in the flow of things from winforms. The message pump will call C# event handlers, and the initialization of the form will be done in an InitializeComponent method.
The difference is just that the InitializeComponent method of a WPF form will include parsing an XAML file, so essentially, the developer is describing the initial appearance of the form using XAML instead of C#.
(Of course "C#" can be interchanged here with "VB".)
Here's some info about the wpf application and it's "lifecycle". http://msdn.microsoft.com/en-us/library/ms743714.aspx
And here's some info on InitializeComponent and the role it plays tying into Xaml parsing. What does InitializeComponent() do, and how does it work in WPF?
I'll see if I can find a more official post about the Xaml parsing.
From http://msdn.microsoft.com/en-us/library/aa970678.aspx
"
The XAML file is parsed by the markup compiler.
A compiled representation is created for that XAML and copied to the obj\Release folder.
A CodeDOM representation of a new partial class is created and copied to the obj\Release folder.
In addition, a language-specific code file is generated for every XAML file. For example, for a Page1.xaml page in a Visual Basic project, a Page1.g.vb is generated; for a Page1.xaml page in a C# project, a Page1.g.cs is generated. The ".g" in the file name indicates the file is generated code that has a partial class declaration for the top-level element of the markup file (such as Page or Window). The class is declared with the partial modifier in C# (Extends in Visual Basic) to indicate there is another declaration for the class elsewhere, usually in the code-behind file Page1.xaml.cs.
"
A XAML-Parser parses it and creates the respective CLR objects from it, that is about it.
I new to c# and windows form programming. Here is the problem i am trying to solve.
I have to write an application that uses an multiple instance of an ActiveX control. Therefore, I dragged as many control as necessary to my Form. Now my problem is that i'd like to add some personalised methods to this activeX. The logical solution I thought was to create my own class derived from that aciveX and add some more members and methods to that class so it would work as desired. Now my problem is that the newly generated class doesn't exists as a control that can be inserted into the form.
So How can a class become a control and then inserted into a form ?
If you look at the Designer.CS file that corresponds to your form, you should see, in the #region Windows Form Designer generated code, the code that was generated when you dragged the ActiveX control onto the form.
This code is similar to what your code needs to look like.
My guess would be that you should wrap this activex into your own control, and add funcionality that lacks into that wrapper.
Pros: you'l have .net control and will be able to extend it and use it anyway you like.
Cons: if you want to access original methods, you'll have to generate pass-through method wrappers.
How:
- create a control class
- drop activex you have onto it
- set activex dock to 'fill'
- either set control to public, create get wrapper for it, or create method wrappers you desire
- compile that and use it on the form.
I didn't realize at the time I create this particular application that I'd need to reuse some of the components - some Windows forms and a class or two.
Now that I've already created the fairly complex forms inside one project, what's the easiest way to transform those forms into inheritable forms that I can reuse in other projects? Once that's done I'd like to modify the existing project to use the newly created inheritable forms.
How can I accomplish this with as little pain as possible? I'm using C# in Visual Studio 2008.
You don't really have to do anything special to achieve this. Your form is already inheritable. On any new form, just make sure the first line looks like this:
public partial class frmMyChild : frmMyInheritableForm
instead of:
public partial class frmMyChild : Form
and make any methods that you need to access from the child either "public" or "protected".
Update: one additional trick is to set the Modifiers property of each control on your original form to Protected (instead of the default Private). In the designer for your child form that inherits from this form, you will then see all of the controls on the parent form, and you can move them and resize them as you see fit (this will not affect the original form's layout).
To access any parent method from the child form, you just call:
base.MyMethod();
Just declare an empty class that inherits from System.Windows.Forms.Form and then make your "huge" class inherit from that. Once that works, start moving, a small reusable piece at a time from your "huge" class to the parent class.
In your first project, add a new "Windows Forms Control Library" to your solution
Drag the windows/classes from the original project to the new one.
fix the errors.
At this point, you now have a Class Library which you can include in your second windows project.
Bear in mind that you don't need to design your forms to be inheritable in order to use them in other projects. Inheritable forms are a PITA, and in all but the simplest circumstances are more trouble than they're worth.
If you're simply looking to design your forms to be more portable, then the biggest thing that would be required is ensuring that you do NOT expose internal fields (Controls are included in that) outside of the form. If outside code (be it in the same or another project) needs to interact with the form in some visual or behavioral way, then you need to expose functions and properties that represent that functionality, rather than the control itself.
Apart from the design of the particular form, it would likely be helpful (if a somewhat time-consuming exercise) to move these common forms into a separate control library. While you can definitely add your .exe as a reference to another project, that's not ideal (and not entirely intuitive).