Andy Smith's Blog

Page.RegisterStartupScript('Andy', 'MetaBuilders_WebControls_GainKnowledge();');

persistence in winforms

While in the proccess of making a small data-massaging winforms app, I got to thinking about persistence in winforms. Almost all “real” applications have the ability to remember certain things between sessions. Most commonly, form size and location, as well as remembering some textbox values and such. These things aren't what you'd generally call “application options”, they are just those things that people think, “it should still be in the same state as when I left it”. Well, people wouldn't actually think those exact words... more like, “why the hell does that window keep popping up in random places.” or “do i really need to fill out this textbox every single time?”

And then I got to thinking about why I seperate these kinds of properties from more the properties that I consider application options. It seems to me that it comes down to the idea that I generaly consider options to be nerd knobs that change how the application works, while form state just changes the way it looks. I'm not sure why these things are so seperate in my mind. It all comes down to some object having a property that is persisted to an external format so that the values aren't lost when the application is shut down. That's the theoretical point of view.

In the practical world tho, options are different to deal with than UI stuff. I already have an options storage pattern I use when I need to do that stuff. I use a global options class that I store in IsolatedStorage via xml serialization. For changing options, I use that property editor box ( whatevertheheck that thing is called ) to edit the global instance. You see, that form just exposes the “real” options, and my code just talks to the options class to get the important stuff.

That pattern is kind of awkward when dealing with options that are more UI centered, such as form size and textbox values. If were handling a button click that dealt with a persisted textbox value, it seems more natural to talk to the TextBox itself, not the options class, to get/set the value. So now it's the textbox that is the real authority, and the fact that it is persisted is secondary. You see how this is opposite of my traditional view of options? I don't query the options form to get the values of the property box... I just talk directly to the class facade over the storage mechanism.

So how do I resolve this?

Obviously, I'd like the best of both worlds. Keep my current natural coding mechanisms, but use the same persistance framework for everything. I think the solution lies in making some kind of two-way databinding shim between controls and the persistance framework. I was thinking that it should be some component I can drag onto the form that exposes whatever databinding interface is required so that I can edit the databindings of my controls and just point whatever properties I want to store at my component. Now, I don't know a whole lot about how the winforms databinding stuff works, but from my minimal experience there, it seems like it should work.

If anybody knows of a project already out there that does this, I'd be interested in hearing about it.

Comments

Duncan Smart said:

Is Isolated Storage always the right place to store user settings? I can see it's right for zero deployment smart client apps, but what about something a bit more substantial -ie, an installed app. How about Application.UserAppDataPath? My hunch is this is the more "Windows-friendly" place and would be integrated with roaming profiles etc:

%USERPROFILE%\Local Settings\Application Data\IsolatedStorage

%USERPROFILE%\Application Data\CompanyName\AppName\n.n.n.n
# August 19, 2003 4:35 AM

Duncan Smart said:

"winforms databinding stuff" -- here's how it should look:

AppSettings _appSettings = AppSettings.Open();

private void Form1_Load(object sender, EventArgs e)
{
textBox1.DataBindings.Add("Text", _appSettings, "UserName");
}

private void Form1_Closing(object sender, CancelEventArgs e)
{
_appSettings.Close();
}
# August 19, 2003 4:43 AM

Andy Smith said:

Isolated Storage resides in the %USERPROFILE%\Local Settings\Application Data\IsolatedStorage folder. I don't see how this is less "windows-friendly".

As for the code you've shown... that's definitely one way to do it. not sure if it's the way I would do it. I don't really like the .Close() call in Closing. Not really sure about the Open() call either.
# August 19, 2003 2:06 PM

Chris Frazier said:

I've probably got what you're saying all wrong, but what about the Configuration Application Block?
# August 19, 2003 2:17 PM

Andy Smith said:

I must admit that I hadn't looked at the CMAB yet, but now that I have... It doesn't really solve the problem I'm seeing. I want to use the DataBindings stuff to automatticly persist the values of textboxes or sizes of controls and such. Such a component may very well USE the CMAB for the actual storage, but I was thinking at a higher level of abstraction, where I just declare the doodads I want stored, and the component(s) simply do it.
Does that make more sense?
# August 19, 2003 2:36 PM

Chris Frazier said:

Pointedly.:)
# August 19, 2003 2:38 PM

Duncan Smart said:

"Windows Friendly" -- my key point here was "integrated with roaming profiles" -- in a corporate environment your Application Data can follow you around the network when you log in at different workstations. Isolated Storage won't do this as it's in the Local Settings folder.

"_appSettings.Open/Close" whatever - that's not the point. What I was trying to show was how you do the data binding. The key was:

textBox1.DataBindings.Add("Text", _appSettings, "UserName");

...not the implementation of the AppSettings class.

Just trying to be helpful...
# August 19, 2003 3:22 PM

Andy Smith said:

Yes, I know how the databindings call generally looks, but IIRC, the UserNames string there has to be a property on the AppSettings class unless I implement some neato databinding interfaces.

I'm not really looking for code here right now, it's just an idea right now.

As for the "roaming profiles" bit, yes, I don't have much experience there. But thanks to Chris's post, I'd probably be using the CMAB as the underlying datastore handler.
# August 19, 2003 3:38 PM

TrackBack said:

# August 23, 2003 10:41 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)