Ramblings of a .NET Developer

4 May 2014

Sunday, May 04, 2014 | by Paul | Categories: , , | No comments
I've been a computer programmer for over 20 years now, enduring framework after framework, changes in technology, changes in how we should develop, being told this is better, or that is better. Sometimes I really get fed up with it.

For the experienced programmer, we just want to develop a system/application as we know how it should be done and not force new tech on us just for the sake of it - especially whilst we are developing that project. I for one, want to produce an end result on time, and something that I'm pleased and confident with.

The state of development projects never seem to get any better either. How many failed I.T. projects have been highlighted over the years, costing governments millions and taking years to complete or getting scrapped?

Surely, with the rise in various methodologies, one of them must work? Or maybe we are doomed because the fundamentals or I.T. development is just wrong?

Traditional Factories

Looking back at my days as a Mechanical Engineer (some 25 years ago) things we different, and working for a manufacturing company that developed railway components, the correct processes and procedures were in place to produce components that were developed and delivered on time and were properly quality controlled.

In a factory, a product or component is not developed on the fly. It has gone through a process of R & D, quality controlled, reviewed, re-visited and then after that is then adopted and is viable for inclusion in larger projects or as a product that can be sold as is.

Where I worked, each part of the process was timed, with Route Cards showing the process of taking a raw piece of material through each defined step to finally end up with a finished product. Each part of the process required a Job Card, allowing the individual worker to indicate the time taken for their bit of the work. All this was fed back into the EFACS system (does this exist any more?) and used to more accurately estimate production times etc.

In a factory, if a new product is being designed, then the R & D to do that is a project in itself and can be time boxed if necessary.

The I.T. Factory

In I.T., we don't have the same rules. We must developed a system, include new technologies/techniques/frameworks as we go (often just for the sake of it), take on more complexity and still give accurate estimates on how we are tracking and if we are on time. Naturally, we can only guess, and quite often we are miles away from the true figures.

We are expected to do the R & D while we develop, be agile, handle change, work with Project Managers that add their spin on how things should work and worse, tell us one thing and tell the project sponsors another...

It's no wonder that projects fail. And if it doesn't fail, how much of that software is re-written for version 2? And how much has to be re-written because the business process has changed?

The funny thing is, the end users of the software don't care if it uses this framework or that framework or technology. They just want it to work, improve their job role and make things easier for them and/or perform their role more efficiently.
Instead, they end up with software that is already creaking at the seems, is slow, buggy, does not make their lives any easier and sometimes makes it worse.

So, how can this be fixed?

1) Start dedicating resources to R & D projects. This will allow us to focus on new technology in a controlled manner, which can be time boxed and give the development team a chance to understand how 3rd party frameworks should be used.

2) Don't to R & D in a project.

3) Use the skills of the team. If they need to learn something for the next project, then it must be recognized that time needs to be allocated for that learning.

4) Learn from environments that work and have been working efficiently for years.


9 April 2014

Wednesday, April 09, 2014 | by Paul | Categories: , , | No comments
So, I've wanted to do some development in the mobile space for the last few years now, and always managed to put it off, change my mind over technology/platform etc, etc.

Well, I decided to go to a meetup a few weeks back. This was quite good as I was suddenly discussing things with other people actually doing something in the mobile space. This was from people with ideas to developers to people paying other developers to do the work.

The other part of the meeting was that everyone had to set a goal for the next meeting.

So, I've committed to releasing an app!

I've even got an idea - which is a minor miracle as I can never usually think of anything decent.

As I'm an Android owner, that's my target platform, and I'm going to a native app to get the experience of the process.

It's funny how the recommendations went on how to do it at the meeting.

All the devs were saying stuff like, go native or use a cross-platform framework, whilst all the non-techies were saying to contract the work out. I can see the point of contracting it out from a business point of view....but, I'm a dev and want to get my hands dirty and also get an appreciation of what's involved.
If it looks like it could work, then I might contract some work out later.

