Let's take simple window:
public partial class NewWindow : Window
{
public NewWindow(CustomType variableName)
{
InitializeComponent();
//do stuff with your variable
#if DEBUG
this.AttachDevTools();
#endif
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
When you do thing like this, application will no longer compile:
Unable to find public constructor for type Project:Project.Views.NewWindow() Line 1, position 2
Is there a way to bypass it? It forces me to use some ancient methods like controlling things via public static variables, which in normal scenario can be avoided by using constructors.
You might have already found this out, but the XAML template requires a public paramterless constructor. However, that doesn't mean you can't add your own second constructor.
public partial class NewWindow : Window
{
public NewWindow()
{
InitializeComponent();
}
public NewWindow(CustomType variableName)
: this()
{
//do stuff with your variable
#if DEBUG
this.AttachDevTools();
#endif
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
Related
I am trying to migrate one of my macOS app to Windows UWP.
There is a requirement that I need to call the function in another class
namespace MyApp
{
public sealed partial class MainPage : Page
{
public bool isOk;
public MainPage()
{
}
public void doSomething(){
};
/*
public static void doSomething(){
isOk=false;// isOk is inaccessible
};*/
}
public sealed partial class AnotherPage : Page
{
public AnotherPage()
{
//call doSomething() in MainPage
}
}
}
it is very easy to implement this in objective-c via protocol(interface)
but in c#, the mechanism of the interface is different from the objective-c protocol.
of course, I can use the code below
MainPage mainPage=new MainPage();
mainPage.dosomthing();
but I wonder if this is valid for Page object related to the XAML file.
or there is a common usage to call the function in another class?
Your comment welcome
NOTE: This is an answer to your question but from a design perspective this is bad.
You need a reference to the instantiated MainPage. I'm sure there's one in the framework but for example just so this can be understood let's make a public static class to hold this reference.
public static class Global
{
public static Page MainPage { get; set; }
}
Now in the MainPage constructor assign itself to this property of the static Global class.
public MainPage()
{
Global.MainPage = this;
}
Now from any other page you can access it.
public AnotherPage()
{
Global.MainPage.doSomething();
}
I am trying to divide my program into classes to reduce clutter and increase readability.
In one of my methods, I need to find the location of a label on the screen.
this.Controls.Find worked before I moved everything into separate classes but it doesn't exist anymore because I am no longer executing it in the same class as the controls. I tried Main.Controls.Find (Main.cs is where my form is executed and set out) but this also didn't work and I got the error, "An object reference is required for the non-static field, method, or property 'Control.Controls'"
How do I reference the controls? Do I need to add an additional using statement?
Thanks,
Josh
You need a reference to the form, passed down to the newly introduced method (or class).
Before
public class Main : Form {
public void Whatever() {
...
this.Controls.Find(...);
}
}
After
public class Main : Form {
public void Whatever() {
...
new Helpers().HelperMethod( this );
}
}
public class Helpers {
public void HelperMethod( Form form ) {
...
form.Controls.Find
}
}
or
public class Main : Form {
public void Whatever() {
...
new Helpers( this ).HelperMethod();
}
}
public class Helpers {
private Form Form { get; set; }
public Helpers( Form form ) {
this.Form = form;
}
public void HelperMethod() {
...
this.Form.Controls.Find
}
}
I want to update textblock1 to 'there' from a class other than the main. As shown this code gives no errors, but does not work. Textblock1 is set to
FieldModifier="Public".
namespace myProgram
{
public sealed partial class MainPage : Page
{
Library stuff = new Library();
public MainPage()
{
this.InitializeComponent();
}
public void mainStuff()
{
stuff.Doit(new MainPage());
}
}
}
namespace myProgram
{
public class Library
{
public void Doit(MainPage mainPage)
{
mainPage.textblock1.Text = "there";
}
}
}
The short answer
Pass your Window as a parameter to the other class.
public class Library {
public void Doit(MainPage mainPage)
{
mainPage.textblock1.Text = "there";
}
}
EDIT According to the other answer that is posted here, you can't (by default) access controls from outside the class (as they are set to protected).
You can override the access modifier to public (refer to the other answer), but that seems to violate the idea that UI and data logic should be separated.
It does work, from a technical point of view; I just suggest not doing it because it can lead to future problems in development.
The cautionary answer
You should endeavour to keep your UI and data logic separate. In most cases where you want another class to access your window's controls; you are violating the principle of UI and data logic segregation.
In short, you don't want anyone (except MainPage) to be aware that a Mainpage has a Textblock; let alone giving them the ability to set its content directly.
In MainPage, create a public property:
public String MyDisplayValue
{
get
{
return this.textblock1.Text;
}
set
{
this.textblock1.Text = value;
}
}
In your external Library class:
public void Doit(MainPage mainPage)
{
mainPage.MyDisplayValue = "there";
}
Functionally speaking, the application works the same as in the short answer I supplied. But this one creates a better separation between UI and data logic.
This is a matter of good practice, not technical requirement.
Make you TextBlock control public like this. x:FieldModifier="public"
<TextBlock Name="TextBlockName"
x:FieldModifier="public"/>
Then expose you MainPage class
public sealed partial class MainPage : Page
{
public static MainPage mainPage { get; set; }
public MainPage()
{
this.InitializeComponent();
mainPage = this;
}
}
then in our Library class do this:
public class Library
{
private TextBlock myTb{ get; set; }
public Library()
{
myTb = MainPage.mainPage.TextBlockName;
}
public void Doit()
{
myTb.Text = "there";
}
}
public void PassValue(string CBA)
{
comboBox1.Text = CBA;
}
public void PassValueA(string CBB)
{
label14.Text = CBB;
}
private void button2_Click(object sender, EventArgs e)
{
Form8 Session = new Form8(comboBox1.Text);
Session.Show();
}
This means that Form8 is missing this:
public Form8(string text) { }
If you opened the code-behind for Form8 I bet you'd see this:
public Form8()
{
// you might even have some code in here
}
BUT, don't get rid of that one, leave it there. The designer will complain next if you do that. Build the one I gave you, and put your code there. Finally, depending on what the overload does, you might want to base one constructor on another, for example:
public Form8() : this("default value") { }
That would call the overloaded constructor from the default constructor and send a default value in for the string.
Now, there is a chance you want it to go the other way. No problem, you could do this:
public Form8(string text) : this() { }
Windows Form Class by default has Parameterless constructor. But You have define a constructor as follows to pass parameter from other forms or class.
public partial class Form8 : Form
{
public Form8(string info) {
//do something
}
}
Does Form8 have a constructor that has one parameter? Something like:
using System.Windows.Forms;
public partial class Form8 : Form
{
public Form8() // This parameterless constructor is required by the WinForms Designer
{
InitializeComponent();
}
public Form8(string someValue) : this() // Constructor chaining
{
// Do something with someValue here
}
}
I'm trying to figure out why this is not working...
public static class ApplicationType
{
private static ApplicationEnum application = ApplicationEnum.App1;
public static ApplicationEnum Application
{
get { return application; }
set { application = value; }
}
public enum ApplicationEnum
{
App1,
App2,
App3
}
}
I want to access Application from another class, such as...
public partial class MainWindow : Window
{
ApplicationType. //<-- Intellisense shows only ApplicationEnum }
Thanks.
EDIT: Problem was that I was not trying inside the MainWindow as in this example as I thought I was.
You're in the middle of a class declaration. You need to declare a field, method etc. For example, this should be fine (if you make ApplicationEnum public):
private ApplicationEnum foo = ApplicatoinType.Application;
Until you've made ApplicationEnum public, you'll find that your Application property will fail to compile - you can't declare a public property of a type which isn't itself public.