CustomTypeDescriptors and WPF
In some of our existing applications here at work, we use a little trick to determine whether a user has permission to click on a button or menu item. We use Active Directory to determine if the current user is in a certain group, and enable/disable the control based on that.
Today, Pete and I were discussing whether there might be a "binding oriented" (as Paul would say) way to do this, so that our newer applications (particularly WPF-based ones) could declaratively determine a control's IsEnabled state.
At first we tossed up the idea of simply building a class for each application with public properties for each potential role. For example, a public boolean property called "IsDepartmentalManager" or something. You could then bind the IsEnabled property of your button directly to that. That would work, but it means a lot of repetitive code - defining a new class with a bunch of new properties each time you created a new app.
I suggested that maybe there's a way to do it so that you simply define the roles you want as strings, and add them to a collection on a class we define only once. So I started reading about CustomTypeDescriptor and its related classes. These classes let you "fool" the binding framework into seeing properties on your class that don't really exist. For example, it's how a DataTable tells the DataGrid it's bound to what columns to show.
The end result is a class that (for now) I have dubbed "RoleProvider". It has a "Roles" property which represents the list of roles you want to define in your application, and the AD groups those roles correspond to. Here's an example. First, some XAML:
<Window x:Class="WindowsApplication2.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WindowsApplication2" Height="300" Width="300" > <Window.Resources> <ObjectDataProvider x:Key="RoleProvider" /> </Window.Resources> <Grid> <Button IsEnabled="{Binding Source={StaticResource RoleProvider},Path=IT}" Content="Only IT Can Click Here!"/> </Grid> </Window>
Pretty simple. One button whose IsEnabled property is bound to an ObjectDataProvider and a property called "IT". The theory is that if you're in that "IT" role, you're allowed to click the button. Now some C#:
public partial class Window1 : System.Windows.Window { public Window1() { InitializeComponent(); RoleProvider rp = new Qaf.Security.RoleProvider(); rp.Roles["IT"] = new string[] { "GR-COR-IT" }; ObjectDataProvider odp = Resources["RoleProvider"] as ObjectDataProvider; odp.ObjectInstance = rp; } }
So we create a new RoleProvider, add an "IT" role which is defined as a single AD Group ("GR-COR-IT"), and then point our ObjectDataProvider to it.
You'll have to trust me when I say that the application works as advertised. If you're not in the GR-COR-IT group (and hence not in our "IT" role), the button is disabled.
I'll put together a post or two about the implementation of RoleProvider next week. Stay tuned!
# Trackback from TrackBack on 7/01/2008 3:08 PM