Category: Uncategorized

  • New Silverlight Juicyness

    Only 3 months after the release of SL3 comes the beta for SL4.  And to be honest it just gets better and better. Following on from David Poll’s excellent PDC session (Building Line Of Business Applications with Silverlight 4) the following bits really got my juices flowing!;

    “Learn about enhancements to data binding and data validation as well as new support for rich text & printing in the platform that allow you to build compelling LOB user experiences. In addition, you will see how you can incorporate webcam & microphone support into your applications using Silverlight 4.”

    This was a good “hand-on” session from David Poll, Silvelight Program Manager. As always, there was a lot of cut-and-paste code, but most concepts where demonstrated well enough to get a grasp of what was required, and the MVVM pattern was talked about on many occasions.

    Interactive Design Surface in VS2010

    The design surface in VS2010 is interactive for XAML controls. This will allow the proofing and creation of layouts from within VS (rather than being forced to switch to Blend). Most properties (including element Binding) can be set from within VS visual design surface. This didn’t crash during the demo – hopefully this will be more stable than the early versions of Blend.

    Data-binding Enhancements

    Binding now supports string formatters – very useful feature for eg enabling the formatting of strings inline in the XAML using standard .NET format codes (e.g. {0:d}) rather than having to create separate format classes.

    
    

    Binding to dictionaries is also added, again simplifying the development process to display controls for simple enumeration types.

    Binding support has been extended to include any DependencyObject, not just objects which derive from UIElement.

    New values have been introduced to binding to support a “FallbackValue” and “TargetNullValue” which will handle the displayed values in situations where a property setter exception occurs and the value is set to Null respectively.

     

    Data Related Controls

    Datagrid now supports “star” based columns. This allows columns to fit the available screen space – much more akin to what we are used to with HTML tables.

    Datagrid supports copy and paste – good potential for copying information to Excel. I have also seen (in the Day 2 keynote) that there is support for calls directly into the Office API. Export to excel will either be possible in SL4 or available in the very near future.

    Combobox will support both SelectedValue and SelectedValuePath – which have been missing to this point. This will simplify the XAML used to display simple comboboxes, which was overly onerous for such a simple control.

    The CollectionViewSource type is enhanced to provide data grouping (this would be ideal for large datagrids of information (case enquiry / allocation).

    Commanding has been introduced as a first-class property on appropriate controls (ButtonBase and Hyperlink). We will not need to attach the commanding properties from the Prism assemblies.

    Input Validation

    Validation is now supported from a service, and responses sent back to the UI via INotifyDataErrorInfo. This is a massive improvement to the validation API and will be hugely beneficial for our product. We no longer have to rely on exceptions in property setters to trigger UI validation controls. Errors raised in the service can be bubbled into the UI easily and displayed using the existing validation controls. Dependency validation can also be achieved in this way.

    Printing Support

    Printing support is added to native applications. This will allows relatively simple setup of printing direct from the UI.

    Any UI element can be printed, and it does not need to exist in the currently displayed Visual Tree.

    Paging is supported and appeared straight forward to control.

    Other Features

    Other interesting functionality in the SL4 beta but not included within this presentation, includes:

    • Implicit Styling – no more explicit style references J
    • Right Click and Mouse Wheel support
    • Native Drag and Drop
    • Clipboard API
    • New controls

      • Viewbox control added (for auto scaling content)
      • Rich text box

    • Hosting of HTML content
    • More advanced out of browser features

      • Notification (“Toast”) API (ideal for an Activity Manager style application!)

    • Trusted mode is enabled
    • Webcam access (e.g. barcode scanning from hand held devices)
    • Official Google Chrome Support
  • Date issues in Silverlight

    Seeing some strange date behaviours in SL UI components. My local culture is UK but we keep seeing US dates popping up “here and there”.

    Have tried setting the Language= “en-GB” in the upper most control, also setting the thread culture is not effecting across the app.

    Going to have to get help on this one…

  • How many chances…?

    How many chances do you give a new piece of software before moving away? That probably depends on the type of “chances” you are giving.

    If you are irritated by a new UI, then you can probably live with it? If the application crashes and you lose all your work, then you’ll be less forgiving.

    Why do I ask this? I just started using Expression Design – in an attempt to do the right thing, and use the tools that are provided as part of our MSDN and partnership packs.

    Firstly I couldn’t get the tool to do what I wanted with Gradients and fills. I can get over that, as I’m probably using the tool in the wrong way.

    But then it crashed. Doing something simple. And it didn’t save my work. And I lost it all.

    Expression Design – you had your chance and you blew it. Come see me again in a few years and we’ll talk. In the meantime, I’m going back to see my old friend – Fireworks.

  • Debugging SQL2005 Stored Procedures from VS2008

    Yesterday I was having great success debugging T-SQL SP’s from VS2008 to a local developer SQL server. This was easy to do:

    • Enable SQL debugging in all my VS2008 projects (all of them was probably overkill, but it works)
    • Turn-off the local windows firewall (again overkill, but it works)
    • Create a connection to a database
    • Right click the SP | Open
    • Set a breakpoint.
    • Launch the app in debug mode.

    All was good and this worked as expected without the need to create loads of PRINT statements and having all the power of the VS debugging tools.

    …Then VS crashed… And it all stopped working. Totally stopped. Totally confused. No manner of reboots, resets, alterations to config made any difference.

    After some considerable support from Microsoft the solution was to delete all the Program Debug Database (.pdb) files in the solutions and rebuild… and voila.

    So the moral is – if VS crashes whilst debugging – delete the PDB’s – they might, just might, be corrupt and causing you a  whole world of pain.

    Here endeth the lesson…

  • Restyling Transitions in the Silverlight Toolkit TransitioningContentControl

    (This post extends my example for using cross project merged dictionaries in Silverlight)

    I’m a developer, not a designer and as such using Expression Blend doesn’t feel natural and makes me feel dirty… However I had to bite the bullet to ease the restyling of the transition animation in the Toolkit TransitioningContentControl.

    NOTE: At time of writing this control is in the Experimental Quality Band – the way I have built this might not work in the future!!

    To edit the transition in blend I added a TCC to my page, right clicked and chose “Edit Template Edit a Copy… Define in Application

    You can then start editing the VisualStates. There is tons of information on how to do this, so I won’t repeat that here, but here are the basics:

    Select States tab, Choose a transition to edit (or add a new one) expand the objects and make changes to the states along the time line.

    After making changes to your template open it and examine the changes. Most stuff is pretty self explanatory. Once this is done I can close blend and copy the XAML in to Visual Studio – now I feel safe and clean!!

    So, I wanted to add a flip transition, that makes the page look like it is doing a 360 flip around a vertical axis. First thing to do is edit the content template to include project planes, as these are hooked from my new animation (lines 17-19 and 37-39 below). You won’t need to do this is you are changing basic animation properties (offset, opacity, scale etc):


    <ContentPresenter x:Name="PreviousContentPresentationSite"
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    Content="{x:Null}"
    ContentTemplate="{TemplateBinding ContentTemplate}">















    <ContentPresenter x:Name="CurrentContentPresentationSite"
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    Content="{x:Null}"
    ContentTemplate="{TemplateBinding ContentTemplate}">














    Then add my flip animation (lines 53-74 below):

    <Style x:Key="TransitioningContentControlStyle1"
    TargetType="layoutToolkit:TransitioningContentControl">
    <Setter Property="IsTabStop"
    Value="True" />
    <Setter Property="HorizontalContentAlignment"
    Value="Left" />
    <Setter Property="VerticalContentAlignment"
    Value="Top" />
    <Setter Property="Transition"
    Value="DefaultTransition" />



    <Border Background="{TemplateBinding Background}"
    BorderBrush="{TemplateBinding BorderBrush}"
    BorderThickness="{TemplateBinding BorderThickness}"
    CornerRadius="2">




    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="0" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="1" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="1" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="0" />





    <ObjectAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Visibility)">


    Collapsed







    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)">
    <EasingDoubleKeyFrame KeyTime="00:00:00"
    Value="0" />
    <EasingDoubleKeyFrame KeyTime="00:00:00.3000000"
    Value="90" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)">
    <EasingDoubleKeyFrame KeyTime="00:00:00"
    Value="-90" />
    <EasingDoubleKeyFrame KeyTime="00:00:00.3000000"
    Value="-90" />
    <EasingDoubleKeyFrame KeyTime="00:00:00.6000000"
    Value="0" />






    <ContentPresenter x:Name="PreviousContentPresentationSite"
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    Content="{x:Null}"
    ContentTemplate="{TemplateBinding ContentTemplate}">















    <ContentPresenter x:Name="CurrentContentPresentationSite"
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    Content="{x:Null}"
    ContentTemplate="{TemplateBinding ContentTemplate}">



















    NOTE: I have removed the DefaultTransition, UpTransition and DownTransition VisualStates from this code as I am not using them. Normal MUST remain. If you want these transition states back they are copied below for your convenience.

    Finally I copied this style to a separate file so it can be referenced as a MergedDictionary across a multi project solution (as described here).

    When doing this, remember to Add a reference to System.Windows.Controls.Toolkit and System.Windows.Controls.Layout.Toolkit from the resources project, and in the resource xaml file:

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:layoutToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit">

    DefaultTransition, UpTransition and DownTransition Visual States



    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="0" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="1" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="1" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="0" />





    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="0" />
    <EasingDoubleKeyFrame KeyTime="00:00:00.7330000"
    Value="0" />
    <EasingDoubleKeyFrame KeyTime="00:00:01.1000000"
    Value="1" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="1" />
    <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
    Value="1" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.9000000"
    Value="0" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
    <EasingDoubleKeyFrame KeyTime="00:00:00"
    Value="0">




    <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
    Value="0">




    <EasingDoubleKeyFrame KeyTime="00:00:00.9000000"
    Value="0">





    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
    <EasingDoubleKeyFrame KeyTime="00:00:00.7330000"
    Value="0" />
    <EasingDoubleKeyFrame KeyTime="00:00:01.1000000"
    Value="1" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
    <EasingDoubleKeyFrame KeyTime="00:00:00.7330000"
    Value="0" />
    <EasingDoubleKeyFrame KeyTime="00:00:01.1000000"
    Value="1" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
    <EasingDoubleKeyFrame KeyTime="00:00:00"
    Value="1">




    <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
    Value="0.75">




    <EasingDoubleKeyFrame KeyTime="00:00:00.9000000"
    Value="1">





    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
    <EasingDoubleKeyFrame KeyTime="00:00:00"
    Value="1">




    <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
    Value="0.75">




    <EasingDoubleKeyFrame KeyTime="00:00:00.9000000"
    Value="1">





    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
    <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
    Value="0">




    <EasingDoubleKeyFrame KeyTime="00:00:00.9000000"
    Value="-500">





    <PointAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)">
    <EasingPointKeyFrame KeyTime="00:00:00"
    Value="0.5,0.5" />
    <EasingPointKeyFrame KeyTime="00:00:00.5000000"
    Value="0.5,0.5" />

    <PointAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)">
    <EasingPointKeyFrame KeyTime="00:00:00"
    Value="0.5,0.5" />
    <EasingPointKeyFrame KeyTime="00:00:00.7330000"
    Value="0.5,0.5" />
    <EasingPointKeyFrame KeyTime="00:00:01.1000000"
    Value="0.5,0.5" />





    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="0" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="1" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="CurrentContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="-40" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="0" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.Opacity)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="1" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="0" />

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
    Storyboard.TargetName="PreviousContentPresentationSite"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
    <SplineDoubleKeyFrame KeyTime="00:00:00"
    Value="0" />
    <SplineDoubleKeyFrame KeyTime="00:00:00.300"
    Value="40" />


    Note: UpTransition has been altered to do a funky “drop-back-swing-left-and-fade-in” animation

    Example

    The obligatory example is here…

  • Cross Project MergedDictionaries in Silverlight

    Todd Miranda has posted a video on the use of merged dictionaries on the Learning portal of Silverlight.net (find it here). This video explains the concepts of MergedDictionaries in a very long winded way. IMHO people investigating MergedDictionaries will already know how to layout a grid, and play some simple controls, so the first 8m of the tutorial is pretty boring.

    The description of the use of MergedDictionaries is pretty good, along with a couple of common pitfalls, but this does not explain one core feature well enough: Cross Project

    Anyone writing a Silverlight LOB application is almost certainly going to have multiple projects, and the use of MergedDictionaries corss project is going to be a huge advantage.

    Luckily this isn’t much more difficult than Todd has shown. Imagine the following scenario; we have a bunch of silverlight pages that need to share styles, but are spread across a few different projects. We want to keep the styles (as resources) in one location and reference these.

    So simply create a Resources project, and add your resources files as described by Todd (Add | New Item… | XML file etc) (you can also add these to any sensible location in your existing solution – say a UserControls project)

    Then when referencing the MergedDictionary from the UserControl where the style will be applied, use the Assembly name of the resources location, rather than the assembly name of the UserControl location.

    So the Source value will be formatted as Source=”/[AssemblyName];component/[Path and filename]

    Don’t forget to add a reference to the Resources project from the Target Project.

    Further details and and example of this in action with a re-styled TransitioningContentControl can be found here: http://thoughtjelly.blogspot.com/2009/10/restyling-transitions-in-silverlight.html.

  • Walking the XAML VisualTree to find a parent of type

    To find a parent item of type T, you can use the following helper class:

    public static class DependencyObjectHelper
    {
    public static DependencyObject FindParent(this DependencyObject obj, Predicate where) {
    var parent = VisualTreeHelper.GetParent(obj);
    
    if (parent == null || where(parent)) {
    return parent;
    } else {
    return parent.FindParent(where);
    }
    }
    
    public static T FindParentOfType(this DependencyObject obj) where T : DependencyObject {
    return (T)FindParent(obj, x => x is T);
    }
    }

    This can then be utilised as follows:

    Grid item = ((DependencyObject)childObject).FindParentOfType();

    This was particularly useful when wanting to locate an invalid control from a ValidationSummary in silverlight, that was nested in an accordian panel:

    BIG shout out goes to Jedi Master Twist for the lead on this 🙂

  • Silverlight PRISM Commands – TextChanged

    Out of the box the Patterns and Practices PRISM code only supports the click event handler. Writing additional handlers really is very easy. Firstly there are two great starter blogs which I’m not going to recreate:

    How Commanding Works in Prism and MVVM by Erik Mork and A code snippet to quickly write Prism commands by Andrea Boschin

    Following these patterns it was a sinch to create the code that can be used as a TextChanged command handler:

      1:     public class TextChangedCommandBehavior : CommandBehaviorBase
      2:     {
      3:         public TextChangedCommandBehavior(TextBox targetObject)
      4:             : base(targetObject)
      5:         {
      6:             targetObject.TextChanged += (s, e) => base.ExecuteCommand();
      7:         }
      8:     }
      9: 
     10:     public static class TextChanged
     11:     {
     12:         public static readonly DependencyProperty TextChangedBehaviorProperty =
     13:             DependencyProperty.RegisterAttached(
     14:                 "TextChangedBehavior", typeof(TextChangedCommandBehavior),
     15:                 typeof(TextChangedCommandBehavior), null);
     16: 
     17:         #region CommandProperty
     18: 
     19:         public static readonly DependencyProperty CommandProperty =
     20:             DependencyProperty.RegisterAttached(
     21:                 "Command", typeof(ICommand), typeof(TextChanged),
     22:                 new PropertyMetadata(CommandProperty_Changed));
     23: 
     24:         public static ICommand GetCommand(DependencyObject obj)
     25:         {
     26:             return (ICommand)obj.GetValue(CommandProperty);
     27:         }
     28: 
     29:         public static void SetCommand(DependencyObject obj, ICommand value)
     30:         {
     31:             obj.SetValue(CommandProperty, value);
     32:         }
     33: 
     34:         private static void CommandProperty_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
     35:         {
     36:             TextBox targetObject = dependencyObject as TextBox;
     37: 
     38:             if (targetObject != null)
     39:                 GetOrCreateBehavior(targetObject).Command = e.NewValue as ICommand;
     40:         }
     41: 
     42:         #endregion
     43: 
     44:         #region CommandParameterProperty
     45: 
     46:         public static readonly DependencyProperty CommandParameterProperty =
     47:             DependencyProperty.RegisterAttached(
     48:                 "CommandParameter", typeof(object),
     49:                 typeof(TextChanged), new PropertyMetadata(CommandParameterProperty_Changed));
     50: 
     51:         public static ICommand GetCommandParameter(DependencyObject obj)
     52:         {
     53:             return (ICommand)obj.GetValue(CommandParameterProperty);
     54:         }
     55: 
     56:         public static void SetCommandParameter(DependencyObject obj, ICommand value)
     57:         {
     58:             obj.SetValue(CommandParameterProperty, value);
     59:         }
     60: 
     61:         private static void CommandParameterProperty_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
     62:         {
     63:             TextBox targetObject = dependencyObject as TextBox;
     64: 
     65:             if (targetObject != null)
     66:                 GetOrCreateBehavior(targetObject).CommandParameter = e.NewValue;
     67:         }
     68: 
     69:         #endregion
     70: 
     71:         private static TextChangedCommandBehavior GetOrCreateBehavior(TextBox targetObject)
     72:         {
     73:             TextChangedCommandBehavior behavior = targetObject.GetValue(TextChangedBehaviorProperty) as TextChangedCommandBehavior;
     74: 
     75:             if (behavior == null)
     76:             {
     77:                 behavior = new TextChangedCommandBehavior(targetObject);
     78:                 targetObject.SetValue(TextChangedBehaviorProperty, behavior);
     79:             }
     80: 
     81:             return behavior;
     82:         }
     83:     }

  • Determining Users in an AD Group

    From a command line (on the AD server) you can use this to get the members of a group:

      1: dsquery group -name "Group Account Name" | dsget group -members

    Additionally a command line exe to get the groups for the logged in member too, something like this:

      1: My.User.InitializeWithWindowsUser()
      2: 
      3: Dim identity As System.Security.Principal.WindowsIdentity = TryCast(My.User.CurrentPrincipal.Identity, System.Security.Principal.WindowsIdentity)
      4: 
      5: Debug.WriteLine(identity.Name)
      6: 
      7: For Each group As System.Security.Principal.SecurityIdentifier In identity.Groups() 
      8:    Debug.WriteLine(group.Translate(GetType(System.Security.Principal.NTAccount)), "group") 
      9: Next
     10: