WPF usercontrol - wpf

I've got a parent UserControl which has a property which I would like to access from a child usercontrol of the parent.
Is this possible? I'll be doing this through the child control's viewmodel.
Just wanted to get an idea on the best approach to do this.
Thankyou.

It's not impossible, but it's not the preferred design pattern (at least not one I would happily use).
The easiest way to do this, would be to pass the parent (via reference or interface) to the child (myabe during the new routine).
The way I would do it, is to have the child raise an event (which the parent handles) when the child needs to access the parent's property. Basically, child raises event, parent handles it, by providing the necessary value to the child.

Related

Backbone.js - sharing part of a model with another view

I have a parent view with parent model, and a child view.
I would like to pass a reference to part of the model (a collection) to the child model, so the child model can monitor this for changes and react accordingly.
I'm not sure about the best way to do this - possibly one of these approaches?
Pass whole model : I don't want to do this, as the model contains a
bunch of stuff that the child shouldn't know about.
Pass part of the model : I don't think this is possible... if I use
this.model.get('thesubpart'), I think I will be passing a value, not
a reference.
Bind the child event in the parent view : is this the way to go? I'm
not sure how I would go about doing this.
Your question is a little bit confusing, but I think you want a child model to react to something happening in a parent model, though I'm not sure if the parent is a collection or a single model itself.
The preferred way to do this is through events (i.e. parent.on('change', child.handleParentChange), where handleParentChange is a function defined on the child model. Since you seem to be interested in only a specific attribute change, you could bind to the more specific "change:thesubpart" event.
There are different ways to do this, such as an event aggregator, but the general idea is the same. Be careful of zombies, though. If the parent outlives the child, it will keep the child in memory because of the binding (an advantage of the event aggregator, if implemented correctly).

Selector that can only take child elements of a certain type?

I need to write a control that is supposed to take only a certain type of child controls. Functionally it works like a Selector in that I can select/activate on of its childs but it seems that I can not derive from Selector because an ItemsControl can take any type of child (object). I really would like to have compiletime typesafety here. So throwing an exception when a child of the wrong type is added is not an option.
This constraint seems to be necessary because the parent control needs to rely on certain properties and behavoir in its children. There is also some direct communication of the children with its parents.
How is something like this usually handled in WPF.
ItemsControl's wrap their children in an item container type of your choice. Thus, you know the children of your ItemsControl will always be of that type. For example, ListBoxes always have ListBoxItems as children.

How to listen for AffectsParentArrange events when you're not the parent

There is an attribute "AffectsParentArrange" that implicitly invalidates the parent's layout - but I want to attach an event handler to the "event" triggered by that attribute.
When a child property with the attribute changes, the parent's arrangement is invalidated.
I have a custom control (which is not the immediate parent) that needs to receive an event.
Does anyone know of an event that can be used here?
Do I need to provide a custom parent that overrides a method and fires an event?
It just calls InvalidateArrange() on the parent when the property change. This causes WPF to later call Arrange() on the parent. Neither of these calls has any way to intercept it (without using really sneaky techniques like patching IL code or attaching a debugger to the process).
This means that the only ways to write managed code that can detect the InvalidateArrange() is to create a custom parent which overrides the ArrangeOverride method, or tap into some behavior of the Arrange method for the particular control in question - for example if the parent is a Panel you could add an extra invisible child just to receive Arrange() calls from its parent.
Update When you get the Arrange() callback you cannot detect why InvalidateArrange() was called on the parent, but you can detect whether the property with the AffectsParentArrange flag has changed or not by saving the old value of the property in each Arrange call and comparing it to the previously saved value. This can be extended to multiple properties using a loop, a Dictionary, and either a list of properties or a call to GetLocalValueEnumerator().

How can you "plug into" the WPF rendercycle to get accurate results from VisualTreeHelper?

I am currently writing a WPF User control (PARENT) which can contain multiple child (CHILD) user controls. I am connecting the (CHILD) controls with polylines.
To do this I need the locations of the CHILD user controls.
However, the locations i get from VisualTreeHelper.GetOffset are zero. WPF is probably not finished yet with sizing and placing the CHILD controls in memory, because when I put my code in the OnLoaded event handler of my control I do get correct locations for my child controls.
This is a problem because even after I loaded my PARENT control I still want to be able to add CHILD controls and update my lines.
How I have currently solved this is by overriding the OnRender of my CHILD controls and raising an event for my MAIN control so it knows it can use the VisualTreeHelper to obtain correct values.
This however means that I will need to redraw my lines untill the last CHILD control has finished rendering.
My current solution feels more like a workaround than a solution. How can you "plug into" the WPF rendercycle to get accurate results from VisualTreeHelper?
Try overriding ArrangeOverride or OnRender on the parent control. WPF does a three-stage layout/render pass: first, it asks the controls how much space they need (measure), then it tells the controls how much space they actually have given all of the requests received (arrange), and then it actually draws everything inside the regions each control was given (render). For this to work, it follows the visual tree - the root element (say, Window) is told to measure; it has to ask its children to measure, who have to ask their children, etc. all the way down to the leaf elements before the whole thing starts returning all the way back to the root. Then it starts the arrange pass, and finally the render pass.
By watching the children's OnRender, you're implicitly saying that you want to start drawing after measure and arrange have occurred, but before the parent starts drawing itself. This can be made equivalent to the parent's OnRender - which wraps the children's OnRenders. You might also be able to do this in the parent's ArrangeOverride, which wraps the children's arrange pass, which is where (IIRC) the values VisualTreeHelper.GetOffset() accesses actually get set.
Finally, by looking at the parent control, you're implicitly waiting for all the child controls to finish arranging/rendering - which means that you won't have to monkey around trying to figure out when the last child has finished rendering.

silverlight - communicate between 2 view models in MVVM using commands

i am working on MVVM and using commanding in silverlight(DelegateEvent and ICommand)
I want something like this ,(say) i have 2 usercontrols , parent and child .
Parent is hosting the child , both have thier own viewmodels .
On parent i have a button and it executes a simple command , on execute of that command i want to update text in the child control's textbox . also we should be able to change something in child which can propagate to the parent .
Is events the best answer for this or i can have commands to update child/notify parent in some way.
There are several ways to go about this.
First, it is completely appropriate to have ViewModels that are composed of other ViewModels, as long as you are OK with them being coupled in that way. When you do that, they can just talk to each other using regular method calls.
Next, you can decouple a bit and use events. Nothing wrong with that. There is still an Observer -> Observable coupling, but they are less dependent upon each other.
Next, you can completely decouple and use something like an EventAggregator (Prism has a good one you can use). Shoot a Publish a message. The other subscribes. They don't know about each other at all.
I have used commands for this as well... but for ViewModel to ViewModel communication, I find this to be a bit awkward.
You should probably start with most obvious implementation where parent viewmodel simply holds a reference to a child viewmodel, and child viewmodel holds a reference to a parent viewmodel. Then when a command is executed on parent viewmodel it simply sets a value on a child viewmodel to which textbox is bound to.
Adding a layer of abstraction between parent and child (e.g. events) adds a level of complexity and as a result it should be justified. If the value this indirection provides is higher than the cost of increased complexity of the code (e.g. it's now less clear what happens when command on a parent is executed, you will have to solve a problem how child gets subscribed to parent's event without obtaining the actual reference to it and vice-versa, adding additional dependencies between parent a child will require adding additional events, which pollutes the actual logic with all the plumbing, etc.) then certainly events (or something like PropertyObserver) might be a next logic step.
This seems like an ideal situation for using an EventAggregator like the one in the Composite Application Guidance / Prism.
In this model, you can set up a MessageBus in the root of the application (or other common area).
// in App.xaml.cs
public static IEventAggregator MessageBus = new EventAggregator();
Then set up a common Messages library
// in Messages.cs
public class SimpleCommand: CompositePresentationEvent<SimpleObject> { }
Where SimpleObject is a class or variable that contains all the info necessary to process this event.
// in control with button
App.MessageBus.GetEvent<Messages.SimpleCommand>().Publish(SimpleObject);
// anywhere in your app that you "care" about this
App.MessageBus.GetEvent<Messages.SimpleCommand>().Subscribe(ProcessingMethod);
Where ProcessingMethod is a method that takes a SimpleObject as a parameter.
Then you can spout off messages from anywhere and process them anywhere - across viewmodels, controls, etc. You can even pass MessageBuses between components if you are dynamically loading parts of the app. Works well.

Resources