WPF - Docking content inside ContentPresenter - c#

The Circumstances
I'm building a plugin for a WPF application. The parent application has a ContentPresenter and my plugin returns a UserControl. When the parent app runs, it loads up my plugin and places my UserControl inside the ContentPresenter.
The Problem
The problem is that my UserControl is not resized to fit within the ContentPresenter, so when the ContentPresenter is too small to show everything, my UserControl is simply cut off. If the app is resized so that the ContentPresenter becomes bigger than my UserControl, then I get a bunch of whitespace around my UserControl.
Basically, I want my UserControl to act as if it was inside a DockPanel.
What I've Tried
Both the ContentPresenter and the UserControl have Horizontal and Vertical alignments set to Stretch already.
I can achieve the desired result if I wrap my UserControl in a ViewBox, but I don't really know if that's the right way to do it. It feels like I'm missing out on some basic layout principle (which might just be a holdover from my Winforms days). Is there any "proper" way to achieve a docking effect within a ContentPresenter element?
EDIT: I want to emphasize that this is not a ContentControl vs. ContentPresenter issue. I cannot change out the ContentPresenter element because it is part of the parent application. The only thing I can control is the contents of my own plugin which are being placed within the ContentPresenter element. The developers of the parent application might allow me LIMITED access to the ContentPresenter if I need to adjust a property by traversing up the visual tree at runtime, but they've already stated that they don't want plugins navigating outside of their own scope of controls. This isn't as much of a technical limitation as a their-terms-and-conditions-won't-allow-it limitation.

Related

How can I create a usercontrol with a panel that slides down over it's parent control?

I want to create a UserControl that displays a dropdown selection control and a couple of buttons when collapsed, but could be expanded to display a larger selection of items when desired. It's expansion panel should slide down over the controls of the Window or UserControl it's embedded in.
I can do it if all of the XAML is in the same control, but I can't figure out how to do it if I want the small view and sliding bits in a separate, re-usable, UserControl.
For a small panel I am using an animation that changes the margin of an offscreen panel and bounds clipping to make it happen. I have been copying the XAML from Window to Window. I want to make a re-usable much larger version of this, but displaying it, properly, has me a bit lost because of the bounds clipping. The UserControl clips the panel within it's smaller view, rather than allowing the panel to display over it's parent.
This is the effect I am looking for:
The primary issue seems to be that the sliding panel has to be contained within the UserControl, or it gets cut off. So the user control has to be much larger than its collapsed view. Because of that, when you want to embed it in another Window (or UserControl) you have to do XAML gymnastics to accommodate for the size of the control while making appear that the control isn't really that big.
Maybe that's just typical for XAML. I am still learning. But I can't figure out how to have a visual element of a control appear outside its bounds. A Popup doesn't really work because of how it opens and closes with focus.
At this point it's just an exercise, as I've decided to implement it a different way (modal dialog) so I have the control I need over the visuals.

Dynamic layout of WPF controls which depends on some condition

I'm using WPF and I have a problem with layouting. I have got a docked panel (non WPF, I just hosted my control inside). And when a user wishes to dock this panel on the left or the right of the screen, I need to layout my controls in one way. But when the user wishes dock this panel on top or bottom, I need to layout my controls in another way.
My question is what is the best way to implement dynamic layout of WPF controls, which depends on some conditions?
I understand, that I can use the grid and dynamically change positions of my controls inside the grid. But I am not really happy with this solution. I'm looking for a solution with no code intervention, xaml only. And in case this is impossible, at least involving minimum intervention in the code.
Thanks in advance.
You could use AvalonDock to get a docking system very much like visual studio's.
This would give your users full control on the layout they desire, and it's not too hard to implement.
But if you really want a quick way to do this, I'd recommand Binding the DockPanel.Dock property to a ViewModel value that changes upon user input (along with an IValueConverter if necessary).
For this purposes DataTemplate feature is.
The idea is to provide multiple DataTemplates and then using your custom inplementation of the DataTemplateSelector rturn right DataTemplate based on criteria.
For an example see my post regarding DataTemplates
Data Templating Overview
Use StoryBoard and change the transformation of controls

How to reuse WPF ScrollViewer to create my own scrollable control?

