Skip navigation

So, I’ve touted the advantages of Attached Dependency Properties extensively in the forums. One of my favorite uses of Attached Properties is the fact that you can use them to attach additional functionality to an object — named the Remora Pattern by Ben Constable. Technically, I think it’s a bit of a misnomer because a Remora doesn’t provide any benefit to its host…it doesn’t harm it, but it definitely doesn’t provide any benefit. So, after a quick search through wikipedia for mutually beneficial symbiosis, I found the Egyptian Plover, also known as the crocodile bird. The plover eats parasites off of the crocodile, providing it relief from pests. In exchange, the Plover gets a veritable smorgasbord and the safest home in the Nile. Although the name remora does a good job at getting the idea of "attaching" across, it doesn’t do so well with the idea of enhancement, which is what the pattern does. However, once a pattern is named, for consistency sake, we should stick to that name. Is this technically a pattern? I can think of three instances where it could be useful, beyond the one named by Ben in his blog.

The first example I will provide is the infamous Multiselect question: how do I select all checkboxes similar to an email client allowing a user to select all of his spam for deletion with one check. Yes, I know I just linked to an example of using attached properties to perform this very task, but I use a slightly different approach that lets me demonstrate a few more neat WPF tricks.

First we’re going to need a source object that tells us whether all the checkboxes should be checked or unchecked. Let’s call it a MultiSelectionSource. Our source needs to be a DependencyObject and should expose whether or not it’s selected as a boolean dependency property

    /// 
    /// Dummy object that acts as a source for s. 
    /// 
    public class MultiSelectionSource : DependencyObject 
    { 
        public Boolean IsSelected 
        { 
            get { return (Boolean)GetValue(IsSelectedProperty); } 
            set { SetValue(IsSelectedProperty, value); } 
        } 

        public static readonly DependencyProperty IsSelectedProperty = 
            DependencyProperty.Register( 
                "IsSelected"
                typeof(Boolean), 
                typeof(MultiSelectionSource), 
                new PropertyMetadata(true));

Now we should be able to declare an instance of our MultiSelectionSource as a resource in our Window/UserControl/FrameworkElement and bind our checkboxes IsChecked property to IsSelected right? Not so fast! If we bind our CheckBoxes to IsSelected, then they are either all checked or all unchecked.

And let’s not forget the importance of the Checkbox…it probably should be binding to a property on our object model (or preferably on our Controller, but that’s another post). If they are bound to MultiSelectionSource, then they can’t bind to something else. Something else can bind to them…but let’s not get into that religious debate. Needless to say we need a way for the MultiSelectionSource to keep track of the Bindings for us. Let’s declare a list of Bindings for that purpose.

        internal List<BindingBase> Bindings 
        { 
            get { return bindings; } 
            set { bindings = value; } 
        }private List<BindingBase> bindings = new List<BindingBase>();

Notice that I declared the collection as internal. I could as well have declared it private, no one can access it from XAML. That’s not the point. The point is that we have a way to store a collection of Bindings so that the MultiSelectionSource can target the Checkboxes. So how are we going to get the bindings from the Checkboxes to the MultiSelectionSource. If you paid attention to my XML comments, you already saw it coming: with a MultiSelectionTarget.

    public class MultiSelectionTarget 
    { 
        private MultiSelectionSource source; 
        public MultiSelectionTarget(MultiSelectionSource source, String path) 
        { 
            this.source = source; 
            this.path = path; 
        } 

        public MultiSelectionSource Source 
        { 
            get { return source; } 
            set { source = value; } 
        }

        private String path;

        public String Path 
        { 
            get { return path; } 
            set { path = value; } 
        } 
    }

 I didn’t get around to commenting this guy, sue me. Actually, the code is the documentation it’s really simple your MultiSelectionTarget has a MultiSelectionSource and a String representing its path. It almost looks like a Binding…except it’s not.  The Path here represents the path on the target object (such as IsChecked on a Checkbox). And the Source will actually be the Target of the generated Binding.

So our scenario so far goes thus:

  1. In our XAML we declare a MultiSelectionSource in the Window/UserControl/Listbox.Resources.
  2. The MultiSelectionSource holds a List that it uses to track bindings with MultiSelectionTargets
  3. We declare MultiSelectionTargets on our checkboxes that point back to our MultiSelectionSource
  4. The Bindings are generated and added to the MultiSelectionSource, allowing it to (un)check a group of checkboxes at once

Hope that helps you…oh wait…how do we do steps 3 and 4, you ask? This is where the Plover Remora Pattern comes into play. But it’s past my bedtime, so that will have to wait for later.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: