Tag Archives: command

MVVM Light CanExecute Command – Re-evaluate en-mass

MVVM Light CanExecute doesn’t work for commands

The following code in MVVM light does not work:

RelayCommand newCommand = new RelayCommand(onExecute, canExecute);

. . . 

canExecute = true;

. . .

canExecute = false;

That is, the bound command will not update. Even if the changed `canExecute` raises property changed.

Raise it manually

So, the way to fix this is as follows:

        public bool canExecute
        {
            get { return _canExecute; }
            set
            {
                _canExecute = value;
                RaisePropertyChanged();
                newCommand.RaiseCanExecuteChanged();
            }
        }

Which works fine. However, what if you have 10 commands, and they all have the same dependant property?

Real life

Here’s my method of working around this. Is it effectively a `RaiseAllPropertyChanged()` for commands. Start with a class level list of commands:

        // Store a local list of all registered commands to inform of updates
        private List<RelayCommand> _registeredCommands;

Now create a function that allows us to iterate this and call RaiseCanExecuteChanged to all of them:

        private void ReevaluateCommands()
        {
            foreach (var eachCommand in _registeredCommands)
            {
                eachCommand.RaiseCanExecuteChanged();
            }

        }

Finally, we can simply call this when the dependant property changes:

        public bool canExecute
        {
            get { return _canExecute; }
            set
            {
                _canExecute = value;
                RaisePropertyChanged();
                ReevaluateCommands();
            }
        }

Magic.

Disclaimer

I kind of stole the idea for this from here. I’m not selling this as a massively scalable, all singing, all dancing solution. It just works for my particular scenario, which is here:

TFS Utilities

Windows Tile Updater (Part 7 – Multibinding command parameters)

We left the last post where the Tile Updater could update text, or images, but we basically had to choose which at design time. In this post, I’m going to pass through the image and text, and have the command work out which to update.

Note: you can have both image and text in live tiles. Look out for that in a future post.

Multibinding

The first thing to know about multibinding for WinRT is that it doesn’t exist. However, to get around this, we can simply take the same approach that we do with a function – a function can only return one value, but that value can be a class; so we’ll bind to the VM (one of the advantages of exposing a static singleton instance of the VM):

<Button Grid.Row="2" Command="{Binding UpdateCommand}" CommandParameter="{Binding MVM}">Update</Button>        

The command itself needs to look something like this for now:

        public bool CanExecute(object parameter)
        {
            MainViewModel mvmInst = (MainViewModel)parameter;
            if (mvmInst == null) return false;

            if (string.IsNullOrWhiteSpace(mvmInst.ImagePath) &amp;&amp; string.IsNullOrWhiteSpace(mvmInst.DisplayText))
                return false;
            return true;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            MainViewModel mvmInst = (MainViewModel)parameter;

            if (string.IsNullOrWhiteSpace(mvmInst.ImagePath))
                TileUpdater.Model.UpdateTile.UpdateTileText(mvmInst.DisplayText);
            else
                TileUpdater.Model.UpdateTile.UpdateTileImage(mvmInst.ImagePath);
        }

There’s a couple of points here:
1. The CanExecute will not prevent the command from firing where neither parameter has a value.
2. It doesn’t disable the button when this occurs.

And that’s it – we now have a command that can accept multiple parameters and update either image or text depending on what is displayed.

Conclusion

Okay, strictly speaking, this is not multi-binding. It does however, solve the problem. I suppose the design question would be: does it introduce a tighter coupling than multi-binding?

It definitely does; however, with a bit of manipulation, you could introduce a mini-VM that just had the parameters that you need. However, for most cases, I would think that it was fine to just pass the VM to the command. We’ll see if this comes back to bite me when we start putting some unit tests in place.

Windows Tile Updater (Part 6 – Binding a command parameter)

We’re still missing functionality to show the text, or show the text and an image where both are specified.

Add text

Let’s start with the text field. It’s currently just hard coded – that’s pretty straightforward:

        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="1">
            <TextBlock FontSize="30" Margin="10">Text</TextBlock>
            <TextBox Text="{Binding DisplayText, Mode=TwoWay}" Margin="10"/>
        </StackPanel>

Next, let’s hook this up to the command.

<Button Grid.Row="2" Command="{Binding UpdateCommand}" CommandParameter="{Binding DisplayText}">Update</Button>

So that works, and the logic to show the text tile is quite straightforward:

        public static void UpdateTileText(string text)
        {
            XmlDocument xmlDoc = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150Text01);

            XmlElement textNode = (XmlElement)xmlDoc.GetElementsByTagName("text")[0];
            textNode.InnerText = text;

            Windows.UI.Notifications.TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
            TileNotification tileNotification = new TileNotification(xmlDoc);
            tileUpdater.Update(tileNotification);
        }

So, we can call this, or we can call the UpdateImage. At the moment, we can’t call both. In the next post I’ll look at how we can do this using Multibinding.

Creating a WPF app with no interface (or WPF)

This does sound counter intuitive, but let’s have a look at an example. Let’s say that I want to create an application that, when called, created a text file with a list of its own arguments, and then finishes.

Console App?

So, the first thing you think is: create a console app. Good idea; here’s what it looks like:

    class Program
    {
        static void Main(string[] args)
        {            
            File.WriteAllLines("tmp.txt", args);
        }
    }

Okay, so it’s simple and it works. And here’s what it looks like when you run it:

Running Console App

It won’t say “Press any key” unless you run it with Ctrl-F5 (because you want to take a screenshot).

Anyway, as unobtrusive as that it, what if you didn’t want it to appear? Well, one option (and, as usual, I don’t claim this is the only option), you could create a WPF app instead. In the App.xaml, you can specify the start-up object… or not:

<Application x:Class="WpfApplication3.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             >
    <Application.Resources>
         
    </Application.Resources>
</Application>

So, no StartupURI element. Next, you need to override the Startup event in App.Xaml.cs:

        protected override void OnStartup(StartupEventArgs e)
        {
            var args = e.Args.Select(a => a.ToString());
            File.WriteAllLines("tmp.txt", args);
            
            Shutdown();
        }

Conclusion

And that’s it… you now have a runable app that is completely devoid of a UI.

One word of warning: if this is going to be a slightly more complex app that makes use of asynchrony, then remember that you’re closing the app here.

As usual, if anyone knows of a better method of doing this then please leave a comment or get in touch.