What is a smarter way to get a child control in XAML? - c#

I have a User Control, containing a Grid, containing a child control.
I want to get a reference to the child control from the code behind for the User Control.
This is what I have:
var childControl = (MyChildControlType)this.Grid.Children.Single(c => (string) c.GetValue(NameProperty) == "MyChildControlNameFromXAMLNameAttribute");
Ugly as a run over garbage can lid.
What is a neater way to do this?

You could either go with the name-hunting, along the lines of what's been suggested already:
var childControl = (MyChildControlType)this.Grid.FindName("MyChildControlNameEtc");
Or, if you wanted a more generic approach to what you're already trying (eg if you want to look up by a different property), you could try:
var childControl = (MyChildControlType)this.Grid.Children.OfType<FrameworkElement>().Single(f => f.Name == "Blah");
or
var childControl = (MyChildControlType)this.Grid.Children.OfType<MyChildControlType>().Single(f => f.Name == "Blah");
Or you could use the VisualTreeHelper, which would work with non-Grids, and would particularly work nicely if you needed to recurse down the visual tree:
for(int i = 0; i < VisualTreeHelper.GetChildrenCount(this.Grid); ++i)
{
var child = VisualTreeHelper.GetChild(this.Grid, i) as FrameworkElement;
if (child != null && child.Name == "Blah")
return child;
}
But really if you can just name it and access it from the codebehind normally like what John Bowen said that's by far the easiest.

Assigning a Name or x:Name to an element in XAML (unless it is inside a template) makes that element accessible from code-behind as a field with that name. So this is basically already declared and populated for you during InitializeComponent:
MyChildControlType MyChildControlNameFromXAMLNameAttribute;
and you can use it directly:
MyChildControlNameFromXAMLNameAttribute.Visibility = Visibility.Hidden;

May be this , Give x:Name to your childControl
var childControl = (MyChildControlType)MyGridNameFromXAMLNameAttribute.FindName("MyChildControlNameFromXAMLNameAttribute");

Related

Align the text in center for multiple richtextbox in c#

I need to align the text center for multiple richtextbox.
I found the solution to align the single richtextbox.
EX:
richtextbox1.SelectAll();
richtectbox1.SelectionAlignment = HorizantalAlignment.Center;
I dont want to enter this for every textboxes.
How to do this for multiple richtextbox using loop?
You can look for all the controls who are of type RichTextBox and do whatever you need to do like this:
foreach (var thisControl in this.Controls.OfType<RichTextBox>())
{
thisControl.SelectAll();
thisControl.SelectionAlignment = HorizontalAlignment.Center;
}
In addition to CodingYoshi's answer, if the Rich Text Boxes don't have a single common parent (i.e. the TextBoxes are dispersed on GroupBoxes, Tabs, etc), then you'll need to recurse from the topmost common parent (possibly the form itself) in order to find the RichTextBoxes, using a technique such as this one here:
public IEnumerable<Control> GetAll(Control control, Type type)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAll(ctrl, type))
.Concat(controls)
.Where(c => c.GetType() == type);
}
You'll then be able to apply your alignment to all subordinate controls at any level from a given root coontrol (this is the root Form control in this example)
foreach (RichTextBox textBox in GetAll(this, typeof (RichTextBox)))
{
textBox.SelectAll();
textBox.SelectionAlignment = HorizontalAlignment.Center;
}
You need to create a list of RichTextBoxes, and then:
foreach(richtextbox in list)
{
t.SelectAll();
t.SelectionAlignment = HorizantalAlignment.Center;
}
You can also use [this] (How to get ALL child controls of a Windows Forms form of a specific type (Button/Textbox)?) post, to gather all your richtextboxes:
First you need to get all the child controls of the form into a list, and by changing the required property of each item in the list your objective can be met.
You can get all child controls by using a function like this:
public static IEnumerable<TControl> GetChildControls<TControl>(this Control control) where TControl : Control
{
var children = (control.Controls != null) ? control.Controls.OfType<TControl>() : Enumerable.Empty<TControl>();
return children.SelectMany(c => GetChildControls<TControl>(c)).Concat(children);
}
You can get all the RichText boxes like this
var richTextBoxes = this.GetChildControls<RichTextBox>();
foreach (RichTextBox rtb in richTextBoxes)
{
rtb.SelectionAlignment = HorizantalAlignment.Center;
}
Consider this as an idea, copy paste this code may have syntax errors.

Get only the groupBoxes from a winform

