Load an OpenTK GameWindow inside a Windows form panel? - c#

I have an application made in C# using OpenTk.
this is in a class called ViewPort, and is initialized like this:
namespace OpenTK_viewport
{
class ViewPort : GameWindow
{
.....
my Program.cs is:
[STAThread]
static void Main()
{
using (ViewPort main = new ViewPort())
{
main.Run(60.0);
}
}
This works great, and opens the game window. Now, I want to embed this window inside a UserControl, so i can load it into a panel on an existing Form.
For example, in the project, I have:
namespace OpenTK_viewport
{
public partial class Form3dViewport : UserControl
{
public Form3dViewport()
{
InitializeComponent();
}
private void Form3dViewport_Load(object sender, EventArgs e)
{
}
}
}
I would like to embed the ViewPort class inside this UserControl.
I can't find an example of this anywhere. How can i go about this?
EDIT:
I am able to add a GLControl to the Form instead of a panel. Can I load the Viewport class into this?
Thank you.

Ah, I was looking at it wrong. OpenTK can be run straight inside a Form. As illustrated here:
https://github.com/mono/opentk/blob/master/Source/Examples/OpenTK/GLControl/GLControlGameLoop.cs

Related

C# - Can't use classes from a .NET Framework project in a WPF project in the same Source

UPDATE: I tried working out by making every class in Code public, but it doesn't seem to accept my class hierarchy.
This is my first post so please bear with me. Besides that, i'm a pretty big noob, so do excuse me if something dumb comes along
I'm currently doing a school project and I have a fully fleshed out .NET Framework project in Visual Studio. Now I have to visualize it with a WPF app. So I made a new WPF project in the same source.
Let's respectively call them Code and Visualization.
I've given Visualization a project reference to Code and put using Code; at the top of the XAML.cs
I made a button in Visualization and I want it's OnClick event to use
Code.Start();
What somehow seems to sort of work is making every class in Code public, but I don't remember that being a good practice, but do correct me if i'm wrong!
I've put multiple hours into finding a solution with none to be really found before. Seeing as nobody seems to have posted this question before I must be missing something really simple.
Cheers!
namespace Code
{
class Program
{
public void Start()
{
/// Do something
}
}
}
using Code;
namespace Visualization
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Start_Click(object sender, RoutedEventArgs e)
{
// Use the Start() function from Code
}
}
}
To use classes and their functions and properties from another project, you have to declare them as public.
namespace Code
{
public class Program
{
public void Start()
{
// Do something
}
}
}
Then go to the other project, right click > Add > Reference > select your project containing the code above (assuming you're using Visual Studio IDE). After, you can access the public functions and properties:
using Code;
namespace Visualization
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Start_Click(object sender, RoutedEventArgs e)
{
Program p = new Program();
p.Start();
}
}
}
If you are worried about security, then ensure that public functions and properties you deem are safe to expose to other projects. For example, what we just did to use the Start function, any other project or some 3rd party program could do also. The only difference is that a reference would be made to the project's .dll produced instead of the project itself.
A basic rule of thumb (at least for me) is that if there are anything I don't want to expose, then don't make them public and have a public function that can be called to perform different actions. This way I can limit what actions and information can be performed or accessed:
//within some project
namespace Code
{
public class Program
{
// can't be access from another project directly
private string _privateText { get;set; }
// can be accessed directly
public string PublicText { get;set; }
public void Start()
{
// Do something
}
public string getPrivateText()
{
// here you can limit what actions are done and what information to return
return _privateText;
}
}
}
You can then do the following:
// within another project
using Code;
namespace Visualization
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Start_Click(object sender, RoutedEventArgs e)
{
Program p = new Program();
string s1 = p.getPrivateText();
string s2 = p.PublicText;
p.Start();
}
}
}
Hope this helps!

Passing data between forms to plot a surface, not working

