How to check where a Panel's Children come from? - wpf

I created a custom Panel, within which I need to check whether its Children are managed by manipulating the collection manually, or whether the panel is used as ItemsPanel for an ItemsControl.
This to prevent the following exception from being thrown when trying to manipulate Children.
Cannot explicitly modify Children collection of Panel used as
ItemsPanel for ItemsControl. ItemsControl generates child elements for
Panel.
How can I differentiate between the two different usages of the panel?

A Panel's IsItemsHost property can be used to check whether the Panel "is a container for user interface (UI) items that are generated by an ItemsControl".
This property can be set manually when creating an ItemsControl template, but also seems to be set to true when using an ItemsPresenter and specifying the panel using ItemsControl's ItemsPanel property.

Related

Using a Grid as the Panel for an ItemsControl

I found this tutorial Using a Grid as the Panel for an ItemsControl but I couldn't get it to work.
I get this exception:
'Cannot explicitly modify Children collection of Panel used as ItemsPanel for ItemsControl. ItemsControl generates child elements for Panel.'
caused by grid.Children.Add(child) in this loop
foreach (FrameworkElement child in phantom.Children.ToList())
{
phantom.Children.Remove(child);
grid.Children.Add(child);
// ensure the child maintains its original datacontext
child.DataContext = phantom.DataContext;
}
Is there any work around possible by inheriting from ItemsPanel?
Shoehorning Grid into an ItemsControl is not a good idea.
You loose the function of an ItemsControl. Peter Duniho mentioned in the comments that an ItemContainer is where you see attached properties. For my application I needed to use the Selector functionality. If I used a Grid I would have had to implement this myself but I saved myself a lot of trouble just using an Listbox.
If you where wanting to use a Grid I suggest you look into the ListView as well as GridView. And if this isn't flexible enough you can always write your own ViewBase.

How to identify whether a WPF Control is a Container control?

At runtime I am creating a WPF control. It can be any WPF Control.
I want to find out whether this WPF Control, IS A CONTAINER CONTROL.
i.e. can this control can embed/contain another control.
Does there exist any Attribute through which the above can be achieved?
e.g. a label, panel, groupBox can contain other control like button, but textBOX cant.
In WPF there are a few base classes that controls extend from.
ContentControl: Most controls extend from this because most controls can store some type of single content within them.
ItemsControl: These are types of collection controls, which contain a collection of content within them.
Panel: These are special controls for layouts. They implement the ArrangeOverride and MeasureOverride methods to measure/arrange the children controls within them. Most of them also expose attached properties for best use.
That being said, you would typically want to use the is operator to check if your control inherits from what you intend it to. You can be specific or general, but typically you want to be as general as possible. I'm not sure what you meant by "container", which is why I listed the three (3) typical base controls that could contain other controls. For example:
if (myControl is ContentControl)
{
// Do something here.
}
All the controls mentioned here and here apart from TabControl inherit from Panel
So you can do something like:
if (myControl is Panel || myControl is TabControl)
{
// Then it's a container
}

Panel that supports explicitly setting its headers and has itemtemplateselector property

In WPF, I want to show records from a collection in a grid like view. I want to be able to explicitly set the headers of columns. Also I want to use itemtemplateselector property because each object should be displayed differently based on a property value. I have a custom DataTemplateSelector class which gives the correct DataTemplate(whether it contains a textbox or not) by checking a property of the object. Is there a control such that I can explicitly set its headers and itemtemplateselector property. If there isn't such a control, is there a way to achieve the same effect using existing controls? I can create a custom control that has a stackpanel for headers and a itemscontrol for displaying the items but I don't want to deal with all of the alignment issues.
I solved the issue by using GridViewHeaderRowPresenter and ItemsControl as described here.

WPF Control Grouping

I have a group of controls that look like this:
<Link to Image>
that i reuse a number of times. It's really simple a listview, 3 buttons and some layout panels.
I want to turn this into a reusable component but the columns in the listview can change and the sources they are bound to will change.
How do i go about this? i've seen many comparisons between ContentTemplates and UserControls etc but they never seem to be functional (eg Add will raise an event which i'll have to handle to add something to the listview, remove will raise an event where i'll likely ask if they are sure first).
I've accomplished the events with my own UserControl, but can't pass a list of GridViewColumns to the control. It also means i have to expose SelectedItem etc manually from the UserControl. Subclassing Listview seems promising for setup and access but doesn't conceptually seem right to have other controls in the listview area.
What is the right way?
I would definately recommend a UserControl. You should:
Add the controls you require to your user control
Add the Dependency Properties you require to your user control which allow you to configure it, e.g. SelectedItem
Wire up these dependency properties to the various controls within your user control. An easy way to do this is to set the DataContext of your user controls visual tree to the user control itself, e.g. if you have a Grid as the root for your user controls, set its DataContext = this in code. You can then use TwoWay bindings to connect up the various control properties to the user control properties.

Expand WPF Expander to bring contained element into view

I have an expander that has n contained elements (possibly other Expanders that also contain elements).
Now I want to programmatically bring a contained element into view - like with BringIntoView() for ScrollViewers. All Expanders that currently hide the element should expand.
My current idea is to subclass the Expander and make it react to an event that bubbles up from the contained element. But there may be a much easier way in WPF, right?
You can create an attached property to do that instead of subclassing the existing Expander class. This AP would be of type bool, and when sets to True on an expander register for the Expanded event. In the event handler, you can walk up the logical tree to grab the parent Expander and toogle is IsExpanded property.

Resources