Is there something like an "OnPaint" method in Silverlight? - c#

Is there something like an "OnPaint" method in Silverlight?
Back when I was writing C++, I found that it was easy to use the OnPaint event to customize the display of a class to the screen?
Is there an equivalent in Silverlight? If I want to do something when a UserControl is displayed on the screen, what method would I override?
I noticed this post:
C# WPF OnPaint method alternative?
but it seems that in Silverlight, thre is no "OnRender" method for a UserControl class.

OnPaint was a workaround... to allow you to customise the appearance of controls. That was because you did not have much control over the default appearance of any controls in WinForms applications.
With Silverlight that all changes. Every control is now effectively skinned, using templates and styles, and there are few limitations on how you can customise them. There are far too many links so I just grabbed a couple for you.
Get yourself a good book on Silverlight and learn the proper way to work with it (not around it). This one is one of my favorites.
If you have specific things you are trying to do, to the appearance of user controls, best to list those instead and find out the best way to do it the Silverlight way. :)

You haven't specified what you're trying to do. If you just want to know when a frame is being rendered, the CompositionTarget.Rendering Event will tell you that. If you actually want to draw on the frame being rendered, you cannot do so.

It is LayoutUpdated.
As in:
...
this.LayoutUpdated += new EventHandler(LayoutUpdated);
}
void LayoutUpdated(object sender, EventArgs e)
{}

Related

Functions like Focus() and properties like Focusable not available for silverlight, only .NET?

Short version: Solutions like the following: How Do I Give a Textbox Focus in Silverlight?
Don't seem to work because functions like Focus and properties like Focusable DON'T EXIST for silverlight and only exist for .net apparently.
Background/Long Version: So I've been trying to get my XNA game to work on silverlight. Porting it was a nightmare but I managed to do it somehow. Currently I want to use ViewBox's so my game is as big as a players browser instead of a set size. When I tried to do it, it VISUALLY worked, but it was impossible to send any keyboard commands to the game. I'm pretty sure its preventing me from focusing it. When I google how to give focus, it gives me links like these where people are saying to use functions like .focus() which DON'T EXIST on silverlight 5 only .NET apparently. For example go here: http://msdn.microsoft.com/en-us/library/system.windows.controls.control(v=vs.110).aspx
It shows the .NET 4.5 version. If you change it to silverlight at the top, all the nice functions and settings disappear. Am I missing something here? How do I access the .Net versions of these classes in silverlight? If its not possible why are all those answers mentioned above use Focus() etc?
Assuming C#...
On your silverlight page, select yourPage_Created from write code menu
Add the following:
partial void YourPage_Created() // this line should be autogenerated
{
this.FindControl("YourControl").ControlAvailable += YourFieldAvailable;
}
private void YourFieldAvailable(object sender, ControlAvailableArguments e)
{
((System.Windows.Controls.Control)e.Control).GotFocus += YourRoutine;
}
private void YourRoutine(object sender, System.Windows.RoutedEventArgs e)
{
// do your focus specific code in here
}
You will now have a custom focus event for the specified control.
Hope this helps :)

VCL's CustomControl equivalent in Windows Forms

Delphi's VCL has a very useful class, CustomControl. This class is a direct base class of Control, which is equivalent to C# WF's UserControl.
For those, who are not familiar with VCL, CustomControl differs very little from Control; the main difference is that most of properties are protected; when implementing the new control, developer may decide, which ones does he want to publish and which ones shall remain hidden.
I'm developing my own control for Windows Forms and I want to hide some properties and events. For instance, I don't want to expose the MouseDown event - instead I allow capturing clicking on control's elements.
Is there an equivalent of VCL's CustomControl in Windows Forms? If not, how can I hide unwanted public properties and events in my control?
In response to answers:
This is not a matter of security, but rather a matter of code elegance. In Delphi I can derive from CustomControl, leave the OnMouseDown event protected (as in C#'s protected) and say to the control's user:
You cannot use OnMouseDown, because there is none. If you want to react to user clicking on control, simply use OnElementClicked - you'll even get detailed information about which element was clicked and what was its state.
I may disable calling the MouseDown event as Hans Passant suggested, but then I would have to include the following in the control's user's manual:
Please do not use the MouseDown event, because I've overridden the OnMouseDown method, such that it won't call the MouseDown event. This is because the control's logic is designed in such way, that you should use OnElementClicked rather than OnMouseDown. Please don't criticize the control because of MouseDown not working. Please don't report it as a bug, because it is by design. Please don't post messages in forums or create blog entries explaining how to fix the MouseDown problem by inheriting the class and manually calling the MouseDown event, because it would break the control's logic. Pleas don't... damnit, told you so!
If someone actually inherits from my control - I assume then, that he knows, what he's doing (also because one would then gain access to my control's internal logic as well). But if someone just uses my control, I would give him only these properties, events and methods, that I'm sure will work as designed.
I hope it explains my motives :)
There's a fundamental difference between hiding, what you asked for, and making it inaccessible, what I assume Delphi does. Hiding is simple, just repeat the declaration and apply attributes:
using System;
using System.ComponentModel;
using System.Windows.Forms;
class MyControl : Control {
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
private new event MouseEventHandler MouseDown;
}
Which prevents the event from being displayed in the Properties window, it won't show up in the IntelliSense dropdown and generates a compile error when he tries to assign the event in code anyway.
It is however not an absolute guarantee that the client programmer couldn't work around the restriction anyway. By casting or overriding your class for example. But the ultimate backdoor is implementing the IMessageFilter interface, nothing you can do about that. So this ought to be good enough if elegance is the goal.