11 March 2014

Tuesday, March 11, 2014 | by Paul | Categories: , , , | No comments
I uploaded my WPF based client framework (Clarity) to codeplex over the weekend.
If anyone is interested, here is the link.

Now all I need to do is add more samples, make it portable and more tests and add more features as needed.

I really need more hours in the day...

It would be good to get some feedback and see what can be improved.

17 December 2013

Tuesday, December 17, 2013 | by Paul | Categories: , , , | No comments
I recently had an interesting requirement. Basically, users were allowed access to any part of the application, but only users that had the correct permissions were allowed to change data. Further to this, the level of control required was down to the field level.

So, I couldn't just disable the window and be on my merry way. Also, as it was field level permissions I had to ignore validation for the field when it was read-only.

After having a think about this I decided to write a custom UserControl that would accept any content. This would have an IsEditable property and additional data source properties to use when the control was not editable.

So, some XAML...


    
        
    
    
    
        
        
        
                
    


As you can, there is nothing too special with the control. Basically it's just a layout grid that contains a ContentControl and a readonly TextBox. The visibility of these are toggled based on the IsEditable property and I used a TextBox to allow the user to still be able to copy data. Now the code behind...
    /// 
    /// Interaction logic for EditableControl.xaml
    /// 
    public partial class EditableControl : UserControl
    {
        public EditableControl()
        {
            InitializeComponent();
            DataContextChanged += OnDataContextChanged;
            GotFocus += EditableControl_GotFocus;
        }

        void EditableControl_GotFocus(object sender, RoutedEventArgs e)
        {
            try
            {
                var isShiftDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);

                if (!isShiftDown)
                {
                    if (Child != null && content.Visibility == System.Windows.Visibility.Visible && !Child.IsFocused && !Child.IsKeyboardFocusWithin)
                    {
                        Child.Focus();
                    }
                    else if (readonlyTextbox.Visibility == System.Windows.Visibility.Visible)
                    {
                        readonlyTextbox.Focus();
                    }
                }
            }
            catch
            {
                //exception could be thrown in some scenarios where child control shows a popup or context menu
            }
        }

        private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            UpdateSecurity(PropertyName);
        }

        public FrameworkElement Child
        {
            get { return (FrameworkElement)GetValue(ChildProperty); }
            set { SetValue(ChildProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Child.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ChildProperty =
            DependencyProperty.Register("Child", typeof(FrameworkElement), typeof(EditableControl), new UIPropertyMetadata(null));

        public string PropertyName
        {
            get { return (string)GetValue(PropertyNameProperty); }
            set { SetValue(PropertyNameProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PropertyName.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PropertyNameProperty =
            DependencyProperty.Register("PropertyName", typeof(string), typeof(EditableControl), new FrameworkPropertyMetadata(OnPropertyNameChanged));

        private static void OnPropertyNameChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var control = sender as EditableControl;
            var context = control.DataContext as ValidatingViewModel;
            if (e.NewValue == null)
                control.UpdateSecurity(string.Empty);
            else
                control.UpdateSecurity(e.NewValue.ToString());
        }

        private void UpdateSecurity(string name)
        {
            var context = DataContext as ViewModel;
            if (context == null)
            {
                Logger.Warn("DataContext not set");
            }
            else if (!string.IsNullOrEmpty(name))
            {
                IsEditable = context.CanEdit(name);
            }
        }

        public bool IsEditable
        {
            get { return (bool)GetValue(IsEditableProperty); }
            set { SetValue(IsEditableProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsEditable.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsEditableProperty =
            DependencyProperty.Register("IsEditable", typeof(bool), typeof(EditableControl), new UIPropertyMetadata(true, OnIsEditableChanged));

        private static void OnIsEditableChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var control = (RossEditableControl)sender;
            control.UpdateSecurity(control.PropertyName);
        }

        public string ReadonlySource
        {
            get { return (string)GetValue(ReadonlySourceProperty); }
            set { SetValue(ReadonlySourceProperty, value); }
        }

     public TextWrapping TextWrapping
     {
   get { return (TextWrapping)GetValue(TextWrappingProperty); }
   set { SetValue(TextWrappingProperty, value); }
     }

        // Using a DependencyProperty as the backing store for ReadonlySource.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ReadonlySourceProperty =
            DependencyProperty.Register("ReadonlySource", typeof(string), typeof(EditableControl), new UIPropertyMetadata(null));

  public static readonly DependencyProperty TextWrappingProperty =
     DependencyProperty.Register("TextWrapping", typeof(TextWrapping), typeof(EditableControl), new UIPropertyMetadata(null));
    }
Here I've created DependencyProperties for Child, PropertyName, IsEditable, ReadonlySource and TextWrapping.
These allow enough configuration to allow us to customize how the readonly field is will be displayed. Also, I've not shown it here, but I have a style for the TextBox that will render the text in a gray italic font and gray border when it is read-only.
For the styling of the application, this was a good fit aesthetically.
I have a base ViewModel that exposes a virtual CanEdit function. This is used in the UpdateSecurity method to determine if the control should be readonly or not. This method is called when the PropertyName property changes.
For many scenarios this will work fine (i.e. the IsEditable set when the PropertyName gets set), but in some cases you will need it to be more dynamic. So, the IsEditable property could be bound to some property on your ViewModel.
Below is an example of how it would be used.

    
        
    


15 December 2013

Sunday, December 15, 2013 | by Paul | Categories: , , | No comments
I've worked with WPF since it was in beta, and although it's super flexible with what you can do, sometimes I just want to cut down on the repetitive xaml I have to write.

How many times have you bound the visibility of a control to some viewmodel property or even to the boolean property of another element?
Well, I've done this literally hundreds of times and realized the other day that I can make it easy with a simple Attached Property.
So, below is a drop-in helper class to make your binding easier without having to use a converter. Oh, use VisibilityHelper.Inverse="True" if you want the opposite result.

public class VisibilityHelper
    {

        public static bool GetIsVisible(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsVisibleProperty);
        }

        public static void SetIsVisible(DependencyObject obj, bool value)
        {
            obj.SetValue(IsVisibleProperty, value);
        }

        // Using a DependencyProperty as the backing store for IsVisible.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsVisibleProperty =
            DependencyProperty.RegisterAttached("IsVisible", typeof(bool), typeof(VisibilityHelper), new UIPropertyMetadata(true, OnIsVisibleChanged));

        public static bool GetInverse(DependencyObject obj)
        {
            return (bool)obj.GetValue(InverseProperty);
        }

        public static void SetInverse(DependencyObject obj, bool value)
        {
            obj.SetValue(InverseProperty, value);
        }

        // Using a DependencyProperty as the backing store for Inverse.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty InverseProperty =
            DependencyProperty.RegisterAttached("Inverse", typeof(bool), typeof(VisibilityHelper), new UIPropertyMetadata(false, OnIsVisibleChanged));

        private static void OnIsVisibleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            UpdateVisibility(sender as UIElement);
        }

        private static void UpdateVisibility(UIElement fe)
        {
            if (fe != null)
            {
                bool value = (bool)fe.GetValue(VisibilityHelper.IsVisibleProperty);
                if ((bool)fe.GetValue(VisibilityHelper.InverseProperty))
                {
                    fe.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
                }
                else
                {
                    fe.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
                }
            }

        }
    }

Now, add this to your favorite UI library and away you go!
As an example, the button below is hidden if it is disabled.

14 December 2013

Saturday, December 14, 2013 | by Paul | Categories: , , | No comments
So the projects I work on are usually quite large, often hitting over 1m lines of code. And, sometimes it is nice to add some buttons into the application which are there just for development purposes.

As one of my developers was hacking a way of doing this by leaving this out of his commits, it seemed like an opportunity to add something to reduce this management effort and eliminate errors when committing and pushing code in mecurial.

So, below is a simple attached property that will only render the control when the app is a DEBUG build.

    public static class Runtime
    {
        public static bool GetDebugOnly(DependencyObject obj)
        {
            return (bool)obj.GetValue(DebugOnlyProperty);
        }

        public static void SetDebugOnly(DependencyObject obj, bool value)
        {
            obj.SetValue(DebugOnlyProperty, value);
        }

        // Using a DependencyProperty as the backing store for DebugOnly.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DebugOnlyProperty =
            DependencyProperty.RegisterAttached("DebugOnly", typeof(bool), typeof(Runtime), new UIPropertyMetadata(false, OnDebugOnlyChanged));

        private static void OnDebugOnlyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var ui = sender as UIElement;
            if (ui != null)
            {
                if ((bool)e.NewValue)
                {
#if !DEBUG
                ui.Visibility = Visibility.Collapsed;
                ui.IsEnabled = false;
#endif
                }
            }
        }
    }

Now just just use the attached property where you need to.


Saturday, December 14, 2013 | by Paul | Categories: , | No comments
I had a requirement recently to provide the usual validation framework, but instead of showing error detail against every invalid control, the client wanted to show a small error bar when the control was not focused. When it receives focus, they then wanted the user to see the full validation error message.

The default validation does not cater for this scenario, but with the help of an attached property I was able to come up with something that works and is reusable.

First, the new class

    public class ValidationEx
    {
        public static bool GetAttach(DependencyObject obj)
        {
            return (bool)obj.GetValue(AttachProperty);
        }

        public static void SetAttach(DependencyObject obj, bool value)
        {
            obj.SetValue(AttachProperty, value);
        }

        // Using a DependencyProperty as the backing store for Attach.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AttachProperty =
            DependencyProperty.RegisterAttached("Attach", typeof(bool), typeof(ValidationEx), new FrameworkPropertyMetadata(false, AttachChanged));

        private static void AttachChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is FrameworkElement)
            {
                var fe = sender as FrameworkElement;

                if (((bool)e.NewValue))
                {
                    fe.SetValue(Validation.ErrorTemplateProperty, Application.Current.Resources["LimitedValidationErrorTemplate"]);
                    fe.IsKeyboardFocusWithinChanged += KeyboardFocusWithinChanged;
                    fe.SizeChanged += ElementSizeChanged;
                    fe.LayoutUpdated += ElementLayoutUpdated;
                }
                else
                {
                    fe.SetValue(Validation.ErrorTemplateProperty, null);
                    fe.IsKeyboardFocusWithinChanged -= KeyboardFocusWithinChanged;
                    fe.SizeChanged -= ElementSizeChanged;
                    fe.LayoutUpdated -= ElementLayoutUpdated;
                }
            }
        }

        static void ElementLayoutUpdated(object sender, EventArgs e)
        {
            var fe = sender as FrameworkElement;

            if (fe != null && (bool)fe.GetValue(ValidationEx.AttachProperty))
            {
                UpdatePopupPosition(fe);
            }
        }

        public static string GetAttachWithTemplate(DependencyObject obj)
        {
            return (string)obj.GetValue(AttachWithTemplateProperty);
        }

        public static void SetAttachWithTemplate(DependencyObject obj, string value)
        {
            obj.SetValue(AttachWithTemplateProperty, value);
        }

        // Using a DependencyProperty as the backing store for AttachWithTemplate.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AttachWithTemplateProperty =
            DependencyProperty.RegisterAttached("AttachWithTemplate", typeof(string), typeof(ValidationEx), new FrameworkPropertyMetadata("", AttachWithTemplatechanged));

        private static void AttachWithTemplatechanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is FrameworkElement)
            {
                var fe = sender as FrameworkElement;

                var template = Application.Current.Resources[e.NewValue.ToString()];
                fe.SetValue(Validation.ErrorTemplateProperty, template);

                fe.IsKeyboardFocusWithinChanged -= KeyboardFocusWithinChanged;
                fe.SizeChanged -= ElementSizeChanged;
                fe.LayoutUpdated -= ElementLayoutUpdated;

                fe.IsKeyboardFocusWithinChanged += KeyboardFocusWithinChanged;
                fe.SizeChanged += ElementSizeChanged;
                fe.LayoutUpdated += ElementLayoutUpdated;
            }
        }

        static void ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            var fe = Keyboard.FocusedElement as FrameworkElement;

            if (fe != null && (bool)fe.GetValue(ValidationEx.AttachProperty))
            {
                UpdatePopupPosition(fe);
            }
        }

        private static ScrollViewer GetScrollViewer(FrameworkElement fe)
        {
            var parent = VisualTreeHelper.GetParent(fe);
            while (parent != null && !(parent is Window))
            {
                if (parent is ScrollViewer)
                    return parent as ScrollViewer;

                if (parent is Border)
                {
                    var child = ((Border)parent).Child;
                    if (child is ScrollViewer)
                        return child as ScrollViewer;
                }

                parent = VisualTreeHelper.GetParent(parent);
            }

            return null;
        }

        static void ElementSizeChanged(object sender, SizeChangedEventArgs e)
        {
            FrameworkElement fe = sender as FrameworkElement;
            if (fe != null && fe.IsKeyboardFocusWithin)
            {
                UpdatePopupPosition(fe);
            }
        }

        private static void UpdatePopupPosition(FrameworkElement fe)
        {
            KeyboardFocusWithinChanged(fe, new DependencyPropertyChangedEventArgs(FrameworkElement.IsKeyboardFocusWithinProperty, true, false));
            KeyboardFocusWithinChanged(fe, new DependencyPropertyChangedEventArgs(FrameworkElement.IsKeyboardFocusWithinProperty, false, true));
        }

        private static void KeyboardFocusWithinChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement fe = sender as FrameworkElement;
            if (fe != null)
            {
                var scrollViewer = GetScrollViewer(fe);

                if (((bool)e.NewValue))
                {
                    var value = fe.GetValue(Validation.ErrorTemplateProperty);
                    var resourceKey = fe.GetValue(ValidationEx.AttachWithTemplateProperty).ToString();
                    if (string.IsNullOrWhiteSpace(resourceKey))
                        resourceKey = "ValidationErrorTemplate";

                    var template = Application.Current.Resources[resourceKey];
                    fe.SetValue(Validation.ErrorTemplateProperty, template);

                    if (scrollViewer != null)
                    {
                        scrollViewer.ScrollChanged -= ScrollChanged;
                        scrollViewer.ScrollChanged += ScrollChanged;
                    }
                }
                else
                {
                    fe.SetValue(Validation.ErrorTemplateProperty, Application.Current.Resources["LimitedValidationErrorTemplate"]);

                    if (scrollViewer != null)
                    {
                        scrollViewer.ScrollChanged -= ScrollChanged;
                    }
                }
            }
        }
    }

This makes available two attached properties.

Attach – which triggers the code to use custom templates
AttachWithTemplate – which allows you to specify a custom validation template key.

So, the above code specifies the validation template to use when the control does not have focus. When it or anyone of its children gets focus, the validation template is changed to reflect the different UI requirement.

The Resource Dictionary

Of course, nothing will look any different if we don’t code up the templates. So, below are some basic templates to use.

    

    
    
        
            
            
        
    

    
        
            
            
                
                    
                        
                            
                                
                            
                        
                    
                
            
        
     


To use the validation extension I have a different resource dictionary where I've specified various settings. So, for a Textbox I've set a global style to hook up the validation extension.


So to visualize this, here are a few screenshots to help.

Here, the last name field is not focused, so the last name validation shows a bar at the side.

Hovering over bar shows the details of the error

Once focused, the bar is replaced with a custom validation message which will display the current error.