i made this code for get all the groupboxes from a winform and then take only the ones with a determinated name.
Control.ControlCollection controles = this.Controls;
GroupBox gBoxAux = new GroupBox();
List<GroupBox> gBoxes = new List<GroupBox>();
foreach (Control c in controles)
{
if (c.GetType() == typeof(GroupBox))
{
gBoxAux = (GroupBox)c;
gBoxes.Add(gBoxAux);
}
}
I don't know if there's a better way to do it instead of iterate over all the controls.
Thank you very much!
You can query that using Linq:
this.Controls.OfType<GroupbBox>().Where(x=> x.Name == "SomeName").ToList();
Well to find all groupboxes there is no better way than to iterate over all of them. But (for me) the code would look better with this:
List<GroupBox> gBoxes = this.Controls.OfType<GroupbBox>().ToList();
OfType<T> selects all elements of a sequence that are of that type.
Note that this only finds all groupboxes directly contained in this ControlCollection but not in sub-containers. You may want to collect the groupboxes recursively:
public IEnumerable<GroupBoxes> GetAllGroupBoxes(Control c)
{
return c.Controls.OfType<GroupBox>()
.Concat(c.Controls.OfType<Control>().SelectMany(GetAllGroupBoxes));
}
List<GroupBox> gBoxes = GetAllGroupBoxes(this).ToList();
To filter for a specific name you can use Where:
Controls.OfType<GroupBox>().Where(gb => gb.Name == "whatever")...

How to select a child from an UIElementCollection where a property = some value?

I have a UniformGrid with a number of Button's as Children. Each Button has a Tag with an ID, e.g. (dumbed down code):
MyUniformGrid.Children.Add(new Button {
Margin = new Thickness(5),
Tag = Query.GetUInt32("id"),
Width = 200
});
How can I select the child Button object with an ID of 87? (as a for instance)
Intellisense isn't popping up with the Linq methods when I type MyUniformGrid.Children. (after adding using System.Linq;).
Here you go:
var MyButton = MyUniformGrid.Children.
OfType<Button>().
Single(Child => Child.Tag != null && Child.Tag == 87);
Linq can't be run directly on MyUniformGrid.Children since UIElementCollection implements IEnumerable, not IEnumerable<T>. Therefore OfType<Button> is required.

WPF DataGrid actual ColumnHeaderHeight

When I set a WPF DataGrid's ColumnHeaderHeight to Auto (double.NaN), how do I get the actual rendered height of the column header?
I cannot seem to find the property in the DataGrid class.
You could get hold of it by searching through the visual tree for the DataGridColumnHeadersPresenter and reading its ActualHeight property.
var headersPresenter = FindVisualChild<DataGridColumnHeadersPresenter>(dataGrid);
double actualHeight = headersPresenter.ActualHeight;
Here's the FindVisualChild method. It could be implemented as an extension method as well.
public static T FindVisualChild<T>(DependencyObject current) where T : DependencyObject
{
if (current == null) return null;
int childrenCount = VisualTreeHelper.GetChildrenCount(current);
for (int i = 0; i < childrenCount ; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(current, i);
if (child is T) return (T)child;
T result = FindVisualChild<T>(child);
if (result != null) return result;
}
return null;
}
When I remember correctly, the property is an attached property - meaning the real value should be found on a DataGridColumn.
There is a separate class for the DataGridColumnHeader with the same name - see: http://msdn.microsoft.com/de-de/library/system.windows.controls.primitives.datagridcolumnheader(v=vs.110).aspx
This class can probably be gained through a single DataGridColumns "Header" property.
See: http://msdn.microsoft.com/en-us/library/system.windows.controls.datagridcolumn.header(v=vs.110).aspx
So I would grab the first column of the grid, convert it's Header property to DataGridColumnHeaderand read its actualheight attribute.
Please make sure to guard for the case that the Header attribute or ActualHeight is null - this can happen when the grid is build / refreshing or closing. I dimly remeber that there should be an event which is fired when the grid is rendered completely.

Updating string properties of an object using enumeration

I have a load of text boxes on an aspx page whose IDs are prefixed with 'txt' the rest of the ID has a corresponding property of the same name in a certain object. I want to be able to enumerate through these string properties and update them where a text box of the same name (with the prefix removed) is found. Any Ideas? I know by using a Dictionary I can get around the problem but it's not ideal.
You can do that using reflection:
MyObject data = new MyObject();
foreach (var pi in typeof(MyObject).GetProperties().Where(i =>
i.PropertyType.Equals(typeof(string)))
{
var control = FindControl("txt" + pi.Name) as ITextControl;
if (control != null)
pi.SetValue(data, control.Text, null);
}
You can work with the controls:
foreach (Control control in divXYZ.Controls)
if (control is TextBox)
((TextBox)control).Text = "whatever";
FindControl is another method you can use in your solution:
Control myControl = FindControl("txtYourID");
http://msdn.microsoft.com/en-us/library/486wc64h.aspx
just find all textbox controls on page and then fill coresponding properties using reflection.

Categories

Resources