Rediscovering the Obvious

…stumbling in the footsteps of greatness

Archive for July, 2007

Update – Thanks MDizzy!

without comments

Ask and I shall receive! A few days ago I mentioned that I’d love to get in touch with people that use WPF daily like I do, and then mdizzy starts commenting on my blog!

He posts over at his blog, Brownie Points, and based on the images does quite a bit more graphics work than I ever will.

 

Written by erwilleke

July 27th, 2007 at 11:33 am

Posted in Uncategorized

Binding to local helper objects

without comments

“Hack” or “Good Thing” — What do you all think?

I wanted to factor out some minor calculations from one of my screen, things like updating a total based on the sum of some other balances. To support this, I created an object named BatchCalculator and added some get/set properties and a couple of get-only calculated properties. I wired up INotifyPropertyChanged, and then added a private property to my page. In OnInitialize I set up the initial values, and in the command handler for the page’s “save” command, I consume the values in building the calls to the other layers of the application. So far, so good… fairly clean design, everything’s happy, right?

Then I tried to bind to that object. UGH! It’s not a DependencyObject or connected as a DependencyProperty… nor does it feel to me like it should be, so I don’t want to set up the Binding object with RelativeSource or ElementName. I have an instance already, so adding a page resource as all the examples point out doesn’t help… or does it?

My only working approach was to build up the binding in Code, like this:

            Binding b = new Binding();
            b.Source = BatchCalculator;
            b.Path = new PropertyPath(“StartingBalance”);
            b.Mode = BindingMode.TwoWay;
            b.UpdateSourceTrigger = UpdateSourceTrigger.Default;
            _startingAmountTextBox.SetBinding(TextBox.TextProperty, b);

This, however is UGLY, and should be a single XAML line.

The Solution

 Based on http://msdn2.microsoft.com/en-us/library/ms750950.aspx, I realized that I could add a resource to the page’s collection in code behind, and then have it be available for a {StaticResource} or {DynamicResource} markup extension to target. Since StaticResource “strongly suggests” (AKA requires in most cases) that the object is already declared and isn’t forward referenced, I added this to my constructor (names changed to protect… Me):

        public MyPageClass()
        {
            // Must be added BEFORE InitializeComponent
            Resources.Add(“batchCalculator”, BatchCalculator);
           
            InitializeComponent();
            RegisterCommands();
        }

Then, everything happily works with XAML that looks like this (get/set properties):

<TextBox Text=”{Binding Source={StaticResource batchCalculator}, Path=StartingBalance, Mode=TwoWay, UpdateSourceTrigger=Default}”/> 

or, for the calculated fields,

                    <TextBox IsReadOnly=”True” Text=”{Binding Source={StaticResource batchCalculator}, Path=AmountOver, Mode=OneWay, UpdateSourceTrigger=Default}” />

Conclusion

So, for those out there with more wisdom than I, is this a good way of accomplishing the binding I need? Or, did I miss something obvious? Do I misunderstand how one of the other two binding source specifiers works?

Written by erwilleke

July 27th, 2007 at 9:02 am

Posted in Uncategorized

Confused about DependencyProperties

without comments

I have a custom control that serves as a generic container for selecting a specific instance of one of a number of types of objects. This container handles the different types by swapping out other user controls as appropriate to what’s being selected, for instance I may have a FooPicker user control and a BarPicker user control. Each of these specific UserControl instances needs to have a value for CurrentSelection and the ability to announce CurrentSelectionChanged. Rather than create a common base class and push a bunch of code into it, I thought I could add a DependencyProperty and RoutedEvent on the container to take care of it for me.

This worked and it didn’t, and here’s why… first, my definitions:

In PickerPanel (the container), I coded:

        public static readonly RoutedEvent CurrentSelectionChangeEvent =
            EventManager.RegisterRoutedEvent(
                “CurrentSelectionChange”,
                RoutingStrategy.Bubble,
                typeof(RoutedEventHandler),
                typeof(PickerPanel));