How to use tooltip on toolstripbutton

I'm trying to apply a tooltip to a toolstripbutton but it keeps giving me this error:
Operator '==' cannot be applied to operands of type 'System.Windows.Forms.Control' and 'System.Windows.Forms.ToolStripButton'
Any clue on how to solve this?
UPDATE:
private void toolTip1_Popup(object sender, PopupEventArgs e)
{
if (e.AssociatedControl == tBtn1)
{
using (Font f = new Font("Tahoma", 9))
{
e.ToolTipSize = TextRenderer.MeasureText(
toolTip1.GetToolTip(e.AssociatedControl), f);
}
}
}
ToolStripButton derives from ToolStripItem which has a ToolTipText property.
As already explained, the ToolStripItem does not derive from the Control class so provides its own implementation to render tool tips. This post may help you with customising the tooltip.
UPDATE: After trying this out in a Winform project and not having success, I searched other threads on SO, this is one that may be helpful to you:
Showing a tooltip on a non-focused ToolStripItem
The problem with the first is you can't set it to the button directly,
it doesn't inherit from Control, and the tooltip won't show up unless
you're over the strip but not over a button.
elsewhere
I was trying to do the same thing and determined it was going to be
pretty challenging and not worth it. The reason is that internally,
the .NET code is specifically designed to only show the tooltip if the
window is active - they are checking this at a Win32 level so its
going to be hard to fake the code out.
The user never accepted any of the answers as true, and it does seem at a glance that this may be a lot of work for little reward. Is this a project from scratch? If so, maybe you can do it using WPF, which is much more flexible than winforms.
Strangely enough, toolstripbutton class doesnt inherit from Control class unlike other System.Windows.Forms gui components. Perhaps in your code e.AssociatedControl is meant to be used with System.Windows.Forms controls. In short, I think MS hasnt decided to provide a tooltip for strip controls. I do not know your exact requirement, but for some alternative that might click, see this link.

Override OnPaint

If I override OnPaint and draw a square on the control, how do I get that e.graphics.draw... to show up when I'm previewing it in the designer?
http://msdn.microsoft.com/en-us/magazine/cc164048.aspx
http://msdn.microsoft.com/en-us/magazine/cc164145.aspx
While you could manually register with
Control.OnPaint to add your design
time UI, you'll find that overriding
OnPaintAdornments is a better option
because it is only called after the
control's design-time/run-time UI is
painted, letting you put the icing on
the cake (see Figure 20). Simply
adding DesignerAttribute to the
ClockControl class completes the
association: Copy Code
[
Designer(typeof(ClockControlDesigner))
] class ClockControl : Control { ... }
If you're trying to draw a focus rectangle for you control, and have it be visible when manipulating your control after it has been added to a form, then Gaijin42's approach should work.
If you're trying to see what your custom drawn control looks like...
If you've overriden the OnPaint method in the control, you should see the results of that OnPaint when you look at your control after it has been added to a form (or another control).
If you're trying to see the results of the Paint when looking at the designer for the control itself, I don't think that is possible (at least it wasn't with VS2005):
Unfortunately this is not possible.
While you're writing the behaviours
of the user control the code isn't
compiled and the designer actually
uses an ordinary user control to host
the child controls. The OnPaint
override etc will not run.
To debug the overrides in your control
you need to run it in some sort of
host. VS2005 provides a new control
host for this purpose but I find that
even this is not sufficient sometimes.

.Net C# Design View errors

I have subclassed a Treeview and on instantiation it loads a new ImageList (and the associated Images).
Whenever I switch to the designer view, it's also trying to run this code, however the images aren't in the designer's path, so it crashes. I ended up putting in a hack to see if the current directory is "Visual Studio", then do nothing... but that's so ugly.
I find this happening for other things. If a control is trying to use objects during load/initalization that are only available while the program is running, then the Design View cannot bring up the control.
But is there a way to get around this?
I guess what I'm hoping for is having a try/catch for the Designer (only) with the ability to ignore a few errors I know will be happening (like FileNotFoundException, etc.).
Thanks
Everything that inherits from System.Windows.Forms.Control has a DesignMode property that returns a boolean indicating if you are in design mode or not. You could use this to determine when to/when not to load external resources.
Usually it is better to move the loading of these resources to an override of OnLoad as they are rarely required directly at construction. This fixes the issue you are seeing and means that only trees which get displayed at least once will perform these additional resource loading steps.
Otherwise, you can just exclude these steps during design time by checking the DesignMode property and acting accordingly.
This is a fine pattern to use if you're making a control library with a sample of images when shown in the designer or hook ins to other designer features but as a pattern for development I'm not sure it's very effective.
I would suggest shifting your "business logic" (in this case your loading of certain images into a treeview) outside of the bounds of your treeview control. In your case I would place the logic within the Load event of the form that the control is inside:
public void Load(object sender, EventArgs e)
{
string path = "c:\somePath\toAwesome\Images";
myFunkyTreeView.AddImages(path);
}
For larger apps I personally think you want to shift the logic even out of the forms themselves, but this is debatable measure as it requires additional plumbing as a trade-off for the flexibility this provides.
Thanks for pointing me in the right directioon guys.
I had tried registering to the OnLoad event, but that event is triggered when the Design View comes up, so that didn't quite work for me (am I doing something wrong?).
Anyway, I looked a bit more into the DesignMode property. It can only work for Controls, and sometimes your object may not even be a control.
So here's the answer I prefer:
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) {
// design-time stuff
} else {
// run-time stuff
}
Found it here.

Categories