|
In a vb.net 2010 desktop application that is using a system.windows.forms.datetimepicker, I am having a problem with. The problem is the datepicker will only allow me to select one month in the past at a time. I hit the down arrow where the date is displayed and then hit the previous button where the month and year are displayed. If I want to go back 3 years in the past, I have to keep this process up 36 times.
I would think I should only have to hit the down arrow where the date is displayed one time, and then keep hitting the back button until I find the month/year I need from 3 years ago. The default selection for the datetimepicker is set today's date since this is what will be used about 95% of the time.
Thus can you tell me what I can do to solve this problem?
|
|
|
|
|
When you see the MonthCalender, displayed by the DateTimePicker, you could move the Cursor over the displayed month and year on the Top.
If you Click the Year now it changes to a NumericUpDown and you could change only the year.
Did you mean something like this ?
modified 18-Jun-15 14:25pm.
|
|
|
|
|
The DateTimePicker will only let you pick a SINGLE point date/time. It will not let you pick a RANGE of dates.
|
|
|
|
|
Hello !
On a Microsoft Word Document , even when a save a document I can undo/Redo step by step all changes that I've made ( until I close the document ).
Is it possible to mimic this behavior on an vb.net application that use a SQL server database ? ( Of course when a record is not yet saved is easily possible to Undo changes , But if is saved ?????) . I'm thinking what is the way that use an application like word to keep in memory changes and easily can move back or forward step by step.
Any idea how can this be realized on a VB.net /SQL server application?
Thank you !
|
|
|
|
|
I'd recommend a memento-pattern; would be a layer higher than the database, and works best if the data is not saved yet.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
MS Word has a comparatively easy job with undo/redo functionality because it's just a single document. Implementing undo/redo for a database application where it should also work for already saved records is a lot more complicated. It gets even more complex if you have data that has to be auditable, like financial transactions. You might want to consider just skipping this feature; after all it can't even remotely be considered standard for database applications. Or maybe implement it in a future release - from what I gather you're developing a new application currently. However..
As the granularity I would choose transactions in order to be able to maintain data integrity.
So you would have to have something like a TransactionID in every entity in order to be able to figure out which entities were created/modified/soft-deleted within the same transaction. Also a history for modified entities (which you already have or plan if I remember correctly). And then if a transaction should be undone, reverse the last action on each entity with that TransactionID. Created ones would be hard-deleted, modified ones their previous values restored from history, soft-deleted ones restored to not deleted.
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
|
|
|
|
|
It gets worse than that - if you undo your changes, you also have to undo everyone else's changes that have been made since the change you're trying to undo.
For example:
- User A adds a new customer and saves;
- User B adds a new order for the new customer and saves;
- User A now tries to "undo" the new customer;
For user A to "undo" the new customer, they also have to "undo" user B's change.
Also, updates made by other users might not have been allowed without the update made by the first user - think bank accounts, balances and transfers for example.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
This was the first horrifying thought that went through my mind when I read his question. The complexity to implement this and the implications in a multi-user environment sent chills down my spine.
My example was going to be what happens when user A hits undo while user B is saving? User B could (should) get a mysterious concurrency error or User A is going to sit there wondering why the undo didn't undo what they expected and User B is going to wonder where the changes he/she just saved went, because, well, they just got undone.
|
|
|
|
|
Well , from your opinions , seems an "mission impossible".
My idea on a multi-user environment was that if a user try to undo a record , he can return to the last state .
for example :
- User A change the record .vl=5
- User B change the record .vl=8
- User A change the record .vl=20
- User A make a record Undo.
After this undo the record .vl=8
|
|
|
|
|
Depends on the common usage scenario of your application. If, though multi-user is possible, single-user is often the case or updates are not very frequent (e.g. because it's mostly used for querying) then you could consider it. If a user would want to undo a transaction, you would have to halt all uncommitted transactions, ensure that, since selecting "undo", no other transactions have already been committed, undo that transaction and then resume normal operation. If you expect heavy multi-user usage with frequent updates I'd drop the idea.
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
|
|
|
|
|
That is a single use case.
What happens when you get this:
- User A change the record .vl=5
- User B change the record .vl=8
- User A change the record .vl=20
- User B change the record .vl=25
- User A make a record Undo.
After undo the record .vl=?????
What does the Undo undo? Is it the last change for User A (which is no longer the most current update)? Or is it the last change User B made?
User B's last change may have been milliseconds before User A hits' Undo. So what does User A expect to happen vs. what really does happen?
|
|
|
|
|
In your example , after the UserA undo , the .vl=20.
Always undo the last change.
Anyway let's suppose that the problem that 2 users try to change the same record at the almost same time , doesn't exist.
Now , technically , this Undo/Redo process how can be made ? I mean , an opinion how these "step by step changes " should be saved in order to permit Unod/Redo ?
An idea ?
|
|
|
|
|
satc wrote: Always undo the last change.
By who? From what you just said, the last CHANGES would consist of the last change User A made AND the last change User B made.
satc wrote: Anyway let's suppose that the problem that 2 users try to change the same record at the almost same time , doesn't exist.
Do not EVER make this mistake. Today, that may be the truth, but tomorrow, or next week, or next year, you can't guarantee that.
satc wrote: Now , technically , this Undo/Redo process how can be made ? I mean , an opinion how these "step by step changes " should be saved in order to permit Unod/Redo ?
An idea ?
You didn't change the circumstances under anything anyone hasn't already said. It's possible, but technically difficult and you've got a bunch of cases where unexpected things will happen because multiple people can make changes to the same data at the same time.
|
|
|
|
|
When I say "Undo the Last Change" , I mean " Undo the last change made to the record regardless of who has made the change and who is making the Undo "
At a specific time , A user X can Undo , and the last action that was performed to this record must Undo.
Yes , may be difficult , but as your opinion don't you think that would be a nice feature to have ?
Anyway , if someone has an idea how can be realized , would be a good start to try it.
Thank you !
|
|
|
|
|
You haven't been paying attention to what I've written. The reason you don't see this in applications is because if User B makes a change right before User A hits Undo, and WILL NOT KNOW about the change User B just committed, the undo is not going to undo what User A thought it should.
|
|
|
|
|
You are taking a case that has a low probability to happen.
"In a company 2 users works on the same record without knowing each other actions."
If you take this as probability , well the same problem will happen with the "Save" case.
User A and User B working on the same record trying to change the record with different values and after try to save. User A says to the boss " I change to this" , User B says "I change to this" .. So a chaos. Do you know any company works like this ?
Anyway even in your case the thing has sense.If the user B change right before the user A click Undo , The Undo process will return the state before the changes made by user B. User A can see what the undo has done and can press again undo to move up to another undo level. What's the problem here ? and just like in Word where you can see what actions you are Undo , here we can include in the Undo comments who has done the action that we are just trying to undo.
The idea of "Step by Step" Undo/Redo is to help people to return /forward to another step if they think that a mistake is done , just like in the Word where something that we have doesn't like to us we can go back step by step.
Instead of loosing time to this discussion , have someone an idea how can this be realized ?
Thank you !
|
|
|
|
|
satc wrote: You are taking a case that has a low probability to happen.
HA HA HA HA HA !!! You haven't been doing this for very long, have you? It WILL bite you in the ass! The second you say it's "rare" for that to happen, it'll happen within 10 minutes of you deploying your code to production.
Also, "rare" is not "cannot ever happen". It WILL happen and you WILL lose data when it does.
In my example, it doesn't have to be two people updating the same record within milliseconds of each other. Both users can retrieve the data, User B can update the record while User A stares at the ceiling tiles for 20 minutes before he decides to undo his last change. Guess what just happened! User A didn't retrieve the record again and didn't know that User B made a change!
How are you going to handle that? You WILL have to handle that situation.
satc wrote: Do you know any company works like this ?
Yes! The problem is called "concurrency" and people who write code have to deal with it every single day. Read up on it here[^]. There are various modes in which collisions like this can occur and various solutions to the problem, each with their pros and cons. Your job is to map your business rules to the situation and choose an appropriate method to deal with the problem, given the down side to the chosen solution.
In the website that I'm working on right now, we use two rules depending on the situation. We use either "last write wins" for data that isn't sensitive to changes of state and "optimistic concurrency" with the stuff that must maintain a consistent state across all involved fields. The later rule covering about 90% of our data.
satc wrote: just like in the Word
You absolutely can NOT compare Word to a multi-user database scenario. The problems are very different, with document editing being very easy to back out. The reason for this is because the code maintains the state of the data (Word document) completely on its own WITHOUT ANY OUTSIDE ALTERATIONS to the data being possible because only one person can edit the document at a time.
Any data in a database can be changed by anyone at any time. Your code on one workstation will not know a change was made by another workstation.
Database changes cannot be backed out so easily without very careful consideration of the different possibilities where changes are being made and accounting for every single one of them in your code. You immediately failed at this requirement the second you dismissed even one possibility as a "rare" occurrence.
Make no mistake. What you want to do is not simple. In fact, it's quite a large project in itself and many things to consider and design for, even the stuff that has only, say, a 1 millisecond window of opportunity to happen.
satc wrote: Instead of loosing time to this discussion , have someone an idea how can this be realized ?
You've already been told what you have to do and the possible pitfalls of various methods. The discussion of what you have to account for in your design and how to account for various things (given your business rules) will be a VERY long conversation and one that I doubt anyone is willing to take on in a forum environment.
|
|
|
|
|
When I say " Has a low probability to happen" ,I mean in the environment that I intend to apply it. I'm not talking in general. You don't know nothing about this , so take as TRUE that I'm saying.
Taking this supposition , can you give me an idea how to implement it or no ?
So can this be done or no , If no , ok end of the conversation.
|
|
|
|
|
satc wrote: I'm not talking in general
I'm not either.
|
|
|
|
|
Ok , then I can ensure that the case that you are talking about has almost 0 probability to happen in the environment that I'm going to use this program.
sorry , why you don't give any idea how can this be implemented ?
Because if you try to find a single justification to drop the idea , then I can tell you for example : " don't install a program in the Hard drive because the hard drive may be broken and you will loose your data ?" But how much probability has this event ?
|
|
|
|
|
satc wrote: I can ensure that the case that you are talking about has almost 0 probability to happen in the environment
May I point out that is it NOT ZERO. What are going to do when it does fail? How are you going to know?
Don't answer, I don't really care.
satc wrote: orry , why you don't give any idea how can this be implemented ?
First, because I don't have the time to write a series of articles on it.
Second, I/we know nothing about your application, it's design, your database design, your business rules, ... NOTHING.
If you want to define your problem as only one user ever uses the application at any one time, your problem becomes far far simpler. Just lookup the last transaction that was committed (and not undone) and create whatever transaction you want to reverse that.
|
|
|
|
|
Quote: First, because I don't have the time to write a series of articles on it.
Ah , finally a reason.
If I knew this from the beginning , I would not make so lot's of replies.
|
|
|
|
|
satc wrote: You don't know nothing about this Correct, thanks to the double negative.
You'll need to save the entire "state" and keep that in a stack. If you want that for tables, that means that all affected tables (and their content) become your state.
That would also only work if the state is accessed from a single location. If multiple people change state from different machines, then they will both have an incomplete list of changes, or they will affect each other.
Dave is right, the idea as a design is wrong.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Quote: Dave is right, the idea as a design is wrong.
Be more clear :
- Is wrong ?
- Is difficult to make ?
- Can't be done at all ?
- It's unusable even if can be realized ?
|
|
|
|
|
satc wrote: - Is wrong ? Yes. A undo/redo pattern applies to a current unit of work, ie, the 'dirty' document that the user is currently editing. Consider that record to be locked, and "stopping editing", moving to the next record becomes "saving a file".
satc wrote: - Is difficult to make ? Depends on how far you are willing to go. Do you want a set of tables that is edited by multiple users? Imagine user A undoing the changes of user B.
satc wrote: - Can't be done at all ? Sure it can be done; capture the entire state of your database as a single memento-item. If your database is 2 Gb, that means 2 Gb per undo/redo step
Do your users really need the functionality that bad? How would you have user A and B negotatiate about whom is right?
satc wrote: - It's unusable even if can be realized ? "Undo/redo" is aiming at the thing you are editing; it is limited to your Word/Excel/MSPaint/Whatever file/document, not to ALL documents on the network. That would create havoc, which does not count as a unique selling point
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|