I want to make sure that the following procedure is a good one since I lack experience with WPF applications. I have done some research but did not see any that meet my requirements, especially with the multi-users at a single station.
Problem: I have an application that needs to switch users with out closing. What is the best option for accomplishing this?
The Stage: I am using a MongoDb database, C# WPF, Custom Authentication. It is a single screen with other windows for Administrative tasks.
The authentication is has two options. First is a normal username and salted password following industry practices. The second I mentioned is a short log in code that is stored the same as a password (IE a username and password in one). This because it is a very busy place and a current requirement is for it to time out quickly, say 5 seconds, so others can not enter information under someone else's credentials. Up to 8 people at a time need to be able to quickly log in and add some information. The environment is a high employee theft place.
My solution: This includes the above authentication. Once logged in, the information is loaded into an ApplicationState public static object that has binding between properties and some of the objects on the screen, example displaying who is logged in. When a Command is issued it is checked against the permissions loaded into the ApplicationState to verify adequate permissions exist. The timer is on another thread, like here: http://www.codeproject.com/Articles/42884/Implementation-of-Auto-Logoff-Based-on-User-Inacti
Review: I spent a day researching and designing this solution. I could not find anyone that had the requirements I have. With my lack of experience with WPF and C#, I was not sure of the vocabulary to use in the search and my research. The other option was to rebuild the MasterWindow on every log in, but that seemed to be a bad idea. Is there another way to implement this or will this suffice? I have not completed coding it, but my tests are working.
You are asking a quite broad question here, with a number of design decisions involved which are not necessarily dependent on one another. It is a little bit hard to give a 'correct' answer here, so just a number of thoughts:
When using WPF, it really makes sense to dig into the MVVM pattern. You have probably heard of it when doing research on WPF. (If you're using it already, never mind). There's a bit of a learning curve, but it frees you of quite a few design decisions. In your case, having a ViewModel which exposes the user related properties (Username, commands for logging on and of, etc...) allows you to easily handle the account switching without worrying about the view being updated or something like that. WPF binding mechanisms will do that for you. Do some research on MVVM and INotifyPropertyChanged, if you haven't done so already.
Working with global hooks to track user action seems like a bit of overkill to me. I would consider resetting the timeout on any user action which affects the ViewModel (Add data, remove data, etc.). If this is not sufficient, than before using global OS level hooks, I would work with events on your applications window. You could subscribe to the MouseMove event of your window and reset the timeout-timer there. That should do, because as I understand the requirements, there won't be anything happening outside of your application. Global hooks usually involve a lot of P/Invoke, which is to be avoided if possible.
Apart from that, you're approach seems reasonable as far as I can tell... Though it is not an exhaustive answer, I hope it gives you some input for the next steps.
Related
I'm far from new at threading and asynchronous operations, but SL seems more prone to asynchronous issues, particularly ordering of operations, than most frameworks. This is most apparent at startup when you need a few things done (e.g. identity, authorization, cache warming) before others (rendering a UI usable by your audience, presenting user-specific info, etc.).
What specific solution provides the best (or at least a good) strategy for dealing with ordering of operations at startup? To provide context, assume the UI isn't truly usable until the user's role has been determined, and assume several WCF calls need to be made before "general use".
My solutions so far involve selective enablement of UI controls until "ready" but this feels forced and overly sensitive to "readiness" conditions. This also increases coupling, which I'm not fond of (who is?).
One useful aspect of Silverlight startup to remember is that the splash xaml will continue to be displayed until the Application.RootVisual is assigned. In some situations (for example where themes are externally downloaded) it can be better to leave the assignment of the RootVisual until other outstanding async tasks have completed.
Another useful control is the BusyIndicator in the Silverlight Toolkit. Perhaps when you are ready to display some UI but haven't got data to populate the UI you assign the RootVisual using a page that has a BusyIndicator.
In my oppinion:
1st: Render start up UI that will tell the user, that the application did register his action and is runing, (Login window may be?)
2nd: Issue neccessary calls for warm up procedures in background (WCF calls and all that) and let user know about progress of tasks that are required to finish before next GUI can be made operable (main window?)
Order of operations is kind of situation specific, but please be sure to let user know what is happening if it blocks his inputs.
The selective enabling of individual controls can look interesting, but user might go for that function first and it will be disabled, so you have to make sure user knows why, or he will be confused why at start it was disabled and when he went there 10mins later it works. Also depends on what is primary function of your program and what function would that disabled control have. If application main function is showing list of books it wouldnt be nice to make that list load last.
I am in the middle of development of a WPF application that is using Entity Framework (.NET 3.5). It accesses the entities in several places throughout. I am worried about consistency throughout the application in regard to the entities. Should I be instancing separate contexts in my different views, or should I (and is a a good way to do this) instance a single context that can be accessed globally?
For instance, my entity model has three sections, Shipments (with child packages and further child contents), Companies/Contacts (with child addresses and telephones), and disk specs. The Shipments and EditShipment views access the DiskSpecs, and the OptionsView manages the DiskSpecs (Create, Edit, Delete). If I edit a DiskSpec, I have to have something in the ShipmentsView to retrieve the latest specs if I have separate contexts right?
If it is safe to have one overall context from which the rest of the app retrieves it's objects, then I imagine that is the way to go. If so, where would that instance be put? I am using VB.NET, but I can translate from C# pretty good. Any help would be appreciated.
I just don't want one of those applications where the user has to hit reload a dozen times in different parts of the app to get the new data.
Update:
OK so I have changed my app as follows:
All contexts are created in Using Blocks to dispose of them after they are no longer needed.
When loaded, all entities are detatched from context before it is disposed.
A new property in the MainViewModel (ContextUpdated) raises an event that all of the other ViewModels subscribe to which runs that ViewModels RefreshEntities method.
After implementing this, I started getting errors saying that an entity can only be referenced by one ChangeTracker at a time. Since I could not figure out which context was still referencing the entity (shouldn't be any context right?) I cast the object as IEntityWithChangeTracker, and set SetChangeTracker to nothing (Null).
This has let to the current problem:
When I Null the changeTracker on the Entity, and then attach it to a context, it loses it's changed state and does not get updated to the database. However if I do not null the change tracker, I can't attach. I have my own change tracking code, so that is not a problem.
My new question is, how are you supposed to do this. A good example Entity query and entity save code snipped would go a long way, cause I am beating my head in trying to get what I once thought was a simple transaction to work.
A global static context is rarely the right answer. Consider what happens if the database is reset during the execution of this application - your SQL connection is gone and all subsequent requests using the static context will fail.
Recommend you find a way to have a much shorter lifetime for your entity context - open it, do some work, dispose of it, ...
As far as putting your different objects in the same EDMX, that's almost certainly the right answer if they have any relationships between objects you'll want them in the same EDMX.
As for reloading - the user should never have to do this. Behind the scenes you can open a new context, reloading the current version of the object from the database, applying the changes they made in the UI annd then saving it back.
You might want to look at detached entities also, and beware of optimistic concurrency exceptions when you try to save changes and someone else has changed the same object in the database.
Good question, Cory. Thumb up from me.
Entity Framework gives you a free choice - you can either instanciate multiple contexts or have just one, static. It will work well in both cases and yes, both solutions are safe. The only valuable advice I can give you is: experiment with both, measure performance, delays etc and choose best one for you. It's fun, believe me :)
If this is going to be a really massive application with tons of concurrent connections I would advise using one static context or one static, core context and just few additional ones just to support the main one. But, as I wrote just few lines above - it's up to your requirements which solution is better for you.
I especially liked this part of your question:
I just don't want one of those
applications where the user has to hit
reload a dozen times in different
parts of the app to get the new data.
WPF is a really, really powerful tool and basically times when users have to press buttons to refresh data are gone forever. WPF gives you a really wide range of asynchronous, multithreading tools such as Dispatcher class or Background worker to gently refresh desired data in the background. This is really great, because not only you don't have to worry about pressing various buttons, but also background threads don't block UI, so data is refreshed transparently from user's point of view.
WPF together with Entity Framework are really worth the effort of learning - please feel free to ask if you have any further concerns.
Okay, I've decided to try and get to grips with the whole TDD process from start to finish.
I'm writing a simple blog in ASP.NET MVC 2 Application and have started with doing acceptance tests to test my fetaures as I implement them. I'm using SpecFlow as my BDD/ATDD framework.
I've been reading "Growing Object Orientated Systems Guided by Tests" which is why I've started as I have.
I would be at the point described as iteration Zero in the book, where I'm creating the "Walking Skeleton"
I decided to start on the login process as my "thinnest slice of functionality that tests all components of the system". In this case, the website itself and the database.
So I wrote a story detailing logging in and the first scenario I'm writing is logging in successfully.
One of the givens in the said scenario is
"Given there is a registered user with the username 'TestUser' and password 'TestPassword'"
However I'm unsure how I would go implementing this step.
Obviously this means there needs to be a user in the database with the given credentials. However, like a good little programmer I'd want the password to be hashed in some way.
I thought of writing some sort DatabaseHelper class that can go insert that for me. However, that will contain the hashing code to hash the password, and then the application itself is going to require the same hashing code at that seems to violate DRY.
So really there are several related questions here:
Does the fact that I'm struggling with this step mean I should start from somewhere else? Even though the Login system is fairly important to the rest of the site? Perhaps it's not really the thinnest slice of functionality that tests both the website and the database?
If you'd start at the same place as I have, how would you do it? Would you not worry about DRY yet? As the Acceptance Tests test functionlity externally via the browser perhaps there's not much I can do?
I have to apologize if the question seems somewhat vague, I have no-one to learn TDD from this side, and it's one of those paradigm shifts that I've just not had that "ah-ha" moment yet.
Thanks in Advance.
If you're doing BDD, may I suggest starting not with the thinnest slice that tests all components, but instead, the thinnest slice that tests the riskiest components?
Assume that whichever user has access to the system is already logged in. Logging in isn't exactly risky. It's been done 15,000 times before.
Hard-code the data to start with. Getting data out of a database isn't very risky either. You can code this later without affecting the scenarios, if you can get some realistic examples of data.
Work out which bits of the system you know least about. Create the scenarios and have conversations around those bits of the system. You don't have to grow the system from the beginning - you can pick any point you like! Which bits of the system make you most uncomfortable? Which bits make your stakeholders most uncomfortable?
Those are probably the bits which will cause your project to succeed or fail. Logging in can come later, and by the time you come to code it, you'll have some real value that people want to log in for.
Would it be easier to start with the scenario that there is no such registered user? The system needs to handle that, too, and what it does can be written without anything more than a stub that says "no such user" for the database.
Software like OneNote has shown that auto-save can be implemented, and it works just as well (or better) as the manual save button / CTRL+S.
Anyways everything that you work on you want saved. Its just if you're trying out something destructive that you would close without saving.
So from a programmers/usability perspective, why is the manual "save" feature still seen in virtually all software today? Is it because everyone is too lazy to implement "auto-save" whenever data gets modified?
And is it a good idea for us implement auto-save, at least to start some traction in our specific industry and amongst our competitors?
autosave normally saves on a defined interval. What happens if you want to save in between intervals?
You should implement a manual save to stay consisent with other applications in the environment as well.
People expect file -> save, or CTRL + S to exist.
The save button is a well-known, comfortable UI feature that everyone from Jon Skeet to grandma is familiar with. If you got rid of it, it would be like removing the close button on a window for some people. Granted, they would eventually get used to it, but some people would not understand that their data has been saved automatically.
Also, if you're autosaving on the web, not only are you taking up a lot of space on your server with all those instances, you're also using up a lot of bandwidth with periodical saves. At least with manual save, you are only using the space and bandwidth when the user intends, which can be more infrequent, thus saving bandwidth. The advantage, of course, to autosaving is the retention of work should something go awry.
Check the definition of "skeuomorph" :)
Additionally with a "save" there is commonly "save as.." as well. Both give the user the feeling of control and security. Knowing that they clicked save lets them know at what state they can expect their data to be in when reloading it.
It really comes down to this: a Save button is cheaper to implement and maintain than Undo.
It is not hard to implement auto-save - just implement a normal save and call it when ever needed or just in a timer (if you are lazy).
Save buttons are common because of the common pattern learned by the users for decades.
Load data or files from a persistent storage into main memory.
Modify the data in main memory.
Save the modified data back to a persistent storage.
This pattern comes from the old distinction between harde drive and main memory. If you think about it in another way (as some experimental operating systems do), there is no need for loading and saving files - just think about a hard drive as your main memory and and the main memory as another cache level for the hard drive. In consequence all files (not on removeable medias) are always in memory and you will never again need to load or save files.
But doing this change is not easy because users are used to the old pattern for years. Further the old load and save pattern is an very easy way to get a kind of primitve undo system.
Auto-saving requires an undo system, too, and it is not that trivial to build one. Esspecialy if you perform image, audio or video editing and you are producing a lot of data it is hard to find a good time-memory-trade-off. And there is the risk that user will try to undo things by closing the application and then recognize that this did not work. So it might even be a good idea to persist undo information to protect users from this error or saving unwanted changes in the case of a crash.
So, yes, I would realy like to see the save (and load) buttons to disappear. I would like persisted undo-information or even complete edit histories, too. But I don't think this change can happen in a few years - if ever.
I work in the medical field and there are situations where you want the user to take responsibility for saving something. If you have an EHR and you are entering a prescription for a patient then you dont necessarily want it autosaving - you want the user to be aware of and take responsibility for their actions. Also, autosaving a value in a critical system like this could be disastrous for obvious reasons...
Should be tagged subjective maybe?
As a developer, I am always a little uneasy around apps like that. I like having control over when my data is saved, though perhaps this is just years of conditioning at work. I get that little "uh oh" feeling whenever I close a window into which I've entered data without explicitly pressing a close button (or shortcut).
That said, I have been "trained" to accept it in certain situations. OneNote, for example, or Tomboy. A great many OS X apps follow this pattern, especially utility apps like DB server GUI tools.
So, in short, different tools for different situations. IMO, most software these days would not benefit from a move from a manual save to an auto-save.
I think the answer to this is that 'it depends'!
You should consider not only your user's expectations in terms of consistency with other applications, but also the way in which the user is going to use your application.
A very common use-case for OneNote is that someone opens it up to dump in some information almost as an aside to what they're working on. They need to get in and out quickly. Any prompts about saving would be a nuisance.
Applications like Word, on the other hand, expect users to be spending a concerted amount of time working on a document. In this case, the chore of manually saving and responding to confirmation boxes etc will be seen as a relatively small task.
From programmers perspective implementing autosave would not be a huge deal. You just set up a timer and callback would do the saving.
However, from usability point of view autosave is very problematic. First of all users are used to having a manual saving and not offering it to them would confuse a majority of users and take feel of control away.
Even bigger issue would be that autosave overwrites contents of underlaying file whether you wanted it or not. Of course you could have autosave feature saving onto temporary file but the decision to overwrite original document must always come from the user, not from the software. And because you would anyways need the user to initiate at least one manual saving, why not enable manual saving to be available always?
An autosave feature is great when you are dealing with a document. What about a business application? If I edit a customer's account, should it update the account as I tab out of the edited fields? If so, what should it do when the account is in an invalid state? When do you enforce business rules and how do you enforce them? How will it perform when you have to take business rules into account on every edit?
You can certainly build an application that will take any of these considerations into account, but will it have been worth the extra effort?
So should we get rid of the Save button? It depends.
Short answer: "auto save" = "auto destroy" / "auto <expletive>".
For one project in university, my group and I built an application without explicit saving as an experiment.
We implemented an infinite undo stack and serialized the undo stack with the actual data so that even if you closed the app and re-opened it, you could always undo your last operation. Every operation wrote a new entry to the action list on disk so that the file was always consistent (well, mostly...), even if the power failed. It was a bit of a cross between a version control system and a journaling file system.
There were two problems: one, we didn't have time to get it completely right (ah, youthful hubris); two, everyone (fellow students and, most importantly, the TAs) hated it, because of all of the reasons mentioned already.
Sometimes, for all your best intentions, you just can't ignore ingrained behaviours.
The form that currently loads during when our beta WinForm application starts up is one that shows a vast array of buttons... "Inventory", "Customers", "Reports", etc. Nothing too exciting.
I usually begin UI by looking at similar software products to see how they get done, but as this is a corporate application, I really can't go downloading other corporate applications.
I'd love to give this form a bit of polish but I'm not really sure where to start. Any suggestions?
EDIT: I am trying to come up with multiple options to present to users, however, I'm drawing blanks as well. I can find a ton of design ideas for the web, but there really doesn't seem to be much for Windows form design.
I have found that given no option, users will have a hard time to say what they want. Once given an option, it's usually easier for them to find things to change. I would suggest making some paper sketches of potential user interfaces for you application. Then sit down with a few users and discuss around them. I would imagine that you would get more concrete ideas from the users that way.
Update
Just a couple of thoughts that may (or may not) help you get forward:
Don't get too hung up on the application being "corporate". Many coprorate applications that I have seen look so boring that I feel sorry for the users that need to see them for a good share of their day.
Look at your own favourite UI's and ask yourself why you like them.
While not getting stuck in the "corporate template", also do not get too creative; the users collected experience comes from other applications and it may be good if they can guess how things work without training.
Don't forget to take in inspiration from web sites that you find appealing and easy to use.
Try to find a logical "flow"; visualize things having the same conceptual functionality in a consistent way; this also helps the user do successful "guesswork".
You might look to other applications that your users are familiar with. Outlook is ubiquitous in my company, and we were able to map our application to its interface relatively easily, so we used that application as a model when developing our UI.
Note that I'm not suggesting Outlook specifically to you, just that you look for UIs that would make your users' learning curve shallower.
The problem here is that you need some good user analysis and I'm guessing you've only done functional analysis.
Because your problem is so abstract, it's hard to give one good example of what you need to do. I'd go to usability.gov and check out the usability methods link, especially card sorting and contextual interviews.
Basically you want to do two things:
1- Discover where your users think how information is grouped on the page: This will help flesh out your functional requirements too. Once you've got information all grouped up, you've basically got your navigation metaphor set up. Also, you can continually do card sorting exercises right down to page and function levels - e.g. you do one card sorting session to understand user needs, then you take one group of cards and ask users to break that down into ranks of importance. Doing so will help you understand what needs to be in dominate areas of the screen and what can be hidden.
2- Understand what tools they already use: what they do and don't like about them. You need to get a list of tools/applications that they use externally and internally. Internally is probably the most important because there is a fair chance that most people in your business will share an experience of using it. External tools however might help give you context into how your users think.
Also, don't be afraid to get pencil and paper and sketch up ideas with users. People generally understand that sketches are a quick and useful way to help with early design work and you can get an immense amount of information out of them with just simple sketches. Yes, even do this if you suck at sketching - chances are it won't matter. In fact, crappy sketches could even work in your favour because then nobody is going to argue if buttons should be blue, red or whatever.
Frankly, a form with a “vast array of buttons” needs more than a little polish. A form dedicated solely to navigation generally means you’re giving your users unnecessary work. Provide a pulldown or sidebar menu on each form for navigating to any form.
The work area of your starting form should provide users with something to actually accomplish their tasks. Among the options are:
A “dashboard” main form, showing summarized information about the users’ work (e.g., list of accounts to review and status of each, number of orders at each stage of processing, To Do schedule). Ideally, users should be able to perform their most common tasks directly in the opening form (e.g., mark each account as “approved” or not). If further information is necessary to complete a task, links navigate to detailed forms filled with the proper query results. At the very least users should be able to assess the status of their work without going any further. Note that different groups of users may need different things on their respective dashboards.
Default form or forms. Users of a corporate application typically have specific assignments, often involving only one to three of all your forms. Users who work with Inventory, for example, may almost never need to look at Customer records, and vice versa. Users also often work on a specific subset of records. Each sales rep, for example may be assigned a small portion of the total number of customers in the database. Divide your users into groups based on the forms and records they usually use. For each user group, start the app by automatically opening the user group’s form(s) populated with the query results of their records. Users should be able to complete most of their work without any further navigation or querying.
If all else fails, open the app to whatever forms and content were last open when the user quit the app. Many corporate users will continue to work tomorrow on the same or similar stuff they’re working on today.
Analyze the tasks of your users to determine which of the above options to use. It is generally not productive to describe each option to the users and ask which they like better.
BTW, “Reports” is probably not a particularly good navigation option. It’s better if you consistently identify things primarily by what they show, rather than how they show it. Users may not know that the information they want to see is in a “report” rather than a form, but they’ll know what content they want to see. Reports on inventory are accessed under Inventory; reports about sales are accessed under Sales.
Have you tried asking your end users what they would like? After all they are the ones that are going to be using the system.
I use components from the company DevExpress. They have some really cool controls (such as the Office 2007 ribbon), form skinning utilities (with a vast amount of different skins), and a load more...
If you want to check it out they have 60 free components - if its corporate though you might have to check the licence but you can get it at... DevExpress 60 Free
I suggest starting with the design principles suggested by Microsoft: Windows User Experience Interaction Guidelines
Some places to get ideas for interaction designs:
Books
About Face 3 - The Essentials of Interaction Design
Don't Make Me Think (this is focused on web design, but many of the principles carry over to Windows design)
Web Sites
Windows User Experience Interaction Guidelines
In addition, many applications have free trial versions that you can download to determine how they handle user interaction. Also, don't discount items on your desktop right now.
Do you have any statistics or insights concerning what the most commonly-used or important functions might be? If so, you could use that to pare down your "vast array of buttons" and highlight only those that are most important.
That's sort of a trivial example, but the underlying point is that your understanding of your audience should inform your design, at least from a functional perspective. You might have past usage statistics, or user stories, or documented workflows, or whatever - even if you're drawing a blank right now, remember that you have to know something about your users, otherwise you wouldn't be able to write software for them.
Building on what they already know can make it easy on your users. Do they live in Outlook? Then you might want to mimic that (as Michael Petrotta suggested). Do they typically do the same thing (within a given role) every time they use the app? Then look for a simple, streamlined interface. Are they power users? Then they'll likely want to be able to tweak and customize the interface. Maybe you even have different menu forms for different user roles.
At this stage, I wouldn't worry about getting it right; just relax and put something out there. It almost doesn't matter what you design, because if you have engaged users and you give them the option, they're going to want to change something (everything?) anyway. ;-)