“Retail” comic gets its own site, full archive

For a while, my hometown’s local newspaper, the Cedar Rapids Gazette, carried a comic strip called “Retail”. I enjoyed the strip’s wry humor, even though I’ve never worked in retail. (I spent a few months as a checker in a grocery store, but that doesn’t compare to what happens in the strip.)

Earlier this year, the Gazette dropped “Retail”, which was very sad. (I only read the Gazette when I went back to visit family, but still, “Retail” was one of the high points of the comics page.) And here in Omaha, the World-Herald has never carried the strip. So I was psyched at the beginning of this year when Norm Feuti, the author, started posting daily “Retail” re-runs from 2006 on his personal site. It’s been in my Google Reader all year.

Now he’s announced that the “Retail” comic now has its own Web site, with unlimited archives. And yes, it has an RSS feed, so I can still get “Retail” in Google Reader — but now it’s today’s strip. Sweet!

From what I can tell, “Retail” is still syndicated in newspapers — it hasn’t made the jump to 100% webcomics. And I don’t see any way to buy dead-tree collections of the comics. (Not that I’ve ever bought a paper compilation of a webcomic… thought about it, never done it.) So for now, the strip is in an interesting state. But it’s an interesting state with full archives, so I’m happy.

If you haven’t read the comic, and enjoy dry humor, go check it out.

Interesting times

I keep thinking I should blog about events in my life, so I can look back later and say, “When did that happen?” Maybe nobody but me will care, but the past couple of weeks were interesting enough that I’m going to blog about them anyway.

First, there was the hailstorm a week ago Thursday. Jennie and I were watching TV when we heard a weird thump overhead. It sounded like somebody had thrown a baseball at our roof. Then another, and another. I looked outside and it looked like someone had been throwing snowballs at our driveway. I later heard that it had been “softball-sized” or “three-inch” hail. It only lasted about two minutes, but it was crazy.

My car had been parked in the driveway, and the next morning, I found that its back window was basically gone. Maybe a third of its area was still intact; the rest was just not there anymore. There were tiny shards of glass everywhere, including the front seat of the car. This is the old car; we didn’t have comprehensive insurance on it, so I had to pay to repair it. It also hasn’t been able to start since last November, so we had to get it towed to the shop (it was either that, or have it get rained in). On the plus side, they got it running again, and they fixed the air conditioner too.

Then we found out our house’s roof took a beating in the storm, and we may have to get the whole roof replaced.The adjuster hasn’t been out to look at it yet, so we don’t know for sure, but we’re saving up to pay the deductible if they do decide it needs replacing.

Tycho has barely been eating for a while now, even if we offer him wet food, so Jennie took him to the vet. He’s lost a full pound, which doesn’t seem like a good sign, and the vet took X-rays (these are our cats — we’ve learned to take X-rays and do bloodwork if anything seems even a little out of the ordinary) and she found that he had several teeth whose roots were splitting. Doesn’t that sound like fun? She said he didn’t need them extracted right away, and gave him some pain medication. When he got home, he snarfed as much food as we could put in front of him. Since then, he’s been back to eating a few mouthfuls at each meal, even though the pain medication was supposed to last three days and we’ve given him even more pain meds since then. We’ll probably need to do something more about this soon.

And yesterday, I got scratched in the face by another cat — one with all four sets of claws, and one who was in a stressful situation and obviously far, far more freaked out than I realized. Also in a position to use all four sets of claws on my face at once, because I was stupid. Pulled my glasses right off. Didn’t get my eyes, thank goodness, but my eyebrows, both cheekbones, a couple of deep gashes in my chin, even clipped one ear and the back of my head. I went to urgent care and got five stitches in my chin. I looked like Frankenstein’s monster for most of the weekend, with all the dried blood from all the scratches. The blue thread of the stitches makes the red cut look like this huge scary purple gash, but when you look closer it’s not as frightening as it looks from a distance. The doc gave me a tetanus shot and some antibiotics, just in case, so now I’ve got a sore arm and chills (aftereffects of the tetanus shot) and a sore face (Advil helps). But I’ll be fine. I’m not one of those lawyer-happy freaks who would sue or something stupid like that — sometimes shit just happens! The cat has been removed from the stressful situation and should also be fine; this was hugely out of character and there’s no reason to think it’ll happen again — just one of those freak things. And on the plus side, with this cut on my chin, I may well end up with a Harrison Ford scar.

Oh, and between the vet bill, the car-repair bill, and one or two other things, Jennie and I had to sit down and redo the budget last Friday. We were afraid we would have to empty our emergency fund. It turns out we didn’t have to touch it. We reallocated a bunch of stuff, put other things off for another month or two, and found over a thousand dollars in this month’s budget. We had to make a few tough calls, but man. This is why we budget.

So there’s definitely some good stuff to go with all the excitement. But still, I think I’ll go do something very uninteresting now.

Refactoring with MVVM is easy!

I’ve built up a kind of intellectual appreciation for some of the things MVVM gives you, but today I had a real “wow!” moment.

I’ve been working on a WPF UserControl, and it was getting kind of big and cumbersome. I wanted to extract some pieces from it into smaller UserControls to make it more manageable (and to make it easier to make some changes to the high-level layout).