and

         public static readonly DependencyProperty CurrentSelectionProperty =
            DependencyProperty.Register(
                “CurrentSelection”,
                typeof(object),
                typeof(PickerPanel),
                new PropertyMetadata(
                    null,
                    new PropertyChangedCallback(OnCurrentSelectionChanged) )
            );
        private static void OnCurrentSelectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UIElement picker = (UIElement) d;

            RoutedEventArgs args = new RoutedEventArgs(PickerPanel.CurrentSelectionChangeEvent, d);
            picker.RaiseEvent(args);
        }

Then, in the entity-specific UserControl, I handed the change event with:

         private void _fooLookupGrid_RecordActivated(object sender, RecordActivatedEventArgs e)
        {
            DataRecord dr = (DataRecord) e.Record;
            SetValue(PickerPanel.CurrentSelectionProperty, dr.DataItem);
        }

My assumption is that the call to SetValue should cause the firing of OnCurrentSelectionChanged with the user control being passed as the parameter “d”. OnCurrentSelectionChanged never called, ever. I have no idea why, either.

I worked around the issue by replacing the code in the derived class with the below code, but I don’t like it.

        private void _storeLookupGrid_RecordActivated(object sender, RecordActivatedEventArgs e)
        {
            DataRecord dr = (DataRecord) e.Record;
            SetValue(PickerPanel.CurrentSelectionProperty, dr.DataItem);
           
            RoutedEventArgs args = new RoutedEventArgs(PickerPanel.CurrentSelectionChangeEvent, this);
            RaiseEvent(args);
        }

 Having made the above workaround, I can now successfully receive the event from PickerPanel’s parent with:
        private void _pickerPanel_CurrentSelectionChanged(object sender, System.Windows.RoutedEventArgs e)
        {

        }

        In XAML:
        <someNamespace:PickerPanel
            x:Name=”_pickerPanel”
            someNamespace:PickerPanel.CurrentSelectionChanged=”_pickerPanel_CurrentSelectionChanged”/>
 

I’m not very happy with this, because I have clue why the event on the dependency property doesn’t fire.  Since I’m allowed to do so, since I’m writing this blog, I’m going to try something now, and then finish this post (I’m breaking all sorts of blogging rules here, right?)

I’m back!
My suspicion is confirmed, but I’m still very confused. In the handler above, I added a line of code as such:
        private void _pickerPanel_CurrentSelectionChanged(object sender, System.Windows.RoutedEventArgs e)
        {
            _pickerPanel.SetValue(Pickers.PickerPanel.CurrentSelectionProperty, “String’s an object, right?”);
        }

Sure enough, my handler was called, and it fired the event again and would have started up ye olde infinite event loop o’ doom if the changed event wasn’t smart enough to actually check that the object changed.

So, does anybody know why the PropertyChangedCallback provided as part of the PropertyMetadata for a DependencyProperty isn’t called when it’s set on another object? Am I required to treat it as an AttachedProperty at that point? I thought AttachedProperty was a XAML-specific helper based on http://msdn2.microsoft.com/en-us/library/ms749011.aspx.

 

 

Written by erwilleke

July 23rd, 2007 at 1:47 pm

Posted in Uncategorized

Baby Blend Rant

without comments

Well not really a rant, more of a lamentation that Blend, like every other [web] designer before it, doesn’t really understand the concept of dynamic layout.

WPF finally offers a VERY dynamic layout system, but blend, when you move things around still hard codes sizes and/or margins to make the dynamic containers (grids, dock panels, and stack panels especially) into very static entities… I’m getting tired of going through and telling it to “reset” the sizing information for everything.

But, at least it ALLOWS a way of resetting a value (i.e. choosing to not specify a property)

 

Written by erwilleke

July 23rd, 2007 at 9:23 am

Posted in Uncategorized

Anybody out there using WPF?

without comments

I realized I have a distinct lack of people on my IM list that I can throw out a quick question regarding WPF to… frustrating when every other tech on my used list has an expert within easy messaging distance…

