C#/WPF - IsElement as a class property/attribute? - c#

I am trying to remake my C#/WPF take on the Simon game by making it more clean and use classes now that I finally understand classes. Before I ask my question - here is some sample code from my old version as a reference.
public MainWindow()
{
InitializeComponent();
RedButton.IsEnabled = false;
BlueButton.IsEnabled = false;
GreenButton.IsEnabled = false;
YellowButton.IsEnabled = false;
}
//Use TextBlock clearing to say "Watch the pattern", "Your Turn" and then an empty box between games
private void StartButton_Click(object sender, RoutedEventArgs e)
{
_IsError = false;
RedButton.IsEnabled = true;
BlueButton.IsEnabled = true;
GreenButton.IsEnabled = true;
YellowButton.IsEnabled = true;
StartButton.IsEnabled = false;
if (randomPattern.Count == 0)
{
randomPattern.Add(random.Next(0, 4));
randomPattern.Add(random.Next(0, 4));
}
StatusBox.Text = "Watch the Pattern.";
ShowPattern();
}
So, my question is: Would it be good practice for me to use IsElement as a property/attribute of class "Buttons" instead of writing all of their statements out individually? And if I should add them to the class, I think my next question comes down to - how would I implement it into the class? I know simply typing only "IsEnabled = <T/F>" won't do anything.
EDIT:
To show you what I mean:
Should I have IsEnabled as a class property like such:
class Button {
IsEnabled = false;
}
var greenButton = new Button()
//Some code that lets the player start the game by clicking a button
greenButton.IsEnabled = true;
Or should I keep my IsEnabled statements outside of a class like in my old version of the code? Note - my old version of the code, there are no classes that I made - only functions.

IsEnabled should be placed into Button class as it is property or feature of button.
public class Button {
public IsEnabled { get; set; }
}
The above class has high cohesion as it is focused on what it should be doing. It has only methods/properties, fields relating to the intention of the class.

Related

C# - Enable/Disable MenuStrip Item Based On TextBox Value

I am trying to disable some menu strip items while a textbox is displaying "Calculating...". Once that value goes away, I wish to re-enable the menu items. Its purpose is not to interrupt MD5/CRC32 calculations. So far, I've tried various method of code, and have had no luck so far. What's listed below should work, but for some reason it does not. Any help would be appreciated.
// THIS PART WORKS
if (boxMD5.Text.Contains("Calculating") == true)
{
openROMToolStripMenuItem.Enabled = false;
saveROMDataToolStripMenuItem.Enabled = false;
asTXTToolStripMenuItem.Enabled = false;
asHTMLToolStripMenuItem.Enabled = false;
}
// THIS PART DOES NOT WORK
else if (boxMD5.Text.Contains("Calculating") == false)
{
openROMToolStripMenuItem.Enabled = true;
saveROMDataToolStripMenuItem.Enabled = true;
asTXTToolStripMenuItem.Enabled = true;
asHTMLToolStripMenuItem.Enabled = true;
}
I can't quite tell you why the code isn't doing what you expect, but I can make a suggestion that will change your approach and may help achieve your goal at the same time. What you are trying to do shouldn't be to disable the menu when the textbox contains "Calculating" but instead you should disable the menu while the calculations are being performed. From a user/UI perspective, these are the same thing, but the inner-workings of your program know better.
Based on you PasteBin code, try this:
private void openROMToolStripMenuItem_Click(object sender, EventArgs e)
{
//Other code omitted for brevity
if (File.Exists(OpenFileDialog1.FileName))
{
UpdateUI("Calculating...");
backgroundWorker1.RunWorkerAsync(OpenFileDialog1.FileName);
}
//Other code omitted for brevity
}
and
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
UpdateUI(e.Result.ToString());
}
where the new method UpdateUI() looks like this:
void UpdateUI(string hash)
{
var calculating = hash == "Calculating...";
if (!calculating)
{
progressBar1.Value = 0;
}
openROMToolStripMenuItem.Enabled = !calculating;
saveROMDataToolStripMenuItem.Enabled = !calculating;
asTXTToolStripMenuItem.Enabled = !calculating;
asHTMLToolStripMenuItem.Enabled = !calculating;
boxMD5.Text = hash;
}
Also, notice how you are able to just put !calculating in the if statement rather than calculating == false. This is because the value is already true or false so you don't have to compare it to anything to figure that out. The same thing applies to your original code but you don't need it anymore with this approach.

