My issue is that I've created an "extended" RichTextBox control that uses native API to add many RichEdit features that are missing from the standard control (ie: modifying a single font property on a selection w/o changing the other font properties, word wrap to a printer [like WordPad], etc.). As part of the control I expose a PrintDocument that is used to print the formatted contents of the RichTextBox. When wordwrap is set to "Wrap To Printer" I SendMessage the EM_SETTARGETDEVICE message to the RichTextBox and cause it to wrap to the appropriate length.
This all works fine when something (user/code) changes the WordWrap property of my control. However if the PrintDocument is modified after that I have no way of knowing it. So even though the user may have changed the margins on the PrintDocument my RichTextBoxEx doesn't resend the EM_SETTARGETDEVICE for the new width until the WordWrap property is changed.
I see a few options to overcome this but I'm not a big fan of any of them. Here's what I have:
Add a UpdatePrintDocument() method or similiar that would need to be called after something external from the control (ie: a PageSetupDialog on the parent form) updated the settings in the PrintDocument. Cons: I'll be distributing the control so I'd like to make it as friendly as possible. While I may remember to call the method anytime I successfully update the PrintDocument settings someone else might not. Pro: It's simple to implement.
Create a new, PrintDocumentEx class that bases from PrintDocument and implements the needed "Changed" events. Cons: Might not be enough, might need to create PrintSettingsEx, PageSettingsEx, etc.. Pro: Implement once and no one has to worry about it again.
I really think #2 is the option I'm going to have to go with but it's not very reusable for the next instance I need some similiar functionality. I guess what I'm looking for is a way to attach a "generic PropertyChanged event" to any existing classes property since this would be applicable in future situations. Anxious to see what you guys have for me :-)
If I have understood your question correctly, the information that you require is sent when the WordWrap property is changed.
When other things are changed, no events updates the Print Document. The next time the WordWrap property is changed all information is sent.
The hack way to fix this is then to change the WordWrap property, whenever you change a property that you want to send to the Print Document. Change it to a temporary value, then change it back again.
Just following up that my PrintDocumentEx (and associated) classed didn't work. Looking into the PrintDialog and related controls it's because they use native methods to acctually update the PrintDocument. So the events I attached to the properties in my "Ex" classes never fired because the set accessor was never invoked.
Related
I am currently developing a chat application in C# and I would like to know which form control allows to add text retaining control to each specific message to modify it later on when is required. I want this in order to be able to add a double tick when the message is received in the other side of the communication, pretty much like in "Whatsapp".
I've thought about an approach consisting on each message object firing events (like "sent", "received"..) when it changes that are listened by the corresponding form control that serves as the view, adding the above mentioned tick.
Any advice on how to achieve this goal? I've tried TextBox but Lines property force to have control os indexes and I want it to be completely event driven. Currently I stuck with DataGridView, however I've made little to no progress.
Thanks!
No one ready made Control I can think of will do the job, I'm afraid.
I would use a FlowLayoutPanel and add a Label for each chunk of text that gets added to the chat.
You can use MeasureString with a given width to get the height of the Label. (AutoSize should be off.)
The Labels would get the Width of the FLP and you could keep a List<> of the Labels with maybe a few meta data, like user, time etc..
Sounds like a good candidate for a ChatDisplay class to bundle the whole functionality!
Of course as the Labels are Controls you can add events to them as you like to communicate with the ChatDisplay or even with an outside communications object.. And the ChatDisplay class is free to implement whatever you need anyway. If necessary you can wrap the Labels in a ChatItem class, too.
Much more extensible than digging into a DGV to force it into doing things it was not meant to do..
I'm totally stumped by this one.
Here's the setup:
RichTextBox that has your standard runs, and paragraphs. When user selects some text, hits a hotkey, I replace the selected text with a custom control derived from InlineUIContainer - let's call it CustomContainer.
CustomContainer has a single child of type TextBlock. TextBlock's TextProperty is bound to an object whose property changes.
This was done so that the text of this property cannot be edited - if you select it, or try to delete it, it deletes the entire chunk rather than any characters.
All this works beautifully.
Here's the problem:
When you click Save we take the entire RichTextBox data, serialize it, and save it to a text file. When you then reopen the file, all the bindings are re-wired as needed, and everything looks as it should.
Until the property that's bound to is changed.
At this point CustomContainer does not change. Remember, CustomContainer has a TextBlock with the Text property bound. If I look at the TextBlock in question, I can see the Text property has changed - however, visually nothing has changed. I've tried doing various things to refresh the container, but nothing seems to work. I've tried UpdateLayout, I've tried changing the binding, but nothing does the trick.
If I go and delete that CustomContainer from the RichTextBox and then highlight and hit the hot-key everything works. So the code and the binding works. Somewhere in the deserialization, rebinding, and updating of the RichTextBox, the painting of the property as it changes stops working...
UPDATE: I've managed to get it working, though I consider it a bit of a hack. I'm going to keep it open in case someone can provide me with a real solution.
What I've done is removed the custom control on load, and create a new one from scratch and insert at the same position. This is doing the trick, though I'm confused as to why (it only amounted to just calling the constructor, removing the old and adding the new. The rest of the code with the binding is all the same, so I'm still confused why this would work - or rather, why the other way doesn't)
I have application full of various controls databound to my classes. I would like to ask user "You are closing application and you made some changes. Do you want to save your changes?". For this I need to recognize that user made any changes.
How to catch user made changes in databound controls? Is textBoxXXX_TextChanged the only way to do this?
Thanks in advance for all your answers.
It depends on the datasource; for example DataTable and DataSet sources contain the GetChanges() methods which allow you to easily see if rows have been added/removed/modified. Other data sources will have their own implementations, if any. If there is no implementation then it's up to you to determine how to check for those changes.
In any event this is something you should do at the data-level, not the UI (by watching for "changed" events). Watching events doesn't scale beyond a couple controls and maintenance can be iffy.
Update: Not sure why I didn't think of it, but a second option is to add a BindingSource to your UI object and use it as a databinding proxy (your UI controls databind to the BindingSource and the BindingSource binds to the real datasource). It provides a better approach than handling all your individual "Control_Changed" events, and requiring rework of your other layers (esp. if they aren't custom data-types).
You need to provide custom logic for that, there's not really an automatic way of doing this. As I see it there are several options:
At the start of the editing, save a copy of the original data object, and when you need to check, compare the current object with the saved one. The comparison can be custom (field by field) or semi-automatic by use of serialization (compare the serialized forms) - if it is serializable.
In each of your data object's property set accessors, test for a change in value and mark the object as 'dirty'.
As been discussed, there are many ways to do this depending on how granular you want to get.
A relatively easy way using client side javascript would be to do something like the following:
Hook into the onchange events of the form elements. You could do this dynamically on page load using javascript/DOM.
When the onchange error handler is called, you could set a page level variable: pageHasChanged = true;
Hook into the page's beforeonunload event (occurs when the user tries to navigate away from the page) and check the pageHasChanged variable to see if any changes were made. If changes were made you could alert the user.
This doesn't give you the detail of what changed, but would be fairly easy to modify to track which form elements changed.
If I make a Statusbar, and PackEnd a Label to it, it looks something like this:
The Shadow disappears over the Label, but remains over the rest of the Statusbar. I want to remove the Shadow from the entire Statusbar. The PyGTK documentation mentions a property called shadow-type, but it's readonly, and nowhere to be found in GTK#. How do I get rid of this shadow?
You're not supposed to pack stuff into the statusbar, it's not meant as a general container.
To display text in a status bar, use its own API, i.e. gtk_statusbar_push() from C. The GTK# docs on go-mono.com seem to be offline, so I couldn't link to those right now.
shadow-type is a style property, which means it's actually supposed to be set by the user and/or desktop theme. You can set it by writing a custom style file for your application and reading it in using gtk.RcStyle.
If you have a need for two separate status messages in your application, you could also consider packing two status bars into an hbox.
The first child of a GtkStatusbar is a GtkFrame which gives the shadow border (edit: apparently not). You should be able to do this:
statusbar.get_children()[0].set_shadow_type(gtk.SHADOW_NONE)
Several apps (most notably Epiphany and, in the past, Galeon) actually replace the contents of that frame with an HBox so they can add stuff to the statusbar.
I have a user control that has among other things a label AND a textbox control. With this class, I set the textbox to have its modifier as "public", so when I subclass THIS control, I can get directly to the properties and such of the textbox in each instance where needed. No problem.
Now, the problem. I do the exact same thing but with a dataGridView control (and some others) within a user control. Set ITs modifier to public with intent to derive this user control downstream. Now, I try to derive this control to a NEW control and can't directly touch the dataGridView and add columns, sizing, etc directly.
I tried reproducing the described behavior and was able to do so with the GUI designer in VS 2008 using .Net 3.5. I suspect you are running into the same issue as this problem
That means to get the desired behavior you may need to implement a custom designer. There is even an example designer given by another person answering the question. Please have a look and see if that helps.