Don’t suppose any other WPF experts (or, like me, wanna-be experts) are out there reading this and sharing the same pain ;)

If so, let me know!     

Written by erwilleke

July 19th, 2007 at 11:59 am

Posted in Uncategorized

Dependency Properties in WPF

without comments

I made my first one today… and it “just worked”.

I have a bunch of Page objects that need to push buttons into a shared space in the window’s frame. How do I do this? Easy! I just define a dependency property on the root window of type IList< RoutedUICommand> and set that on any pages that need buttons… On each page, I define a RoutedUICommand for anything that page wants to handle that’s unique to the page, add a new CommandBinding to the root window, and then call SetValue(MyWindow.SupportedCommands, list). Back in the window I handle Frame.LoadCompleted, cast e.Content to a DependencyObject, then see if GetValue( MyWindow.SupportedCommands ) is null… if not, I create a button for each command in there, using the Name and Text properties to look up the appropriate resource strings for display and tooltips.

What’s this gain me? First, my pages do not care IN THE SLIGHTEST what command scheme we’re using… right click, buttons on the screen, hot keys, mnemonics, accelerators, mouse gestures, pen motions… who cares? It just gets told when the command’s invoked. THAT is the sort of flexibility I like in an application. The pages don’t need to worry how to display their commands any more, which means all the styling and configuration code for the buttons is in a single location for the entire application.

Second, I can TEST MY PAGE IN ISOLATION! Well, not quite, but the step to getting there is pretty small. I just need to push the information to create the CommandBinding object into the dependency property and have the binding handled by the host. Then, the page can run “anywhere”, such as in a test harness. Throw in some injection for the data source, and it could go into a silverlight app… portability… yay!

Third, it just feels good. No really, the degree of separation it provides to an app makes working on either side (host, page) easier and cleaner… that feels good to me.

Written by erwilleke

July 19th, 2007 at 11:35 am

Posted in Uncategorized

The joys of a designer!

without comments

and, I’m not talking about the type that plugs into an IDE and lets somebody play at being a prolific programmer by generating thousands of lines of code… I’m talking about the living, breathing, ARTISTIC types… the guys who talk about colors and margins and padding and know what it means to the people looking at your app.

I’ve recently had the joy of working with Mr. Gilbert here at my current job, and he’s helped me to create an incredibly rich and beautiful experience with WPF on my client app… a piece of brilliance in its simplicity and visually pleasing environment. For the first time in a VERY long time I’ve caught myself just sitting and staring at what I’ve produced.

I’d also like to state how wonderfully useful Blend is for this sort of work. I can sit with him and talk about changes, move things around quickly and easily WITHOUT BREAKING MY APPLICATION! For instance, today we decided that a certain visual element should move up when a tab strip isn’t visible… with WPF and Blend, this was a matter of reordering a few element in a container so they docked in a different order. Done. Testable. No business logic interrupted in any way. No coding required. No styles broken. EASY.

A month or two ago I attended a demo given by Chris Bernard (blog), the MS User Experience Evangelist in my area, and he really turned me on to the possibilities of WPF and helped me to see HOW Blend is meant to be used. It’s NOT a C#/WPF development IDE, it’s a designer tool. It really is! I put on my Gimp! hat, and suddenly it makes sense (sorry, can’t afford Photoshop). Life becomes easy!

Microsoft, Thank you! THIS is what I’ve wanted… and I bet the next release even fixes the biggest bugs that bother me with Blend ;)

 

Written by erwilleke

July 19th, 2007 at 11:25 am

Posted in Uncategorized

What I saw last night…

without comments

Last night I was walking past the morgue, and what did I see, but my very own blog, thin an starving from lack of attention… sitting there parked on a gurney waiting for its last breath before being wheeled inside.

Well, a sense of deep compassion led me to take it home with me and decide to take another try at making it work. So, for the moment, expect a series of little posts about WPF, like the one immediately to follow….

Written by erwilleke

July 19th, 2007 at 11:23 am

Posted in Uncategorized