Read and Save Location of a Form in c sharp - c#

I wanna read the location of a text file so when I reopen my Form it should be at the location I last closed it. Any way to do that?
My code to write into text files:
string path = Directory.GetCurrentDirectory() + #"\config\Loc\dateloc.txt";
if (!File.Exists(path))
{
File.Create(path);
}
try
{
System.IO.File.WriteAllBytes(path, new byte[0]);
StreamWriter writer = new StreamWriter(path, true);
string overlayloc = this.Location.ToString();
writer.WriteLine(overlayloc.ToString());
writer.Dispose();
writer.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}

get the value from file in constructor if file exist read the data get x y location and assign to location sorry for not able to understand your question in first glance i hope this works now
public Form1()
{
InitializeComponent();
string path = Environment.CurrentDirectory + #"\config\dateloc.txt";
if (File.Exists(path))
{
string loc = File.ReadAllText(path);
this.Location = new Point(Int32.Parse(loc.Split(',')[0].Replace("{X=", "")), Int32.Parse(loc.Split(',')[1].Replace("Y=", "").Replace("}\r\n","")));
}
}

Given your sample and approach, the answer you were probably initially looking for is provided by #sai kiran.
That is, you're doing ToString() of Form.Location (which is a System.Drawing.Point type) and you're writing that to a file in your approach. Note: the output string of ToString() is (X=?,Y=?), where ? is numerical characters representing the value.
Given that you are storing Location Point value that way (and not the serialized form of Point) and In order to achieve your desire result, you'll need to read that file and parse\handle the string represented value, constructing a new Point type instance from it, then assign it to Location before the form is shown.
There is NO standard Point.Parse method for this ToString string representation of Point (that I'm aware of), so you'll have to handle it with string manipulations and extrapolations. Note: if it was represented as "0, 0", you could deserialize it to Point type instance
Having said that, you can accomplish this task without specifically implementing File\Stream reads\writes nor parsing the extrapolated values of a string by using Application Settings and control Property Binding.
And actually, Using Application Settings and Property Binding is my recommended approach and answer here. I'll provide some instruction on doing that:
You'll define a Setting (for example "Form1LocationPointUserSetting") as a System.Drawing.Point in the scope of User. Since Point is a value type, it will have a default value - (0, 0)
You can define setting in a couple ways, but the easiest is probably using the Settings Designer tool of your IDE (it will generate code and update App.config)
After saving settings designer changes (with CTRL+S to save all), you will be able to both programmatically reference to the Setting property name in code and use it in control property bindings (as it relates to the Type of Property it is). Note: not all control properties support binding in this manner, and some control properties that support bind may not implement\update with INotifyProperty changes.
Lastly, you'll want to persist any changes you've made to settings. So you'll call Property.Settings.Default.Save() during some event. (such as form closing event.)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
FormClosing += Form1_FormClosing;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//Save Settings
Properties.Settings.Default.Save();
}
}

try changing
File.Create(path);
to
File.Create(path).Close();

Related

Access variable from another form in Visual Studio with c#

