views:

412

answers:

2

This is similar to a question I asked a couple of days ago. However, I now have a better understanding of the problem, so I'd like to take another crack at it.

I am creating an MVVM app that (among other things) displays a list box with alerts for the user. These alerts relate to various routine tasks that have to be carried out periodically, and each alert contains a hyperlink that, when clicked, will open the editor and record needed to perform the task related to the alert.

My problem arises when I try to bind these hyperlinks to ICommands. The app's commands are all ICommand objects and are exposed as command properties in the view model. So normally, binding to a command is as simple as Command="Foo", where Foo is a view model command property.

But that won't work for my hyperlinks. Here's why: The ListBox is bound, through its ItemsSource property, to a collection property in the view model called Alerts. This collection is made up of Alert objects, which contain the information necessary to create the alerts and their associated hyperlinks.

However, since the ListBox is bound to the Alerts collection, its elements only have access to that collection, and not to the rest of the view model! In other words, my hyperlinks don't have access to the command properties they need to bind to. Command=Foo simply doesn't work, because WPF can't find a Foo property on the Alerts collection, even though the view model has a command property with that name.

I can work around this with a fairly ugly hack that involves using an IValueConverter to instantiate the ICommands I need. The hyperlink binds to the name of the ICommand it needs (from the Alert object), and the IValueConverter swaps the name for a new instance of the ICommand itself.

I am not really happy with this solution. I have been trying to figure out how to create resources from the view model command properties, so that I could bind the hyperlink commands like this:

<Hyperlink Command={StaticResource Foo} />My Hyperlink</Hyperlink>

But I can't figure out how to create the resource.

Any suggestions on how to solve this problem would be greatly appreciated. Thanks for your help!

+1  A: 

Why not just expose the Command from the AlertViewModel instead? Even if it is actually getting it from the parent view model:

public class MainViewModel
{
    private ICollection<AlertViewModel> _alerts = ...;
    private ICommand _theCommand = ...;

    public ICommand TheCommand
    {
        get { return __theCommand; }
    }

    private void SomeMethod()
    {
        _alerts.Add(new AlertViewModel(this));
    }
}

public class AlertViewModel
{
    private readonly MainViewModel _mainViewModel;

    //ctor omitted

    public ICommand TheCommand
    {
        get { return _mainViewModel.TheCommand; }
    }
}

HTH, Kent

Kent Boogaart
Thanks! Interesting idea--but I still need to set the ItemsSource property to a collection in the AlertViewModel to get the ListBox populated, and that disconnects the hyperlinks from the commands exposed by the AlertViewModel.
David Veeneman
A: 

I have implemented the IValueConverter approach. The solution is documented with a demo project on The Code Project. Hopefully, it will help others down the road.

David Veeneman