A Better Sandwich!

When considering topics for blog posts more often then not I filter out ideas based on their technical merit. I try my best to offer solutions to problems that I face everyday as a software developer in an attempt to repay the many others who’s blog postings have helped me. This post however does not fall into that category. So feel free to ignore it.

In a recent dinner with my wife and her parents. I retold a story that my wife has heard many times before. This particular time however, I managed to make some correlations to software development that had not previously occurred to me. So before I go any further let me retell the story…. Again…

In the beginning…. Wait wrong story.

When I was in high school I was dating a girl who in all accounts was much smarter then I was. However since I was a rocking guitar player and all around rebel she found my charms irresistible.

*The statement above is a complete embellishment except for the fact that she was indeed much smarter then I am*

One night while the two of us sat in my parents kitchen, I decided to take full advantage of the refrigerator filled with all of the parental subsidized food you could imagine, and make us some sandwiches. I grabbed some lunch meat, lettuce, tomatoes, mustard and all the other standard sandwich fixings available. I reached for the bread box to grab the bread, and the sandwich making commenced.

First up my sandwich (because I am selfish). I slapped down two slices of bread and started to add the fixings. On one slice went the meat, and on the other slice all of the fixings, salad, mustard, onions etc. Once all of the fixings were in place I grabbed each fully loaded slice and tried my best to marry the two without dumping the fixings all over. I managed to get the sandwich together like I had with all sandwiches before. After all I was not at all new to the art of sandwich making with free ingredients. I took a look over at my girlfriend expecting a look of awe as she basked in my artistry. Instead I got a look of utter confusion mixed in with a little disgust. She said, “Really? That is how you make a sandwich?” This was the beginning of the end for use as a couple. She then continued to tell my how much easier it would have been if I put all of the fixings on one slice of bread, and simply placed the second slice on top.

Her words flipped my world upside down. I could not believe what she was saying! It was a perfect solution. A perfect solution to a problem I never thought existed! I then proceeded to make her the most efficiently crafted sandwich I had ever made. It was a work of art that would bring the likes of Picasso to tears.

And that is the story. My story of a better sandwich! So why blog about it?

Well at that moment when my girlfriend pointed out the problems in my process I realized that had she not done so, I would have continued making sandwiches that way. Who knows how long or how many sandwiches would have fallen victim to my intellectual laziness. The reason this horrible process would have continued is because despite its short comings it did in fact work. At the end of this process I could always partake in some tasty sandwich goodness.

The point here is simple. You can go years and years doing what you do the way you always have. The results after all in this case were just fine. The same is true in software development. We can follow all of the patterns we have always followed. We use all of the best practices we have spent so long learning and mastering over and over again. And as long as we do that and nothing major changes we can turn our brains off and churn out application after application, object after object, and pattern after pattern. And all along never even considering that there may be a much better way to make a sandwich. And if we are not looking for ways to make our sandwiches better, what the hell is the point!

Enjoy!

Binding WPF Style

This may be old news but it is exciting to me so I want to document it. Often times when working with the MVVM/Presentation Model Pattern you want to apply a style based on the state of your Model/Business Object. For example if a Business Object ‘IsNew’ you may want to apply a editable style to a TextBox control so the user can supply some data. Yet when the same Business Object ‘IsOld’ you may want disable a field preventing any data entry. My first thought was to use a converter to determine the style in a binding statement similar to this.

<TextBox Style={Binding Path=ViewModel.Customer, Converter={StaticResource StyleConverter}}/>

When data binding does its thing the Convert method will be passed the Customer Business Object. We can then inspect the Business Object to determine what style to apply to the TextBox. The rub however comes when we try to locate the style we want to apply. See code below.

        /// <summary>
        /// Converts a value.
        /// </summary>
        /// <param name="value">The value produced by the binding source.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var customer = value as Customer;
            if(customer != null && customer.IsNew)
            {
                //Locate and return the EditableTextboxStyle
                //Wait!!!! How?!!?
                return null;
            }
            return null;
        }

The crux of the problem is that most often styles exist as resources of your UserControl/Window/Page. In order to resolve these resources the converter will need a reference to the FrameworkElement that contains said resources. So how about this?.

<TextBox Style={Binding Path=ViewModel.Customer, Converter={StaticResource StyleConverter}}, ConverterParameter={Binding Path=DataContext}/>

And the converter….

           /// <summary>
        /// Converts a value.
        /// </summary>
        /// <param name="value">The value produced by the binding source.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var customer = (Customer)value;
            var viewModel = (ViewModel)parameter;
            var view = viewModel.View;
            var fe = (FrameworkElement)view;

            if (customer != null && customer.IsNew)
            {
                return fe.TryFindResource("EditableTextboxStyle");
            }

            return fe.TryFindResource("NonEditableTextboxStyle");
        }

Though this seems like it may work(not really) there is one major issue that we run into. The ConverterParameter property in the binding statement is a CLR property that is it is not a DependencyProperty and because of this fact it cannot be data bound!

So just to restate the problem because most of the time I forget what problem I am actually trying to solve. I want a specific style to be applied to a TextBox based on the state of my Customer Business Object. For a converter to do this it needs a reference to the both the Business Object(to interrogate its state) as well as the View(To locate resources i.e. styles). So how can we pass two data bound objects to a converter? Well you cant! Not without some craziness.

Thankfully we have the Multibinding

I am not going to explain what you can read for yourself in the above article. I will however give you the code that did what I wanted to do 🙂 I am Felling a bit lazy tonight!

 <TextBox>
        <TextBox.Style>
            <MultiBinding Converter="{StaticResource StyleConverter}">
                <Binding Path="Customer"/>
                <Binding Path="DataContext"/>
            </MultiBinding>
        </TextBox.Style>
    </TextBox>

And the converter… When we multibinding we also have to use a multiconverter. So basically your converter has to implement IMultiConverter instead of IValueConverter. The only difference is that the first parameter of the Convert method is an array of objects. And in my case the first element in the array is a Customer object and the second a ViewModel! See below.

           /// <summary>
        /// Converts a value.
        /// </summary>
        /// <param name="value">The value produced by the binding source.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        public object Convert(object [] value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var customer = (Customer)value;
            var viewModel = (ViewModel)parameter;
            var view = viewModel.View;
            var fe = (FrameworkElement)view;

            if (customer != null && customer.IsNew)
            {
                return fe.TryFindResource("EditableTextboxStyle");
            }

            return fe.TryFindResource("NonEditableTextboxStyle");
        }

Like I said in the beginning this is far from groundbreaking but I thought it was worth a short post!

Tagged
Advertisements