Accessing class from form and vice-versa

After hunting the internet for two days and not finding a solution that I can understand properly I have to ask on here for an answer.
I have a windows forms application that was written in vb.net and works fine. I have decided to rewrite this in c# which I thought wouldn't be too much of a problem but ...
I have two classes in the project :
FormJobs & AppJobs
FormJobs contains methods and functions that modify the forms in some way.
AppJobs contains methods and functions for everything else (Checks,Scanning and so forth).
On my main form (FrmStart) the On_load event uses a function from AppJobs to check that the network is up (public bool CheckNetConnection) and then Checks to make sure that the root save folder exists (public void CheckRoot).
If CheckNetConnection is false or CheckRoot does not exist then a method in the FormJobs class sets some buttons to disabled, some labels to display information as to what has gone wrong and also sets the height of the form.
The above works in VB.net but I keep getting a StackOverflowException or NullReferenceException with the C# code.
I know the reason for the Exceptions is because the two classes and the form all keep calling each other so I know that I need to remove this code but I am not sure how to let each class and the form access each other. It is obviously bad design as I`m just starting to learn C# so any help on this would be much appreciated.
But my main questions are:-How do I get a form to access multiple classes?
Allow the classes to access each other?
Let the classes make changes to a form?
FrmStart Code
AppJobs Appjobs = new AppJobs();
private void FrmStart_Load(object sender, EventArgs e)
{
KeyPreview = true;
if (Appjobs.CheckNetConnection(this) == true)
{
Appjobs.CheckRoot(this);
}
AppJobs Code
public class AppJobs
{
FormJobs Formjobs = new FormJobs();
public string AppRoot = Properties.Settings.Default.DefaultFolder;
public string DefaultDevice = Properties.Settings.Default.DefaultScanner;
public bool NoDirectory = false;
DialogResult MsgBoxQuestion;
public bool CheckNetConnection(Form StartForm)
{
IPHostEntry ServerIP = new IPHostEntry();
bool ConnectedToServer = false;
string CurrentRoot = "MyServer";
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
try
{
IPHostEntry DNSTest = Dns.GetHostEntry(CurrentRoot);
if (DNSTest.AddressList.Length > 0)
{
ConnectedToServer = true;
}
else
{
ConnectedToServer = false;
}
}
catch (System.Net.Sockets.SocketException ex)
{
ConnectedToServer = false;
}
}
return ConnectedToServer;
}
public void CheckRoot(Form StartForm)
{
if (string.IsNullOrEmpty(AppRoot))
{
Formjobs.SetHeight(StartForm);
return;
}else if(AppRoot == "0")
{
Formjobs.SetHeight(StartForm);
return;
}
else
{
if ((!Directory.Exists(AppRoot)))
{
NoDirectory = true;
MsgBoxQuestion = MessageBox.Show(AppRoot + " is set, but the directory does not exist." + Environment.NewLine
+ Environment.NewLine + "Would you like to create the folder now?", "Root folder missing", MessageBoxButtons.YesNo);
if (MsgBoxQuestion == DialogResult.Yes)
{
Directory.CreateDirectory(AppRoot);
NoDirectory = false;
}
else
{
MessageBox.Show("You will not be able to use this program until you create a root folder.", "No root folder selected",MessageBoxButtons.OK);
}
}
}
}
}
FormJobs Code
public class FormJobs
{
AppJobs Appjobs = new AppJobs();
public void SetHeight(Form StartForm)
{
if (Appjobs.AppRoot == null | Appjobs.AppRoot == "0") {
if (Appjobs.DefaultDevice == null | Appjobs.DefaultDevice == "0") {
if (StartForm.Controls["MenuStrip1"].Visible == true) {
StartForm.Height = 167;
StartForm.Controls["LblNoRoot"].Visible = true;
StartForm.Controls["LblNoRoot"].Location = new Point(0, 24);
StartForm.Controls["LblNoRoot"].Text = "There is no root folder selected. Please select a root folder to continue.";
StartForm.Controls["LblNoDevice"].Visible = true;
StartForm.Controls["LblNoDevice"].Location = new Point(0, 48);
StartForm.Controls["LblNoDevice"].Text = "There is no default device selected. Please select a default device to continue.";
StartForm.Controls["BtnOkTickets"].Enabled = false;
StartForm.Controls["BtnQueryTickets"].Enabled = false;
StartForm.Controls["BtnSearch"].Enabled = false;
}else
{
StartForm.Height = 147;
StartForm.Controls["LblNoRoot"].Visible = true;
StartForm.Controls["LblNoRoot"].Location = new Point(0, 9);
StartForm.Controls["LblNoRoot"].Text = "There is no root folder selected. Please select a root folder to continue.";
StartForm.Controls["LblNoDevice"].Visible = true;
StartForm.Controls["LblNoDevice"].Location = new Point(0, 33);
StartForm.Controls["LblNoDevice"].Text = "There is no default device selected. Please select a default device to continue.";
StartForm.Controls["BtnOkTickets"].Enabled = false;
StartForm.Controls["BtnQueryTickets"].Enabled = false;
StartForm.Controls["BtnSearch"].Enabled = false;
}
}
One of the causes of your problems is that everyone is changing your StartForm. Apart from that this spaghetti makes it difficult to understand, it certainly doesn't help to make your classes reusable and maintainable if your Startform changes.
It seems to me, that AppJobs is meant to decide what the form should look like (for instance it decides that the StartForm should change height), while FormJobs performs the calculations needed to change this height. StartForm apparently is just allowing to let everyone make changes to him.
A better design would be that StartForm would not ask AppJobs to change its size, and to ask the operator whether a folder should be generated. Instead if ought to ask appJobs for advise: "Which height do you think I should have". after that it could ask FormJobs: "Please adjust my height according to this specification"
FormJobs should trust StartForm that it has gathered the correct information about how a StartForm ought to look like. FormJobs should not ask AppJobs for any information: "Hey AppJobs, StartForm asked me to change its appearance to certain specifications, but I'm not certain whether StartForm has done its job correctly. Please tell me if these specifications are correct, and give me some missing information")
The correct division into tasks would be:
AppJobs specifies the format of any StartForm according to its internal state (a.o. AppRoot, and existence of certain folders)
StartForm is the one who displays all items. He decides who to ask for specifications, and what to do with the returned specifications. He is also the only one who communicates with operators
FormJobs is a class that apparently knows all elements from a StartForm. If you will only have one type of StartForm, then Appjobs should be part of the Startform class. If you think there might be several different Startform classes, all with the same elements that ought to be manipulated similarly, shouldn't all these StartForm classes be derived from a FormJobs class?
Anyway, redesign without everyone causing to manipulate StartForm
Apparently there are a limited number of StartForm layouts depending on AppRoot, defaultDevice etc. You seem to be missing some "else" after your if, so this list might not be accurate. Still you will get the idea:
enum StartFormLayouts
{
DefaultDevice0,
AppRoot0,
Other,
}
// class that specifies the layout of any startform
class AppJobs
{
private bool IsAppRoot0
{
get{return Appjobs.AppRoot == null || Appjobs.AppRoot == "0";}
}
private bool IsDefaultDevice0
{
get{return Appjobs.DefaultDevice == null || Appjobs.DefaultDevice == "0";}
}
public StartFormLayoug GetPreferredLayout()
{
if (this.IsAppRoot0)
{
if (this.IsDefaultDevice)
{
return StartFormLayout.DefaultDevice0;
}
else
return StartFormLayout.AppRoot0;
}
else
{
return StartFormLayout.Other;
}
}
public bool ShouldAskDirectoryCreation()
{
return (!this.IsAppRoot0 && !Directory.Exists(AppRoot));
}
}
Note that this class doesn't need StartForm, nor AppJobs. It could work with any class that wants to know if it should ask for DirectoryCreation. Since it also does not speak any language, even a Chinese StartForm could use it. After all, the StartForm is the only one who knows what language it speaks and what to do if a certain layout is requested.
Furthermore, did you notice that I used a double || to use a Boolean OR instead of a bitwise or?
And I use statements like if (a) instead of if(a=true) a C# Boolean is a real Boolean, in contradiction to Booleans in C and C++.
The class of all kinds of forms that should be able to be layout according to the requested layout contains the functions similar to your
It depends a bit of whether you decide to let it be a base class of StartForm or StartForm itself. If you want it to handle every form class that has the required controls, consider of using an interface:
public Interface IStartForm
{
public int Height {get; set;}
public Label LabelNoRoot {get;}
public Label LabelNoDevice {get; }
public Button BtnTickets {get;}
...
This way you can set the size of any form that has these labels and buttons, even if they have different names than those strings you use.
But again: if you ever only want to size StartForm, then this should be a function in StartForm.
public SetHeight(StartFormLayout layout, IStartForm startForm)
{
switch (layout)
{
case StartFormLayout.DefaultDevice0:
if (startForm.MenuStrip.Visible)
{
startForm.Height = ...;
startForm.LabelNoRoot.Location = ...
// etc
}
else
{
...
Noticed that because of this separation of concerns the AppJobs and FormJobs don't have to know each other. AppJobs and FormJobs also don't really have to know what 'StartForm` is, only that it has the labels and buttons etc that it needs to change.
class StartForm : Form, IStartForm
{
public Label LabelNoRoot {get{return this.label1; } }
...
private void FrmStart_Load(object sender, EventArgs e)
{
AppJobs layoutdesigner = new AppJobs(...);
StartFormLayout layoutdesigner = layouter.GetPreferredLayout();
FormJobs layouter = new FormJobjs();
layouter.SetHeight(this)
}
Noticed that my form didn't have a label named "LabelNoRoot", but a Label1 that should function as a LabelNoRoot. Also: because I used types instead of string, You can be certain that I can't handle a label as if it was a button. I can't by accident try to press the label. Something that could easily been done when you were using strings to identify the items you want to layout.
Extending the comments: you just remove the new part in your FormJobs and AppJobs classes.
leaving the code in i.e. in the FormJobs class like : AppJobs appObj;
Then in your main form create at some point a FormJobs obj and an AppJobs obj and set its property.
I.e. in main Form:
AppJobs appObj = new AppJobs();
FormJobs formObj = new FormJobs();
formObj.appObj = appObj;
Tho I must say i dont like that approach you are taking with this...
You should think of another way or at least refactor your code that FormJobs does not need AppJobs methods and vice versa in a way that all calls to FormJobs and AppJobs come from your main form.

c# application interface is loading slow

I'm creating a interface for a application at the moment. Background are all 1x1 pixel. In design time the interface is super slow (visual studio 2012). Moving components is super laggy. If I run the application it takes about 10 seconds for the interface to load.
Some parts of the interface can be hidden. Ones they become visible again they take time to build up / load part by part.
How can I improve this and make the interface much smoother / loading faster?
Source code:
namespace WindowsFormsApplication1
{
public partial class MapTool : Form
{
public int Pin_Berekenen = 0;
public int pin_Settings = 0;
public MapTool()
{
InitializeComponent();
BlackSetupUI();
panel_Berekenen.Visible = false;
panel_settings.Visible = false;
}
void BlackSetupUI()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
SetStyle(ControlStyles.Selectable, false);
pictureBox_RouteBerekenen.BackColor = Color.Transparent;
panel_Berekenen.BackColor = Color.Transparent;
pictureBox_settings.BackColor = Color.Transparent;
button_pin_berekenen.FlatAppearance.BorderSize = 0;
button_Berekenen.FlatAppearance.BorderSize = 0;
label_berekening1.Parent = pictureBox_bar;
label_berekening1.BackColor = Color.Transparent;
label_Berekening2.Parent = pictureBox_bar;
label_Berekening2.BackColor = Color.Transparent;
label_verschil.Parent = pictureBox_bar;
label_verschil.BackColor = Color.Transparent;
button_pin_settings.FlatAppearance.BorderSize = 0;
label_RouterBerekenen.Parent = pictureBox_bar;
label_Settings.Parent = pictureBox_bar;
pictureBox_settings.Parent = pictureBox_bar;
pictureBox_RouteBerekenen.Parent = pictureBox_bar;
pictureBox_innectis.Parent = pictureBox_bar;
label_innectis.Parent = pictureBox_bar;
}
void WhiteSetupUI()
{
}
private void MapTool_MouseClick(object sender, MouseEventArgs e)
{
if (Pin_Berekenen == 0)
{
panel_Berekenen.Visible = false;
}
else
{
return;
}
if (pin_Settings == 0)
{
panel_settings.Visible = false;
}
else
{
return;
}
}
private void button_pin_berekenen_Click(object sender, EventArgs e)
{
switch (Pin_Berekenen)
{
case 0:
Pin_Berekenen = 1;
button_pin_berekenen.Image = Properties.Resources.Pinned;
break;
case 1:
Pin_Berekenen = 0;
button_pin_berekenen.Image = Properties.Resources.Pin;
break;
default:
break;
}
}
private void button_pin_settings_Click(object sender, EventArgs e)
{
switch (pin_Settings)
{
case 0:
pin_Settings = 1;
button_pin_settings.Image = Properties.Resources.Pinned;
break;
case 1:
pin_Settings = 0;
button_pin_settings.Image = Properties.Resources.Pin;
break;
default:
break;
}
}
private void pictureBox_settings_MouseHover_1(object sender, EventArgs e)
{
panel_settings.Visible = true;
}
private void pictureBox_RouteBerekenen_MouseHover_1(object sender, EventArgs e)
{
panel_Berekenen.Visible = true;
}
}
}
I'm just designing the interface there is no data loaded with in this application as you can see.
It is hard to tell what exactly is your interface "doing". But here are some general tips:
You can preload something while showing splash screen (with or without progress) and then doing all time consuming work (to example, constructing all forms, parsing all configurations, caching graphics, etc). Or even put main application into dll and making exe-file small with the only splash screen.
You can optimize parent/child controls redrawing and layout operations (BeginUpdate/EndUpdate and such), so you don't waste time by calling unnecessary draw operation until it's a right time for it to happens. You can use double buffering, WS_EX_COMPOSITED.
If you have to much calculations, then perhaps something has to be virtualized (you display "fast placeholders" and after caculation replace them with real data) or cached.
You can use one of many tricks to simulate faster (as user can feel) operation: show a small part of data on screen, while prepare a much bigger portion of data in the memory (sort of virtual window), add some intelligent conclusions and caching (if user is moving left, then perhaps he want to continue that way, preload more data from left or, if user is moved right by 100 pixels, perhaps he will want to return, so don't unload that data yet).
Perhaps you have to much data what you have to profile it and optimize or even use C++ to write speed demanded parts in separate dll's.
Or maybe you should redesign your UI, split common parts into control, put nested things into user controls, etc, etc..
Hide all of them then when it is fully loaded, show it up
If you want to show animation, you can use Bunifu UI (paid)

C# Setting Custom Properties of SSIS custom data flow component through custom UI

I'm having a real problem trying to set a custom property of a data flow component I've created through a custom form.
The value I'm assigning is just now being set, the custom property either remains the original value or stays null.
In my TaskClass I've overridden the ProvideComponentProperties() method and I've created the custom property as shown below.
IDTSCustomProperty100 componentCustomProperty = ComponentMetaData.CustomPropertyCollection.New();
componentCustomProperty.Name = "PAFProvider";
componentCustomProperty.Description = "PAF Provider";
componentCustomProperty.Value = "testinitial";
I've created a TaskClassUI which inherits from the IDtsComponentUI interface. I implement all required methods.
My Initialise method.
public void Initialize(IDTSComponentMetaData100 dtsComponentMetadata, IServiceProvider serviceProvider)
{
this._dtsComponentMetaData = dtsComponentMetadata;
this._serviceprovider = serviceProvider;
}
The implementation of my Edit Method
public bool Edit(IWin32Window parentWindow, Variables variables, Connections connections)
{
bool flag;
try
{
PAFUIMainWnd ui = new PAFUIMainWnd(this._dtsComponentMetaData, this._serviceprovider, connections);
DialogResult result = ui.ShowDialog(parentWindow);
bool flag1 = result != DialogResult.OK;
if(!flag1)
{
flag = true;
return flag;
}
}
catch(Exception exe)
{
MessageBox.Show(exe.ToString());
}
flag = false;
return flag;
}
And the implementation of my UIFORM.
public PAFUIMainWnd(IDTSComponentMetaData100 iDTSComponentMetaData100, IServiceProvider serviceProvider, Connections connections)
{
this.components = null;
this.InitializeComponent();
this._dtsComponentMetaData = iDTSComponentMetaData100;
this._designTimeComponent = this._dtsComponentMetaData.Instantiate();
textBox1.Text = _dtsComponentMetaData.CustomPropertyCollection["PAFProvider"].Value.ToString();
}
And just for testing purposes I've stuck a textbox and a button on my form. The OnClick even for the button is below. I'm just taking the value from the textbox and assigning it to the Custom Property but its not assigning it. I can read the original value from the Custom Property which I assign to the text box. I just dont understand why I can't assign it. I've followed the MSDN and various other examples through completely. If anyone can point out what I've done wrong I would be very greatful. Its gotten to the head banging stage.
private void btnOK_Click(object sender, EventArgs e)
{
_designTimeComponent.SetComponentProperty("PAFProvider", textBox1.Text);
this.Close();
}
A restart fixed this. The code was perfectly fine.

Virtual member call in constructor [duplicate]

This question already has answers here:
Virtual member call in a constructor
(18 answers)
Closed 9 years ago.
In my application I am running the same winform in different contexts to control visibility of buttons, enabeling of text fields and the winform header text.
The way I decided to do this is simply by passing a string to the form constructor and check it with a couple of if statements that in turn contain the desired winform tweaks.
if (formContext == "add")
{
Text = "Add member";
}
if (formContext == "edit")
{
Text = "Change role";
userTextBox.Enabled = false;
searchButton.Visible = false;
}
This works fine, however the "Text" keywords get a blue squigly line added by ReSharper with the following message: Viritual member call in constructor.
Is this a potential problem or just some sort of overly enthusiastic ReSharper message.
Any clarification or suggestions for improvement of my implementation would be much appreciated.
A virtual member call in the base class ctor could cause some logic to run in the subclass before the subclass' ctor is called (and thus before the object gets a chance to initialize itself to a consistent state).
It's just a nice reminder so you know you are doing something that could potentially cause some nasty unexpected behavior.
In addition to the existing answers, for forms you could add a Load event handler:
Load += delegate
{
if (formContext == "add")
{
Text = "Add member";
}
if (formContext == "edit")
{
Text = "Change role";
userTextBox.Enabled = false;
searchkButton.Visible = false;
}
};
Just seal your class.
I would suggest rewriting you class as follows:
public partial class Form1 : Form
{
public enum FormContextMode
{
Add,
Edit
}
private FormContextMode m_mode = FormContextMode.Add;
public Form1( FormContextMode mode )
{
InitializeComponent();
m_mode = mode;
Load += delegate { UpdateForm(); };
}
private void UpdateForm()
{
if( m_mode == FormContextMode.Add )
{
Text = "Add member";
}
else if( m_mode == FormContextMode.Edit )
{
Text = "Change role";
userTextBox.Enabled = false;
searchkButton.Visible = false;
}
}
}

Categories

Resources