Passing a Delegate to an Attribute: a simple workaround

Working on a very simple DataForm control for Winforms I had the need to pass a function delegate to an attribute that qualifies a property to generate a ComboBox on the UI. The function was mean to be used as a way to retrieve the set of values you use to populate the Items property of the ComboBox.

I quickly discovered that I cannot pass that delegate as a parameter using the standard attribute qualifying syntax because: an attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.

A quick and dirty workaround was to add a Dictionary<String, Func<IEnumerable>> to my DataForm control and a function to actually ‘register’ the delegate you want to use to populate the combox. The delegate is registered using a string key that you will later on pass to the attribute that qualifies the property.

Here are some code snippets taken from the DataForm:

...
private readonly Dictionary<string, Func<IEnumerable>> _loadItemsFunctions = new Dictionary<string, Func<IEnumerable>>();

Are you ready for the upcoming DotNetMarche workshop on July 16 ?

This announce will be particularly interesting for the people that live and work Italy: our .Net User Group DotNetMarche organizes another cross community Workshop.

This time we team up with DotDotNet, Gaia srl and Ce.S.M.I. of the University of Ancona (Italy) to offer you a complete overview over the challenges you have to face when designing and building up a Silverlight SOA application: from the relationships with the customers, the design and the UI/UX prototyping, the application lifecycle and the coding stage using various patterns...I know it’s quite an ambitious plan!

For the registration, the complete agenda and the details on the location and speakers take a look at our website: http://dotnetmarche.org

This time, thanks to the guys at Ce.S.M.I, we will also probably be able to offer you the whole workshop using internet streaming too, so if you cannot be physically there you have a chance to follow us anyway! For further details on how to attend the workshop online keep following this blog or our official DotNetMarche website.

See you there!

Related Content


Silverlight / WPF: is it possible to bind to an explicit interface indexer implementation?

The WPF binding system allows you to bind to Indexers and properties and it also have a nice feature that allows you to bind to the explicit implementation of interfaces’ members, allowing you to resolve possible ambiguities if the properties have the same names, let’s consider this simple example you have the following two interfaces and a class that implements them:

public interface IFirst
{
   string this[string index] { get; }

Exams 071-518 and 071-519 passed successfully

I’ll make this short post to test the new Windows Live Writer (which seems quite cool at a first look).

Yesterday I got some good news, I passed both the certification exams I tried some time ago:

  • 071-518 - Pro: Design & Develop Windows Apps Using MS .NET Framework 4
  • 071-519 - Pro: Designing & Developing Web Apps Using MS .NET Framework 4

Maybe I’ll try some more of them now :).

Winforms: improving rendering performances with BackgroundImage and BackgroundImageLayout

Even after years you always have something to learn...this time I had a windows forms application with a lot of graphics in it: big and heavy background images, graphic buttons with transparent background, mixed bitmaps, Jpegs and PNGs...the whole thing rendering performance was just...horrible! The form was rending slowly piece by piece (with a lot of artifacts) giving the user a very poor feeling.

To improve the rendering speed you can use some standard techniques, here are a couple of them:

  • Calling BeginUpdate() before populating data intensive controls (ComboBox, ListBox DataGrid, etc...) and EndUpdate() when done.
  • Calling SuspendLayout() and ResumeLayout() on parent controls and forms to optimize layout changes. Bounds, Size, Location, Visible, and Text for AutoSize controls causes the layout changes. You should call these methods when performing multiple layout changes and always on parent control of the controls that you are changing layout for.

However the biggest impact was given when I changed the following properties:

  • Avoid using BackColor=Transparent when it’s not strictly needed, windows forms transparency is done with a two pass rendering, so prefer solid colors whenever possible.
  • If you use BackgroundImage heavily and with very large images do not underestimate the impact of changing the BackgroundImageLayout property too: the default value it’s ‘Tile’ which means that the rendering engine will do additional computations to figure out if it have to replicate it horizontally and vertically and this is a big show stopper when dealing with performances! Change it to ‘none’ or to the value most appropriate for you (to be honest ‘none’ should be the default value here).
  • Set the DoubleBuffered property to true (you need to use reflection if you want to set this on dynamically created controls because it’s a protected method) or use:
    SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); in your control’s constructor.

My recommendation is to change the BackgroundImageLayout from the default ‘Tile’ value to something else (if you don’t really need the tile behavior) for all the controls that use a Background Image, the speed-up in rendering was surprising.

If you use PictureBoxes too, check the ‘SizeMode’ and set it to an appropriate value in order to reduce unnecessary scaling of the images.

    Related Content


    Microsoft Expression Encoder - using LiveJob, LiveDeviceSource and PreviewWindow

    For the proof of concept about a recording and encoding application I’m building, I had the need to show the preview of the actual data stream I can grab from a video source before the actual encoding job started. In the previous example you could view the result of the encoding operation and if you used that code, you could saw a delay between your actions in front of the webcam and the preview of the encoded stream.

    To solve the issue a little more dig into Expression Encoder was needed, at the point of this writing the documentation won’t help you too much cause it’s quite poor compared to the information we’re used to have from MSDN.

    So let’s introduce again our main actors:

    • LiveJob - this is the main class you use to perform the encoding from different sources, it has the ability to enumerate the devices, activate the selected sources, chose between preset encoding profiles or use your custom ones, do the dirty encoding job and show a preview of the encoded stream.
    • LiveDeviceSource - this class represent your actual source (or sources - it can mix video and audio) for the raw bits you will pass to the encoder, you can use this to gain access to the selected devices and use their configuration dialog; you can also specify a preview window to be used to see the uncompressed stream.
    • PreviewWindow - this is a wrapper around a plain old winform control or around a WPF window (something with an handle in short, see my previous post).

    To fulfill our requirement we can modify the previous Encoding service in the following way:

    • Add two properties for the PreviewWindows: one for the raw stream preview coming from the webcam (we call this LivePreviewWindow) and one for the encoded stream (we call it EncodedPreviewWindow)
    • Add a private variable to store the LiveDeviceSource we get from mixing the selected devices.
    • To display the raw preview, during the device activation we need to set the PreviewWindow property of the active LiveDeviceSource and then we need to call the ActivateSource() function on the LiveJob class (this will be done in the ActivateDevices() function) passing the newly created LiveDeviceSource as parameter; this will activate the preview.
    • To display the encoded preview, we need to set the OutputPreviewWindow of the LiveJob class before calling the StartEncoding() function (you can see it in the StartCapture() function).

    If you leave those properties empty the preview will be disabled; here’s the new code for the class:

    public class EncodingService : IDisposable
    {
    /// <summary>
    /// job used to perform the real encoding and mixing of video and audio sources
    /// </summary>
    readonly LiveJob _encodeJob = new LiveJob();