WPF ContentControl: Iterating over child control - c#

I have a WPF Window, where I put a ContentControl, Later in my code I use a string to be read as Xaml using XamlReader.Load function and put that in ContentControl. This is done to make a Dyanmic UI. Now all is done, but I want to capture the Input field values from this control. on button click.
So, all I want to do is to Iterate on Child Controls of ContentControl. How can I do this, there doesn't seems a way to iterate on child of it? Any Idea. Thanks.

Here, you can use VisualTreeHelper:
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(contentControl); i++)
{
var child = VisualTreeHelper.GetChild(contentControl, i);
if(child is ContentPresenter)
{
var contentPresenter = child as ContentPresenter;
for (int j = 0; j < VisualTreeHelper.GetChildrenCount(contentPresenter); j++)
{
var innerChild = VisualTreeHelper.GetChild(contentPresenter, j);
}
break;
}
}

The difference between the logical and visual tree is, that the visual tree lists all elements which are used to display the control. E.g. The visual tree of a button looks like
Button -> Border -> ContentPresenter -> TextBlock
The logical tree list just the controls itsself (as you declared in your xaml).
For further details, visit this site: http://wpftutorial.net/LogicalAndVisualTree.html
So to get the children you want, LogicalTreeHelper.GetChildren(contentControl); should work.

Related

Find all controls in all regions in WPF PRISM application

I am trying to add tooltip to all controls in my WPF application i tried
foreach(IRegion region in _RegionManager.Regions)
{
foreach(IView view in region.Views)
{
foreach(Control c in view.)//here my problem
c.ToolTip = "some tooltip";
}
}
That did not work because i have not any idea where I should looking for controls in that case.
Thank you for any advice.
In WPF, views should be defined in declarative way via XAML markup.
You would normally define your tooltips in your views:
<UIElement ToolTip="toolTipContent"/>
Of course, you can use bindings:
<UIElement ToolTip="{Binding ToolTipText}"/>
Note, that Prism's IView interface doesn't provide any information about the actual type of the view instance. It could be a Page, an UserControl or even a TextBox.
You can, if you want to, use linq and get only those views, which are e.g. UserControls:
foreach(UserControl view in region.Views.OfType<UserControl>())
{
// do something...
}
But that doesn't really help you, since in WPF there's no such easy way to iterate through child elements of an UserControl, as we did it in in Windows Forms.
You could use the VisualTreeHelper and traverse your visual tree looking for the child elements, but that's awkward:
void GetChildControls(IList<Visual> container, Visual parent)
{
int childCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childCount; i++)
{
Visual visual = (Visual)VisualTreeHelper.GetChild(parent, i);
container.Add(visual);
if (VisualTreeHelper.GetChildrenCount(visual) > 0)
{
GetChildControls(container, visual);
}
}
}

Adding buttons to a TabControl Tab in C#

I have a TabControl in a windows form. I have pragmaticly added new tabs like so:
for (int i = 1; i < numOfLanguages; i++)
{
// add a tab for each language
string tabTitle = split[i];
TabPage newTab = new TabPage(tabTitle);
languageTabs.TabPages.Add(newTab);
}
inside the loop I want to set up the other controlls for each tab. mainly I want to add buttons. I have seen this code:
tabPage1.Controls.Add(new Button());
Based off this example I want to do something similar like:
languageTabs.SelectTab(split[i]).Add(new Button());
I know that this code wont work. Have been looking through the params and cant see anything that lets me do this kind of thing.
Any ideas community?
SelectTab moves the actual TabControl to the specified tab, it does not return the tab to let you manipulate it.
You can index into the tab pages as follows:
languageTabs.TabPages[2].Controls.Add(new Button());
If you have set the Name property on the TabPage on creation, then you can also find individual tabs by key:
for (int i = 1; i < numOfLanguages; i++)
{
// add a tab for each language
string tabTitle = split[i];
TabPage newTab = new TabPage(tabTitle);
newTab.Name = tabTitle;
languageTabs.TabPages.Add(newTab);
}
...
languageTabs.TabPages[split[i]].Controls.Add(new Button());
(See MSDN for more)
Whichever is most convenient.
LINQ?
languageTabs.TabPages.First(tab => tab.Title == split[i]).Add(new Button());
This might be not reliable (crash) if your tabcontrol does not have tab with specific name, so you might want more reliable way:
if (languageTabs.TabPages.Exists(tab => tab.Title == split[i]))
{
languageTabs.TabPages.First(tab => tab.Title == split[i]).Add(new Button());
}

Clearing text boxes inside of a Control

I have a series of of tabs that hold text boxes in them. Some of the tabs have a control that contains Text Boxes inside of a Scrollview as well. I am trying to iterate through the tabs and clear the content of the text boxes.
I was going to use this:
foreach(TabItem item in Tabs.Items)
{
ClearTextBoxes(this);
}
I then use this to clear to the text boxes:
TextBox tb = obj as TextBox;
if (tb != null)
tb.Text = "";
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
ClearTextBoxes(VisualTreeHelper.GetChild(obj, i));
}
It is currently only clearing the first tab and none of the rest.
Any ideas?
Use the LogicalTreeHelper. Only the items of the currently active tab are contained in the visual tree, therefore the visual tree helper is not the best choice for your task.
Iterating over the tab items is IMO not necessary, only if you have a lot of other controls not residing in the tab-items and therefore want to spare cpu power. As already mentioned by Bela R, there is an error in your call to ClearTextBoxes().
I think it should be ClearTextBoxes(item) and not ClearTextBoxes(this)
foreach(TabItem item in Tabs.Items)
{
ClearTextBoxes(item);
}

Changing button properties in a loop, for example

I would like to know how it's possible to change button properties by a code when we don't know a button name while writing it.
For example, I have a loop like this:
for (int i=0; i<5; ++i) {
int buttonName = "button_" + i;
buttonName.enabled = false;
}
Thanks in advance!
You can access the Controls collection of the parent containing the button like this:
if(parent.Controls.ContainsKey(buttonName))
{
Button myButton = (Button)parent.Controls[buttonName];
myButton.Enabled = false;
}
This will need a little extra work if your buttons are not contained within the same parent; ie. some buttons on a Form, some buttons on a Panel contained within that same form.

How do I access the children of an ItemsControl?

If i have a component derived from ItemsControl, can I access a collection of it's children so that I can loop through them to perform certain actions? I can't seem to find any easy way at the moment.
A solution similar to Seb's but probably with better performance :
for(int i = 0; i < itemsControl.Items.Count; i++)
{
UIElement uiElement =
(UIElement)itemsControl.ItemContainerGenerator.ContainerFromIndex(i);
}
See if this helps you out:
foreach(var item in itemsControl.Items)
{
UIElement uiElement =
(UIElement)itemsControl.ItemContainerGenerator.ContainerFromItem(item);
}
There is a difference between logical items in a control and an UIElement.
To identify ItemsControl's databound child controls (like a ToggleButton), you can use this:
for (int i = 0; i < yourItemsControl.Items.Count; i++)
{
ContentPresenter c = (ContentPresenter)yourItemsControl.ItemContainerGenerator.ContainerFromItem(yourItemsControl.Items[i]);
ToggleButton tb = c.ContentTemplate.FindName("btnYourButtonName", c) as ToggleButton;
if (tb.IsChecked.Value)
{
//do stuff
}
}

Categories