0

I'd like to create a custom hyperlink control that, when clicked, navigates to a region and parameters specified by bindings to properties in a parent ViewModel. Since I'd like to be able to drop this control into any arbitrary xaml, it cannot have its own ViewModel or Module Manager, which is usually how a Region Manager is obtained.

Is there a way to get a RegionManager object in code-behind, without having to inject it into a ViewModel? I see that there's a static GetRegionManager() method on the RegionManager class, but it takes a dependency property parameter that I don't understand how to use.

Why I'd like to do this in code-behind:

While I could certainly supply the constructor that allows injection of the RegionManager object into the ViewModel, I would like my new Hyperlink control to be more self-contained and independent than that. Involving the ViewModel in this manner means that the navigation is going to take place in the ViewModel, not the new Hyperlink control, which sort of defeats the purpose of having a self-contained Hyperlink control.

Community
  • 1
  • 1
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • As a note, RegionManager is an [attached property](https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/attached-properties-overview). The static GetRegionManager method is the corresponding property get accessor. – Clemens Apr 18 '18 at 18:35
  • Yes, but I don't know what the DependencyProperty parameter it accepts is. Do I just pass it `this`? – Robert Harvey Apr 18 '18 at 18:36
  • I don't know what `this` is in your case. However, that doesn't matter, because you will only ever get a non-null value if it has been set before on the target element (by SetRegionManager or in XAML). I have no experience with Prism, but I'm pretty sure that this method is not what you are looking for. – Clemens Apr 18 '18 at 18:38

2 Answers2

0

It sounds like you want something with the behavior of a button, but with the appearance of a hyperlink. If so, I'd suggest using the existing WPF Button control and styling it appropriately to appear like a hyperlink.

If that fits your purposes, then wherever you use the control you can bind it to a command in whatever viewmodel is used there. Each viewmodel can have an IRegionManager (via constructor injection, for example) and you can use IRegionManager.RequestNavigate to perform whatever navigation is appropriate.

As a side benefit, keeping the logic in the viewmodel allows it to be more easily tested. For example, a unit test could invoke the command on the viewmodel and verify that IRegionManager.RequestNavigate was called with the appropriate parameters.

syutzy
  • 41
  • 1
  • 1
  • So if I hear you right, since you have to expose bindable properties on the ViewModel anyway, you might as well wire up the constructor in the ViewModel that gets the Region Manager from Prism? – Robert Harvey Apr 18 '18 at 18:35
  • See my question update. Styling is not the issue; a normal hyperlink control should work just fine. – Robert Harvey Apr 18 '18 at 18:48
  • Can you clarify a bit why performing the navigation from the control itself rather than the viewmodel behind the code is desirable? I'm making an assumption here that you're using MVVM, and if so then navigation is typically a concern of the viewmodel. For implementation, you could implement ICommandSource in your Hyperlink control to allow binding to arbitrary commands in the viewmodel, then wherever you use the control you'd bind to whatever Command/CommandParameter is appropriate. – syutzy Apr 19 '18 at 19:36
  • It's desirable because it makes the control *self-contained.* See the last paragraph in my OP. – Robert Harvey Apr 19 '18 at 19:38
0

You can always use the CommonServiceLocator, but that's just evil. Also, you want navigation to happen in a view model (rather than in a view) just to make it testable. If not for that, you could drop mvvm altogether.

Having a HyperLinkViewModel (that receives an IRegionManager and has an associated DataTemplate and/or ControlTemplate) looks very self-contained to me, btw. Just expose it as a property from another view model, and you have a working hyperlink.

The view model is the code-behind of the DataTemplate, in a way.

Haukinger
  • 10,420
  • 2
  • 15
  • 28