I'm trying to improve the graph drawing control that comes with Graph#. It's good, but things get out of hand when you start dragging nodes around. This is my first encounter with WPF, so this is probably a newbie question. :)
I have the GraphCanvas control which has nodes and edges on it. They can be dragged around which changes their coordinates, possibly making them negative. I would like to add scrollbars to the control which would allow to see how big the canvas really is.
To this end I'm thinking of putting the GraphCanvas inside a ScrollViewer. Which would be pretty easy and straightforward if not for one problem. I may not resize the GraphCanvas itself when a node is dragged outside the borders or this will mess up dragging bad. That is also the problem with the original control (check it out, it comes with a sample application).
It would be good if I could bind the scrollbar size/location to properties of the GraphCanvas, so that the ScrollViewer would not scroll anything physically, but just set the properties of GraphCanvas. That in turn would perform all actual calculations and scrolling.
How can this be done?
OK, I found it! Three easy steps:
Implement System.Windows.Controls.Primitives.IScrollInfo on your custom control;
Add your custom control to a ScrollViewer;
Set the CanContentScroll property on the ScrollViewer to True.
Voila!
Check out this link straight from MSDN. It talks about composing several controls into a single Composite Control:
WPF: Customizing Controls for Windows Presentation Foundation

Resize ElementHost to size of the hosted XAML UserControl

I would like an expanding panel in my Windows Forms app. I was having a look to see if this would be possible using the WPF Expander control. I've created a Xaml UserControl where I've inherited from Expander rather than UserControl. I have a trigger on the Expander for setting it's size.
Is it possible to change the height of the ElementHost to reflect the change in the size of the child? Or would I just be better off creating an expanding Panel in Windows Forms?
I'm using C# .Net 3.5.
Cheers
Yes. You need to override MeasureOverride in your outermost WPF control, convert the size from WPF coordinates to device coordinates, and update ElementHost.Size.
Since you are already subclassing Expander:
Override the MeasureOverride method
After the measurement is calculated, use PresentationSource.From(visual).CompositionTarget.TransformToDevice.Transform(point) to get the device coordinates
Update ElementHost.Size.
Your Expander subclass instance will need a pointer to ElementHost to do this.
A more general solution would be to create a new class to handle the synchronization. It would subclass FrameworkElement and be the direct child of ElementHost.
Is there any particular reason you are inheriting from Expander vs. just using an Expander in your UI?
If you set up the H/V Alignment properties of the Expander, you should be able to get most standard sizing behaviors without having size triggers. From my experience, the content portion of the Expander automatically sizes to fit.
If you're trying to completely remove the header part, then you might look at making your own ControlTemplate for the Expander.

Drag&Drop-adorner in deeply nested visual trees

We have a WPF application that has custom windows on a canvas which in turn contain custom controls (the main canvas containing the custom windows is again custom control displaying stuff). So basically the visual tree looks like this (without implicit Borders and other things):
- Windows
- Canvas
- WindowMgr
- CustomWindow (maximized with z-index 0, functioning as background)
- ScrollPresenter
- CustomControl1
- CustomWindow
- ScrollPresenter
- CustomControl2
Now we need drag&drop from those custom controls to each other (usually from a movable window to the background window). To show the drag&drop adorner an adorned element and an adorner layer is needed. Usually examples use their grid or itemscontrol for that, and also get the adorner layer from the same element.
Doing the same here doesn't work since the ScrollPreseneter/CustomWindows clip their content which prevents you from dragging out of the window. For now we walk up the visual tree until we find the root canvas and use that as adorned element, but that seems kind of dirty (and as we experienced isn't very robust).
Any suggestions on a robust solution for this?
If I read your question correctly and since you didn't mention it yourself you might be looking for the AdornerDecorator Class, which Provides an adorner layer for elements beneath it in the visual tree.
Assuming from its name that ScrollPresenter is derived from ContentPresenter, it's worth noting that for implementing advanced custom controls you might want to surround their ContentPresenter by an AdornerDecorator, just like the Window Class does, see for example Don’t forget the AdornerDecorator for a nice real work scenario involving drag&drop too.
That is, by means of the AdornerDecorator you'll ensure the required AdornerLayer to be contained within your custom control, hence removing the need to retrieve it elsewhere by walking up the visual tree, e.g.:
<ControlTemplate TargetType="{x:Type CustomWindow}">
<Border ...>
<Grid>
<AdornerDecorator>
<ScrollPresenter ... />
</AdornerDecorator>
</Grid>
</Border>
</ControlTemplate>
Depending on your particular scenario you might need an AdornerDecorator for your custom windows, your custom controls or both.
See Adorners Overview for more details on the adorner architecture.

Categories