0

I was thinking I could simplify and consolidate some code by creating a UserControl. To test my theory, I picked a very simple prospect. Basically, on almost every screen, I expose a control that lets an administrator choose which tenant they are working on. (Non admins are assigned a tenant and do not see this functionality.)

So I created a user control, sticking to the MVVM pattern, that has its own viewmodel. The viewmodel exposes the list of tenants and a SelectedTenant property to the UC. The visual aspect is, basically, just a listbox. The UC also exposes a dependency property called SelectedTenant that could be bound to a property in the parent control or window.

The missing link, as many others have queried about, is somehow connecting the dependency property exposed by the UC to the ViewModel, underneath, so that when a user selects a tenant, the viewmodel's SelectedTenant property gets set and then propagates up to the UC's DP which would then trigger the parent control to, perhaps, take some action through its binding to the UC DP.

I haven't seen anything that explains a "proper" way to approach this. Most posts suggest using the parent datacontext or, essentially, abandoning MVVM for the UC.

Looking at the code I had, it seemed, to me, that a very simple approach would be to include code in the DP getter and setter that would read or write the UC's viewmodel values. Then I saw a post saying that you should never do that, but there was no explanation as to why. So I am asking why this is not considered a valid approach.

Digital Camel
  • 175
  • 2
  • 14
  • I'm not 100% clear on the problem; could you provide sample code of what you want to do that you think is bad? – Marisa Feb 02 '18 at 20:43
  • "*a user control ... that has its own viewmodel*" is a bad idea in the first place. Although often advised by "expert" blogs on the internet, a UserControl should never have its own view model. It should instead expose dependency properties that are bound to properties of a view model which is provided "externally" by means of property value inheritance of the DataContext property. The UserControl should not have knowledge about the view model. It just has bound properties. – Clemens Feb 02 '18 at 20:48
  • See [this question and answer](https://stackoverflow.com/q/48578490/1136211) asked today for an example. – Clemens Feb 02 '18 at 20:52
  • @Clemens - I've seen that, as well, but then how do you build a control that, as in this case, pulls data from a DB and presents that list to the user? Do you advise just not using MVVM with user controls? – Digital Camel Feb 02 '18 at 21:04
  • UserControls without own view model doesn't mean "not using MVVM with user controls". It's still MVVM when the properties of your UserControl are bound to properties of a view model object in the inherited DataContext. Just the internal, private view model of a control makes no sense. A UserControl has code behind, and that may be a lot of code. A major part of that are PropertyChangedCallbacks of the control's dependency properties. – Clemens Feb 02 '18 at 21:14
  • @Clemens - You are mixing up a "user control" and a "UserControl [derived class]" that many people use loosely and interchangeably when they really aren't. The explanation you gave about using DPs and "code-behind" is for a "user control" (i.e. a custom control built by the user). I put "code behind" in quotes because there is no "code behind" in the technical sense. You have a class derived from Control that overrides the style metadata for the class in a static constructor and then you have a totally detached XAML in your Themes folder. – SledgeHammer Feb 02 '18 at 21:59
  • @Clemens - Continued... That is not code behind, its the implementation class. Typically, in MVVM, your View WILL be derived from UserControl and use various methods to set the DataContext. Personally, I use an attached property for that. Also no code behind here since the DataContext should point to a class derived from ViewModelBase that uses INPC. – SledgeHammer Feb 02 '18 at 22:01
  • @SledgeHammer It doesn't matter at what the base class is. You can have dependency properties in a class derived from UserControl, Control, FrameworkElement or whatever DependencyObject you like. Fact is that none of these should have its private view model. – Clemens Feb 02 '18 at 22:02
  • @Clemens So what do you derive your Views from? – SledgeHammer Feb 02 '18 at 22:03
  • @SledgeHammer That's irrelevant. You're missing the point ... no private view model. A UserControl or any other control should never explicitly set its DataContext. – Clemens Feb 02 '18 at 22:04
  • @Clemens - Okeeydokee... seems pretty relevant since that what the question is about... I derive my views from UserControl (actually a class derived from UserControl that automates some of the wiring up) and I never have code behind, I wire it up to a VM. If you can't explain how your MVVMs are wired up, then *shrug*... all you've explained so far is the way NOT to do it [in your mind] :). – SledgeHammer Feb 02 '18 at 22:06
  • That "wiring up" is done by property value inheritance of the DataContext property. The value is inherited from the parent element of the control. If you set it explicitly, you're breaking the inheritance mechanism and end up asking yourself why the bindings to the properties of your control won't work. People ask this every day on StackOverflow, the answer is always the same: do not explicitly set the DataContext, don't have a private view model. – Clemens Feb 02 '18 at 22:08
  • @Clemens That's for a control or a user control, not a view. I fully agree that you shouldn't (in most cases) be manually setting DCs for controls. A View will always have its own DataContext. Why would a child View inherit the DC from say the main window? If you do that, you'd have to make every property in the app available through there. You are lumping everything together when there are different concepts here. – SledgeHammer Feb 02 '18 at 22:12
  • The difference you're making between "user control" and UserControl is completely artficial and makes no sense to me. Sorry. As said, *"A View will always have its own DataContext"* makes the people come here to ask why their bindings don't work. Seriously. Every day. Pease let's stop this discussion now. You will never convice me. – Clemens Feb 02 '18 at 22:14
  • @Clemens That's why I asked what you derive your views from lol. A "user control" is a single user defined control. A UserControl derived window (XAML) can host multiple controls or "user controls" or even child "UserControls". Heck, you can pretty much host anything in anything in WPF. Surely you see there is a difference between a control like a ListView vs. a real world MVVM view. Even though the ListView is built from many other "controls". – SledgeHammer Feb 02 '18 at 22:18
  • 2
    @SledgeHammer What I think @Clemens means is that a control (be it a custom control or a view) should not have its `DataContext` pre-assigned (people either do this in _XAML_ or in the constructor), but rather it should be provided by the context in which the control is used. That is, when you instantiate your control, it should have its `DataContext` untouched and only later you decide whence it should come from (either by binding, inheritance, or whatever). So the main point is that you **should not assign `DataContext` in control's definition**. – Grx70 Feb 02 '18 at 22:36
  • 1
    [Here](https://stackoverflow.com/questions/4225373/setters-not-run-on-dependency-properties) and [here](https://stackoverflow.com/questions/2728267/wpf-dependency-property-setter-not-firing-when-propertychanged-is-fired-but-sou) are explanations of why you shouldn't put any logic in the dependency property getters/setters, and [here's](https://stackoverflow.com/questions/1364484/dependency-property-dependent-on-another) a question that might point you to a potential solution to your problem. – Grx70 Feb 02 '18 at 23:00

0 Answers0