I'm using c# and Visual Studio. I want to access a variable from another form. I've found some things like:
textBox1.Text = form22.textBoxt17.Text;
But I don't want to access a textBox value, I just want to access a variable. I've tried this:
string myVar1 = Form2.myVar2;
But that doesn't work.
Any help?
Update
This is what I've got now:
private string _firstName = string.Empty;
public string firstName
{
get
{
return _firstName ;
}
set
{
if (_firstName != value)
_firstName = value;
}
}
In formLogin (where the variable is located), just below public partial class formLogin : Form
Then, later in code, inside button on click event:
OleDbCommand command2 = new OleDbCommand();
command2.Connection = connection;
command2.CommandText = "select firstName from logindb where username = '" + txtUsername.Text + "' and password = '" + txtPassword.Text + "'";
firstName = command2.ExecuteScalar().ToString();
I write this in formAntonyms (from where I want to access the variable) in formLoad event:
formLogin fli = new formLogin();
lblName.Text = fli.firstName;
The problem with all this is that, when formAntonyms opens, lblName is still empty, instead of showing the users name. What am I doing wrong, I've done all the steps right...
You are on the right path, you should not expose controls or variables directly to client code.
Create a read only property in the form/class you want to read the value from:
//Form2.cs
public string MyVar{get{ return textBoxt17.Text;}}
Then, being form22 the instance variable of your already loaded Form2 form class. Then, from any client code that has a reference to it, you can read the value of the property:
string myVal = frm22.MyVar;
EDIT:
Ok based in your last comment, you have a variable in Florm1 and want to access it from Form2, the principle is the same as the previous example, but instead of exposing a control property you now expose a private variable, and instead of living in Form2 it now lives in Form1:
//Form1.cs
private string _myVar = string.Empty
public string MyVar
{
get
{
return _myVar ;
}
set
{
if(_myVar != value)
_myVar = value;
}
}
The property is now read/write so you can update its value from client code
//From From2, assuming you have an instance of Form1 named form1:
string val = form1.MyVar;
...
form1.MyVar = "any";
First of all it is bad object oriented design to access variables from classes directly. It reduces maintainability and reusability.
Your problems arise, because the functionality of your objects is not clear to you.
You should not think in terms of "I want the value of this variable", but in terms of: "Suppose you have a form22, what properties should such a form have?".
Well, apparently it has a size and a position and lots of others, and apparently your form has some information that it displays, and you think that users of this form want to know the text of the displayed information.
Let's suppose the displayed information is named MyInformation. Be aware, that you can only display a description of the information. This descriptive text is not the information itself.
A proper object oriented design of your form would be
class Form22 : Form
{
public string MyInformationText {get {return ...; }
...
}
Now you are communicating to the users of Form22 that a Form22 has some MyInformation. You also communicated that you are not willing to share this information, only to share a descriptive text of the information. Furthermore users of your form can't change this information.
This gives you a lot of advantages. For instance, suppose you don't want to display the text in a TextBox, but in a ComboBox. Or maybe you don't want to display it at all anymore. The users of the form who wanted a descriptive text of MyInformation don't have to change.
Of course your design could be different if you want users of your form to change the information. Probably that would also mean that you need to change the displayed description of your information. But again: users of your form won't need to know this. Again, this gives you the freedom to change it without users having to change:
public MyInformation SpecialInformation
{
get {return this.mySpecialInformation;}
set
{
this.mySpecialInformation = value;
this.UpdateDisplay(mySpecialInformation);
}
}
It depends on your model if you should still provide a property for the displayed text or not: Should all MyInformation object in the world have the same displayed text, or could it be that the displayed text in form22 might differ from the displayed text of MyInformation in form23? The answer to this influences whether MyInformation should have a function to get the descriptive text, or whether the forms should have a function to get the descriptive text.
These are just examples to show that you should think in: what should my object do? What should users of my object be capable to do with my objects. The more you allow them to do, the less you will be able to change. You will have the greatest flexibility if you supply them with no more information than required. Besides you'll need to test much less functionality.

xml Parse Exception error when deserializing WPF

I am having problems deserializing a xaml file and get the following error
My code is as follows:
private void SerializeToXML()
{
FileStream filestream = File.Create(#"H:\test1.xaml");
StreamWriter streamwriter = new StreamWriter(filestream);
foreach (ListViewItem Item in slideListView.Items)
{
string mystrXAMLWrite = XamlWriter.Save(Item.Tag);
streamwriter.Write(mystrXAMLWrite);
}
streamwriter.Close();
filestream.Close();
}
private void DeSerialize()
{
FileStream filestream = File.Open(#"H:\test1.xaml", FileMode.Open);
XamlReader reader = new XamlReader();
slideListView = (ListView)reader.LoadAsync(filestream);
}
If I go to the XAML file after saving and change the various names it has problems with, for example changing slideCanvas to slideCanvas1 and ContextMenu to ContextMenu1, then it will load. But obviously this is not a solution and it also means that whatever is loaded back in is not pointing to the correct bits of code as they have had numbers added to the values.
Does anyone know what I need to do here?
UPDATED
Here is the xaml produced when saving one slide object
<Slide imageZIndex="0" editText="False" ClipToBounds="True" xmlns="clr-namespace:StoryboardTool;assembly=StoryboardTool" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation"><av:Canvas Background="#FFFFFFFF" Name="slideCanvas" /></Slide>
If I try to place this in a Slide Object for example
Var obj = (Slide)reader.LoadAsync(filestream);
I get this XmalParseExceptionOccured problem.
The error says cannot register duplicate name 'slideCanvas' in this scope. I can only assume that you have another control called 'slideCanvas' that is defined in your application somewhere. Have you tried searching through the entire solution for 'slideCanvas'?
Other than that, there are a few other issues that cause this exception:
Declaring a control in the Resources section using x:Name instead of x:Key.
Trying to serialize a control that has code behind.
You could also try simply removing the names from the controls and binding to them to replicate whatever functionality you named them for.
If you still have a problem, please show the XAML that is causing the error when you try to deserialize it.
How I solved this:
1. Make user control which inherits from your control
2. Add this in the constructor
static int counter = 0;
public TestControl()
{
InitializeComponent();
this.Name += counter.ToString();
counter ++;
}

CheckedListBox - Collection of FileInfo objects - Display Custom ToString

I have a CheckedListBox in a WinForms app (3.5 runtime), and I am adding a bunch of FileInfo objects to the Items ObjectCollection. The problem is that I don't like what is displayed in the CheckedListBox (since the FileInfo was from a Directory.GetFiles() it just shows the FileInfo.Name of the file in the listbox).
Is there any easy way to change what is displayed in the CheckedListBox without having to create a seperate custom class/object.
I am basically doing
checkedListBox.Items.Add(fileInfo)
and the result is just the file name of the file.
Changing display member works but I can't create something custom, only the existing properties in the FileInfo class.
I want to be able to display something like Name - FullName
Example (desired):
File1.txt - C:\Path\SubPath\File1.txt
Actually, it seems like it should be possible after all. The CheckedListBox has a FormattingEnabled property and a Format event inherited from ListBox which is called before each item is displayed. So something along these lines should work:
myCheckedListBox.FormattingEnabled = true;
myCheckedListBox.Format += (s, e) => { e.Value = string.Format("{0} - {1}", ((FileInfo)e.ListItem).Name, ((FileInfo)e.ListItem).FullName); };
Haven't tested it though. See also MSDN
Old answer:
I don't think you can do it without creating a wrapper. Although 10 lines of code don't seem all that bad to me:
class FileInfoView
{
public FileInfo Info { get; private set; }
public FileInfoView(FileInfo info)
{
Info = info;
}
public override string ToString()
{
// return whatever you want here
}
}
The additional advantage to having a view model is that you can decorate it further for display purposes all the way you like.
I dont know if there is work around for this except creating a custom class and include an instance of FileInfo inside it
and in this way you either create a new property and include a custom data in it or override the ToString() function
something like (this for demonstration purposes)
MyFileInfo
{
public FileInfo TheFileInfo;
public string CustomProperty
{
get
{
if(this.TheFileInfo != null)
return this.TheFileInfo.FileName + this.TheFileInfo.FullName;
return string.Empty;
}
}
}

How to force a new property to be serialized in designer.cs

I added a new property to a component to uniquely identify every gridcontrol in my project, called GridIdentifier:
public class MyCustomGridControl : GridControl
{
private string gridIdentifier = "empty";
[Browsable(true)]
[DefaultValue("empty")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string GridIdentifier
{
get { return gridIdentifier; }
set { gridIdentifier = value; }
}
public MyCustomGridControl()
{
if (this.gridIdentifier == "empty")
this.gridIdentifier = Guid.NewGuid().ToString();
}
}
The problem is that for existing controls in my forms, the form only serializes the new property after I change something (read: anything) within the form. It might be the caption of the form, the size, etc.
But what I would like to see is that it detects that the form has changed when I open it, so I can save it and the new property gets serialized.
Does anyone have a clue why the new property doesn't get saved after opening the form and how to fix it? Any other ideas that help are of course also appreciated.
I would guess it is doing basic sanity checking (i.e. should anything have changed) - to prevent unexpected source code changes (I hate it when opening a file can cause side-effects - I'm looking at you, DBML!).
On a side note, to force serialization generally (I don't think it will apply due to the above):
public bool ShouldSerializeGridIdentifier() { return true; }
the bool ShouldSerialize*() and void Reset*() are a convention used by the framework.

How to pass string parameter of a method from one class to another class in same namespace?

Little silly question, but got stuck for a long time.
I have written two classes one which is a Form (TreeDisplay class) and other which contains buiseness logic (MyTreeNode class).
TreeDisplay class contains browse button to select a file pass it to a method initiatingTree(string filename) which is in MyTreeNode class.
Now I have to pass this string parameter filename to MyTreeNode class. When I run my code the XML file which I have selected is shown in the textbox but not in treeview.
I have written the part of code but it is throwing NullReferenceException(Object reference not set to an instance of an object).
When the whole code was writeen in Form.cs the code was running successfully but on separating the business logic the exception has occured.
Can you please tell me where I am wrong?
This is the code in Browse button of TreeDisplay class (My main form):
if (open.ShowDialog(this) == DialogResult.OK)
{
txtFileName.Text = open.FileName;
MytreeNodeClass treenodeClass = new MytreeNodeClass();
treenodeClass.initiatingTree(open.FileName,treeView1);
}
Here is the code of initiatingTree() in my MyTreeNode class:
public class MytreeNodeClass
{
private readonly System.Windows.Forms.TextBox txtFileName;
private TreeView treeView1;
private readonly ToolStripStatusLabel toolStripStatusLabel1;
public string Filename
{
get { return filename; }
}
protected string filename;
public MytreeNodeClass()
{
}
public void initiatingTree(string nameofFile,TreeView treeView1)
{
try
{
//Create XML document & load the XML file.
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(nameofFile);
treeView1 = new System.Windows.Forms.TreeView();
treeView1.Nodes.Clear();
if (xmlDocument.DocumentElement != null)
{
TreeNode treeNodedoc = new TreeNode(xmlDocument.DocumentElement.Name);
treeView1.Nodes.Add(treeNodedoc);
}
On using breakpoint treeView1.Nodes.Clear(), the code comes out from this line and enters the catch block throwing NullReferenceException.
Please help to find root cause of exception. Thanks.
What is the value of treeView1 at your breakpoint?
I suggest this may be null, as the reference isn't available in your Business Logic Layer.
Updated with sample code:
public void initiatingTree(string nameofFile, TreeView treeView1)
{
try
{
//Create XML document & load the XML file.
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(nameofFile);
treeView1.Nodes.Clear();
if (xmlDocument.DocumentElement != null)
{
TreeNode treeNodedoc = new TreeNode(xmlDocument.DocumentElement.Name);
treeView1.Nodes.Add(treeNodedoc);
}
}
}
and where you call this:
if (open.ShowDialog(this) == DialogResult.OK)
{
txtFileName.Text = open.FileName;
MytreeNodeClass treenodeClass = new MytreeNodeClass();
treenodeClass.initiatingTree(open.FileName, treeView1);
}
As c.k said.
You don't have access to the usercontrols from your business layer as a standard.
May i suggest that you keep you control code in the gui code behind for simplicity.
An example how to sort your code
(Gui Layer) Codebehind for control interaction
Business Layer for data manipulation
Data Layer for database manipulations and such
Initialize the treeView1 object before accessing it.
I guess you copied and pasted, right?
Anyways here's a little note:
When you drag controls on a form in VS Designer, vs generates code for these controls "usually in InitializeComponent()". VS writes the references in your class (e.g form1.cs) like the following:
private System.Windows.Forms.TreeView treeView1;
this is just declaring a variable of type System.Windows.Forms.TreeView this variable (itself) is stored on the stack, because it's just a reference, a reference that doesn't point to any actual heap objects till now (i.e NullReference). Now this reference is useless and you can't use it unless you initialize it and tell it to point to a real object on the heap, and that's what VS does for you in the designer, it simply adds the next line to InitializComponents:
this.treeView1 = new System.Windows.Forms.TreeView();
And this is the line that you forgot to copy to the other class, which left your reference uninitialized (i.e still NullReference), hence when you tried to use it, a NullReferenceException was thrown. I guess this is your problem or at least this is how i could understand it. Forgive me if i failed to understand you!

Categories