I have two forms (in the same namespace), Form1 which acquires data from images, and GraphForm, which sould plot the data as a surface graph, using the ILNumerics framework.
I had never done such a construction with two forms (fairly new to C#, and coding as a whole for that matters), and I can't figure out why my code doesn't work, as it's almost copy/pasted from a previous question asked here (Sujith H S answer). I tried other constructions described in various similar questions as well, with the same result : the second form and the ILNumerics plotting interface appear, but are empty.
Here is my version of the answer I linked :
IN FORM1 :
// Form creation
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public static ILInArray<double> CrossCorrExpMatrixReShiftedILN;
//Here is my whole data acquisition code, about 800 lines long
ILInArray<double> CrossCorrExpMatrixReShiftedILN = CrossCorrExpMatrixReShifted;
GraphForm Form2 = new GraphForm();
Form2.Show();
IN GRAPHFORM :
public partial class GraphForm : Form
{
public GraphForm()
{
InitializeComponent();
}
private void GraphForm_Load(object sender, EventArgs e)
{
ILInArray<double> GraphData = Form1.CrossCorrExpMatrixReShiftedILN;
//Here I use GraphData to plot the surface
}
Does anyone have an idea why it doesn't work ?
Have you tried passing the ILInArray<double> object into GraphForm's constructor and setting it to a local variable? So something like the below?
IN FORM1 :
GraphForm Form2 = new GraphForm(CrossCorrExpMatrixReShiftedILN);
Form2.Show();
IN GRAPHFORM :
public partial class GraphForm : Form
{
private ILInArray<double> CrossCorrExpMatrixReShiftedILN;
public GraphForm(ILInArray<double> pCrossCorrExpMatrixReShiftedILN)
{
InitializeComponent();
CrossCorrExpMatrixReShiftedILN = pCrossCorrExpMatrixReShiftedILN;
}
private void GraphForm_Load(object sender, EventArgs e)
{
ILInArray<double> GraphData = CrossCorrExpMatrixReShiftedILN;
//Here I use GraphData to plot the surface
}
I found the solution.
In the design tab for the GraphForm form, the Load event was NOT associated with the GraphForm_Load code bit. I don't know why it didn't associate automatically.
I found this by placing breakdown points along the GraphForm code, and noticing that the GraphForm_Load code didn't run at all.

How to call a class method from a different class

I am creating Windows form application and its main form contains a panel. Different user controls are being loaded on that panel on button click.
namespace LearnCSharp
{
public partial class MainForm : Form
{
private void configButton_Click(object sender, EventArgs e)
{
var uControllerDashboard = new Controllers.Dashboard();
panel.Controls.Add(uControllerDashboard);
updateNotification("active");
}
private void updateNotification(string state)
{
switch (state)
{
case "active" :
//Do something here
break;
}
}
}
}
when click config button it loads Dashboard user controller into Panel there is a another apply button in Dashboard userControl. When I click that button I need to call updatNotification method in MainForm Class.
namespace LearnCSharp.Controllers
{
public partial class Dashboard : UserControl
{
private void btnApply_Click(object sender, EventArgs e)
{
// Need to call updateNotification method here.
}
}
}
how can I achieve my requirement. I appreciate any help. Thanks.
Use events for that.
Instead of calling the MainForm inside the UserControl, create an event in the UserControl and have the MainForm subscribe that event. Inside the UserControl you just need to trigger the event.
There are many examples on web about this. Just take a look at this:
How do I make an Event in the Usercontrol and Have it Handeled in the Main Form?
How do i raise an event in a usercontrol and catch it in mainpage?
Hope this helps.

Define custom path for control events

I've been working a lot with WPF, and after awhile the MainWindow class becomes cluttered and unorganized. Is there a way to store all of the control events in a custom class like below? Inheriting doesn't work and i'm guessing its because it has no instance of the new class to go off of.
public partial class MainWindow : Window
{
public class ControlEvents : MainWindow //Custom class
{
private void Abutton_Click(object sender, RoutedEventArgs e)
{
...Stuff
}
}
}
Is there a way to store all of the control events in a custom class like below?
No, the event handlers themselves must be defined in the code-behind of the same view class where the element is defined and the handler is hooked up.
You could move the code inside the event handlers to another class though:
public partial class MainWindow : Window
{
private YourClass _handler = new YourObject();
public class ControlEvents : MainWindow //Custom class
{
private void Abutton_Click(object sender, RoutedEventArgs e)
{
_handler.HandleButtonClick(e);
}
}
}
But you should look into MVVM: https://msdn.microsoft.com/en-us/library/hh848246.aspx. There is a reason why this is the recommended design pattern for developing XAML based UI applications.
If you don't use mvvm:
You can create user control for area of controls and load this user control in your main window.
Also - you can take your code of "do stuff" to another class and call it from the event function.
for example:
functions.cs
dostuff1()
{
...
}
dostuff2()
{
...
}
your usercontrol/mainwindow.xaml.cs:
functions f = new functions();
private void Abutton_Click(object sender, RoutedEventArgs e)
{
f.dostuff1();
}
good luck
You can move all the events to Partial class in separated file.
call the file MainWindowEvents.cs or something. (to remember what is it)

How to move methods to external file in windows form C#

newbie question :(
I'm making a program using windows forms and i have a lot of small methods like this
private void label1_Click(object sender, EventArgs e)
{
textBox1.Select();
}
private void label13_Click(object sender, EventArgs e)
{
textBox13.Select();
}
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
plotGraph(prostokat);
}
in the Form1.cs file and to make the code more transparent, I would like to move these small methods out somewhere to an external file (class?) but I don't really know how to do this. If they were normal methods I would just make a class and create an object of that class and just call the methods using that object but these are functions that "happen" when a user action is performed i.e. a textbox is clicked, so I'm not sure how to make this work.
It is possible to create an extra partial class (separated file) for your Form1 and place your cluttering methods there.
Or you could collapse them with #region
#region UI Handlers
#endregion
The perfect solution would be using some kind of MVVM for WinForms. In that case in your ViewModel you can implement your business logic separately from the code-behind.
Check out this:
https://www.codeproject.com/articles/364485/mvvm-model-view-viewmodel-patte
Hope it helps!
Have a look at your Form class subsection. It most cases it is still a partial class. Create a new .cs file in the same subsection in your project and add another partial form class to it.
You can find additional information here:
Partial Classes and Methods
Sure, you can add a new class to your project (right-click the project in Solution Explorer --> Add Class --> ) and put your methods there. Then you will need to hook the methods up to the controls in code:
I added a static class called "Form Methods" and put a method in there for label1 Click event:
static class FormMethods
{
public static void label1_Click(object sender, EventArgs e)
{
Label label = (Label) sender;
// Try to find the textbox through the label's parent form
TextBox textBox = (TextBox) label.Parent.Controls.Find("textBox1", true).First();
if (textBox != null)
{
textBox.Select();
}
}
}
Then in the Form Designer code, you can hook up the event:
this.label1.Click += new System.EventHandler(FormMethods.label1_Click);
Alternatively, you can make the class part of your original form class, and it will still be a separate file. If you want to do this, you can then make your event a private non-static method, and you would change the class definition to a public partial class:
public partial class Form1 // <-- This used to be: static class FormMethods
{
// This used to be: public static void label1_Click
private void label1_Click(object sender, EventArgs e)
{
. . .
And then hooking up the event looks like:
this.label1.Click += new System.EventHandler(label1_Click);
You can create any number of partial class files mimicking your original and group methods inside as your functionally needs - however, you won't be able to use the designer to directly navigate to your callbacks. That is, if you double click a graphic element or click an event of a graphic element you will have an unexpected behavior: in both cases you will have an event handler generated in your first partial and a hook created to that . . . so you can't directly navigate to those handlers anymore, and you need to go trough your partial files looking for their definitions.
Use partial to split C# code like this.
public partial class Employee
{
public void DoWork()
{
}
}
public partial class Employee
{
public void GoToLunch()
{
}
}

Categories

Resources