Passing class reference to another class not working - c#

I have a fairly complicated application, so I decided to organize code a bit and am having problems with references to the main class not working anymore. I already had a structure with classes, but all of them were properties of the main class and had no other class properties that would need the reference to the main class.
So my structure was like this: Main Class -> Class1, Class2, Class3 etc.
After restructuring I created a structure similar to this:
Main Class -> (Class1 -> Class12, Class13), Class2, Class3 etc.
I was passing the reference to the main class just fine to all of them before, but now that I have a deeper structure, I am getting the main class null error.
The structure relevant to this particular error is this:
MainWindow: Form -> MaxFlow (algorithm) -> LabelNodes (a part of that algorithm)
The structure is fairly simple since most of my code is completely irrelevant to the problem.
First I have the MainWindow class.
public partial class MainWindow : Form {
private MaxFlow maxFlow; // Algorithm
internal MaxFlow MaxFlow { get => maxFlow; set => maxFlow = value; }
public MainWindow() {
InitializeComponent();
maxFlow = new MaxFlow(mainWindow: this);
}
Then the Maxflow class:
class MaxFlow {
private MainWindow mainWindow;
public MaxFlow(MainWindow mainWindow) {
mainWindow = this.mainWindow;
}
and then the last class with nodes:
class LabelNodes {
private MainWindow mainWindow;
public LabelNodes(MainWindow mainWindow) {
this.mainWindow = mainWindow;
}
public AddNewNodeLabel() {
//…
// THIS PART THROWS THE ERROR (mainWindow equal to null):
Label newLabel = new Label {
Location = mainWindow.LastClickLocation,
Name = ”…”
};
//…
}
I tried setting breakpoints and found out that the reference to the MainWindow class is null already before passing it to the LabelNodes class, it gets passed as null in the MaxFlow class.
Since I had no problems before transferring the LabelNodes class from MainWindow to MaxFlow, I suspect the problem is because I am passing it two times but do not understand why this could be a problem.
Any help would be appreciated.

Your code is not correct: You should assign the this.mainWindow instead of the parameter mainWindow. It will assign the default value null in the field to the parameter. (in the Maxflow class)
class MaxFlow {
private MainWindow mainWindow;
public MaxFlow(MainWindow mainWindow) {
// mainWindow = this.mainWindow; <-----
// should be:
this.mainWindow = mainWindow;
}
Like DavidG pointed out. Better naming convension would prevent making these mistakes:
class MaxFlow
{
private MainWindow _mainWindow;
public MaxFlow(MainWindow mainWindow)
{
_mainWindow = mainWindow;
}
}

Related

Accessing object created in different Window in WPF application

I have created one window and declared 2 instances of my object, then I modified them and wanted to pass to another Window. My questions are:
How would i do that ?
(I can pass simple types such as string or int trough window constructor but passing my own object giving me an error (Inconsistent Accessibility parameter order is less accessible then method))
Does it have any connection with dataContext ?
Can anybody explain to me how I can achieve that (in the simplest possible way)? What are the correct ways to do that ?
Here is part of my code (everything is in one namespace):
public partial class Main_window : Window
{
Order myOrder = new Order();
Menu menu = new Menu();
public Main_window()
{ InitializeComponent() }
private void OpenSecondWindow(object sender, RoutedEventArgs e)
{
Second_Window SecondWindow = new Second_Window();
Second.ShowDialog();
}
}
// Second Window class
public partial class Second_Window : Window
{
public Second_Window(Order someOrder)
{ InitializeComponent(); }
}
Make sure that the Order type, and any other type you intend to inject the SecondWindow with, is defined as a public class:
public class Order { ... }
A non-public type cannot be part of the signature of a public method or constructor.

WPF/C# Link Two Variables together

I currently have a simple WPF application, in the MainWindow I will have a variable (In this case the variable is a class that holds data). Then I have a User Control which has the same variable.
Currently, I'm passing the variable with the ref keyword and it works perfectly fine, however, is this save/good practice? Is there a better way of linking this two variables together?
I am aware of the existence of DependencyProperty, however, I could not get it to work.
MainWindow:
public partial class MainWindow : Window
{
private TestClassWithInfo m_SelectedInfo;
public MainWindow()
{
InitializeComponent();
m_SelectedInfo = new DrawingInformation();
TestGridUC mp = new TestGridUC(ref m_SelectedInfo);
TestCanvas.Childrens.Add(mp);
}
}
TestGridUI:
public partial class TestGridUC : UserControl {
private TestClassWithInfo m_SelectedInfo;
public TestGridUC (ref TestClassWithInfo e)
{
InitializeComponent();
m_SelectedInfo = e;
}
}
TestClassWithInfo:
public class TestClassWithInfo
{
public Image imageTest;
public int intTest;
public TestClassWithInfo ()
{
m_img = null;
m_layer = 0;
}
}
I am aware of the existence of DependencyProperty, however, I could not get it to work.
A dependency property really is the way to go about it though:
public partial class TestGridUC : UserControl
{
public TestGridUC()
{
InitializeComponent();
}
public TestClassWithInfo Info
{
get { return (TestClassWithInfo)GetValue(InfoProperty); }
set { SetValue(InfoProperty, value); }
}
public static readonly DependencyProperty InfoProperty =
DependencyProperty.Register("Info", typeof(TestClassWithInfo), typeof(TestGridUC),
new PropertyMetadata(null /*or initialize to a default of new TestClassWithInfo()*/ ));
}
Now you can bind to that property from the xaml in your MainWindow:
<local:TestGridUC
Info="{Binding Info}"></local:TestGridUC>
If you need help with that part, as pr177 answered there are many tutorials on getting started with WPF with the MVVM pattern. The basics here would involve a view model object that contains a TestClassWithInfo public property that you bind to.
Have a look at the MVVM (Model-View-ViewModel) Pattern
There are many tutorials & introductions like that:
https://blogs.msdn.microsoft.com/ivo_manolov/2012/03/17/model-view-viewmodel-mvvm-applications-general-introduction/
or
https://social.technet.microsoft.com/wiki/contents/articles/32164.wpf-mvvm-step-by-step-2.aspx

How to get the window obj the ViewModel is bind with

I have rewriting app into MvvM and having a problem with calling one function from viewModel. That function takes as parameter a window it should alter.
I code behind it looks like this:
this.utils = new IntroPageUtils(this);
this.Dispatcher.BeginInvoke(new Action(this.utils.InitializeWizard), null);
where
this = window which should be altered
InitializeWizard the method we are calling to make it
In code behind its quite easy but how how to achieve this in viewModel?
at this moment code behind file is clean:
public partial class IntroPage : Page
{
/// <summary>
/// Initializes a new instance of the IntroPage class.
/// </summary>
public IntroPage()
{
InitializeComponent();
}
}
and a viewModel:
class IntroPageViewModel: ObservableObject, INavigable
{
private ICommand nextButtonCommand;
private ICommand cancelButtonCommand;
private IntroPageUtils utils;
public IntroPageViewModel()
{
this.utils = new IntroPageUtils(/*What to put here? */);
this.Dispatcher.BeginInvoke(new Action(this.utils.InitializeWizard), null); // There is not such thing as dispatcher here
}
/* Rest of a viewModel */
}
I'll be grateful for any samples, guides or tutorials how to overcome this problem.
A ViewModel is set as Datacontext of a View.
For example :
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainViewModel(this);
}
}
In this example, we pass the window in parameter to the view model.
So you can store the reference to the window in the view model.
class MainViewModel : ViewModelBase
{
#region fields
private MainWindow mainWindow;
#endregion
#region properties
public MainWindow MainWindow
{
get
{
return this.mainWindow;
}
}
#endregion
public MainViewModel(MainWindow mainWindow)
{
this.mainWindow = mainWindow;
}
}
I guess it depends on the answer to a few questions. Could there be more than one instance of the IntroPageViewModel in your application? Would these be specific to the window it's view is hosted in? If so (and I assume so), why not pass in your IntroPage instance into the constructor of the view model and then use that?
The view model then has a reference to the model it represents, which is perfectly valid I think.
i.e.
View Model:
class IntroPageViewModel : ObservableObject, INavigable
{
private readonly IntroPage _model;
private readonly IntroPageUtils _introPageUtils;
public IntroPageViewModel(IntroPage model)
{
_model = model;
_introPageUtils = new IntroPageUtils(Window.GetWindow(_model));
}
}
Wherever you initialise the view model instance:
IntroPage introPage = new IntroPage();
IntroPageViewModel viewModel = new IntroPageViewModel(introPage);

define variable internal for get him in child window wpf-c#

i have in the main window variable
example:
public partial class MainWindow : Window
{
internal int i;
public MainWindow()
{
InitializeComponent();
}
}
and i want to use him in child window and for that i do him internal (the two window in the same namespace) and the child window still doesn't recognize the variable
what i'm suppose to do?
You should create a public property on the child window of type int. When you create the child window then set that property based on the value of the field in the parent window.
It appears that you want to be able to not just read the variable in the child class, but also modify it and have that change reflected in the parent form, so that will complicate the answer.
We'll need to start off with a helper class. Because the data we're interested in is an int (which is a value type) we'll need something that is a reference type (i.e. a class).
public class Wrapper<T>
{
public T Value { get; set; }
}
So we'll start by not having an integer in the parent form, but instead an instance of this class:
public class Form1
{
private Wrapper<int> data = new Wrapper<int>(); //TODO give better name
//...
}
Next we'll need a public property on the child form; rather than an int we'll use this new class:
public class Form2
{
public Wrapper<int> Data { get; set; }
//...
}
Now when we create the child class we'll set the property based on the value in the parent class:
public void someMethod()
{
Form2 childForm = new Form2();
childForm.Data = data;
childForm.Show();
}
Now that we've done all this we've ensure that both the parent and child class have a reference to the same instance of Wrapper, so any changes to the Value property of the Wrapper instance (from either class) will be "seen" by either reference.

Instantiate in the class

I am working on something and I have to instantiate the class. My question is where would I do that at? Would I do it before this:
public partial class Form1 : Form
{
InputClass myclass = new InputClass();
public Form1()
{
InitializeComponent();
}
Or
public partial class Form1 : Form
{
public Form1()
{
InputClass myclass = new InputClass();
InitializeComponent();
}
Here is another code I am working on but it is not working out to well this is what my code looks like right now:
public partial class Form1 : Form
{
InputClass myClass = new InputClass();
myClass.yourname = "";
myClass.Banner = "";
public Form1()
{
InitializeComponent();
}
I am new to C# and I am trying to figure this out. I need to instantiate the class. Then when the page load add to set the labels text from the _banner variable. Then add code to set the property yourname from the text in the textbox when the user presses the button. Then i need to clear the textbox. I also have to display the name in a messagebox from the class.
class InputClass
{
public string _banner;
private string _yourName;
public InputClass(String _banner)
{
this._banner = _banner;
}
public string yourName
{
get { return _yourName; }
set { _yourName = value; }
}
}
}
If you want to access your object from other methods in your class then you need to use a member field rather than a local variable.
private InputClass myClass = new InputClass { YourName = "", Banner = "" };
public Form1()
{
InitializeComponent();
}
Another option is to declare a member field but initialize it inside the constructor:
private InputClass myClass;
public Form1()
{
InitializeComponent();
this.myClass = new InputClass { YourName = "", Banner = "" };
}
This isn't too useful in your specific case, but it can be useful if you need to pass parameters from your constructor to the InputClass constructor.
You can only set the properties inside a function body! not inside the class context.
Instantiating the class would work inside Form1() or at declaration time. IMO best style in your case would be:
public partial class Form1 : Form
{
InputClass myclass;
public Form1()
{
InitializeComponent();
myclass = new InputClass();
}
}
This enables one to use myClass not only in the Form1 constructor, but also in any other function.
First of all, make the distinction between Declaration and Instantiation. In your first snippet, you're declaring the InputClass member in the class scope, meaning it will be shared by all methods in the class. Once you do that, it doesn't matter if you instantiate it in the constructor or during declaration, it (mostly) works out to the same thing.
Secondly, I'm guessing that this is an ASP.NET project, since you refer to "page load". If so, remember that your Form1 instance doesn't stay alive between page loads. Every time you reload the page, either manually with F5 or via button-clicks/postbacks, you're creating a new instance of Form1, which will create a new instance of InputClass.
What you're doing in the first example is a declaration of a member variable of Form1 named myclass. You can assign it a value at the same place, which is fine:
public partial class Form1 : Form
{
InputClass myclass = new InputClass();
public Form1()
{
InitializeComponent();
}
}
But you usually cannot insert actual code statements in your class declaration (like the assignment myClass.yourname = ""). You need to put them in the constructor. So a correct way to do this would be:
public partial class Form1 : Form
{
InputClass myClass = new InputClass();
public Form1()
{
myClass.yourname = "";
myClass.Banner = "";
InitializeComponent();
}
}
For performing actions on button click, look here: http://msdn.microsoft.com/en-us/library/43sxkdeb(v=vs.80).aspx

Categories

Resources