So I created a new UserControl, moved my XAML into it, and referenced it from the original spot.

And that was it. I ran it, and it worked. That simple. No worries about moving dozens of code-behind methods onto the new control. No messing with method and field visibilities, and figuring out which objects the new control needed to have references to so it could do its work. No re-hooking event handlers.

Okay, it wasn’t quite cut-and-paste — there was some fixup to be done. The new UserControl needed some xmlns: attributes added. And I wanted the attached layout properties (Grid.Row, Grid.Column) to stay in the original file, not move into the new one (they’re part of the parent layout, not intrinsic to the child UI). So it took maybe a minute or so.

But it was nothing like the splitting headache that is extracting a UserControl in WinForms.

And then I extracted another UserControl. And I ran. And it just worked.

Wow.

Just, wow.

But the downside is, now I’ve got this overwhelming temptation to rewrite our million-line codebase in WPF…

MVVM and DialogResult with no code-behind

I like the Model-View-ViewModel pattern in WPF, and the way it helps get code out of the UI and into a place you can test it. But every now and then you run into a weird limitation — something you can’t do out of the box. One such example is closing a dialog box.

WPF’s Button doesn’t have a DialogResult property like buttons did in Delphi and WinForms. Instead, the codebehind for your OK button has to manually set the Window’s DialogResult property to true. This makes sense in principle — it lets you validate the user input before you close — but it makes it hard to use “pure” MVVM with no code-behind. I don’t actually give a hoot about blendability (I still write all my own XAML), but since I’m still learning WPF and MVVM, I take it as a challenge to find pure-MVVM solutions to problems, just as a learning exercise.

The obvious (wrong) solution

The obvious solution would be to just do this:

<Window ...
        DialogResult="{Binding DialogResult}">

Then make your ViewModel implement INotifyPropertyChanged in the usual way, and DialogResult gets pushed up to the view the same way as everything else. Right?

Unfortunately, DialogResult isn’t a dependency property (good grief, why not?), so the above code gives you a runtime error when you try to create the window:

A ‘Binding’ cannot be set on the ‘DialogResult’ property of type ‘TestWindow’. A ‘Binding’ can only be set on a DependencyProperty of a DependencyObject.

Back to the drawing board.

Others’ solutions

Some Googling found a StackOverflow post, “how should the ViewModel close the form?”, with an accepted answer (with 5 downvotes) of “give up; you can’t use MVVM for dialog boxes”. But I’m not quite ready to throw in the towel, so I keep reading.

Another answer on the same question — which had 0 upvotes at the time I read it, despite perfectly answering the question — pointed to a blog post by Adam Mills: “Window.Close() from XAML”. Adam’s solution uses an attached behavior. I’m learning to appreciate the attached-behavior pattern; you create an attached property, but then give it side-effects. It’s a good way to get code out of the codebehind, and it forces you to make it reusable at the same time.

But I’m not crazy about the details of Adam’s solution, because it requires you to create a style, hook up triggers, …a lot of mess. His post doesn’t actually have a complete code sample, so I’m not even sure how you hook the style into your window, though I’m sure I could puzzle it out eventually. And even his incomplete example is five lines of XAML. It’d probably be up to 7 or 9 by the time you actually got it fully wired up, and that’s 7 or 9 lines that you have to repeat for every dialog box you write.

Shouldn’t it be simpler? Shouldn’t it be almost as simple as the databinding syntax would have been, if the WPF team had gotten it right and made DialogResult a dependency property?

The one-line* attached behavior

* Okay, yes, it’s two lines if you count the XML namespace.

So I rolled my own attached behavior that does make it almost that simple. Here’s how you use it:

<Window ...
        xmlns:xc="clr-namespace:ExCastle.Wpf"
        xc:DialogCloser.DialogResult="{Binding DialogResult}">

Your ViewModel should expose a property of type bool? (Nullable<bool>), and should implement INotifyPropertyChanged so it can tell the view when its value has changed.

Here’s the code for DialogCloser:

using System.Windows;
 
namespace ExCastle.Wpf
{
    public static class DialogCloser
    {
        public static readonly DependencyProperty DialogResultProperty =
            DependencyProperty.RegisterAttached(
                "DialogResult",
                typeof(bool?),
                typeof(DialogCloser),
                new PropertyMetadata(DialogResultChanged));
 
        private static void DialogResultChanged(
            DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            var window = d as Window;
            if (window != null)
                window.DialogResult = e.NewValue as bool?;
        }
        public static void SetDialogResult(Window target, bool? value)
        {
            target.SetValue(DialogResultProperty, value);
        }
    }
}

I’ve posted this as an answer on the StackOverflow question, so if you think it’s a good solution, feel free to vote it up so that others can find it more easily.

Brittanica

I’ve fulfilled one of my life’s ambitions: I now own a print copy of the Encyclopædia Britannica.

Of course, it’s not brand-new — it’s the 1984 edition, picked up at a used bookstore at $45 for the whole 20-volume set. But that’s cool. It’s got the history I grew up with. The USSR. Pluto as a planet.

Plus, you know. Britannica.

Let’s see… I’m married, have a house, own a copy of Britannica. I’ve even had my fifteen minutes of fame. Geez. There aren’t that many life’s ambitions left.