Convert BeginInvoke Code From Winforms To Wpf - wpf

I have found out that ISynchronizeInvoke cannot be used in WPF after having tried to convert the following code unsuccessfully. Can anybody help?
private static void EVENT_R(Delegate #event, object[] data)
{
if (#event != null)
{
foreach (var A_C in #event.GetInvocationList())
{
var NewTp = (ISynchronizeInvoke)A_C.Target;
if (NewTp != null && NewTp.InvokeRequired)
{
NewTp.BeginInvoke(A_C, data);
}
else
{
A_C.DynamicInvoke(data);
}
}
}
}

If NewTp is a UIElement, then you need to cast to UIElement and call UIElement.Dispatcher.BeginInvoke:
var NewTp = (UIElement)A_C.Target;
if (NewTp != null)
{
NewTp.Dispatcher.BeginInvoke(A_C, data);
}

Related

XAM Data Grid change order of filter drop down list

Can I change the order of filter drop down list.
There is a blank option at the end of the list I've to put it at very first position.
To solve this I searched for the TreeView that is being displayed and reassociate the ItemSource at runtime. I have used RecordFilterDropDownOpening event of XAMDataGrid.
CODE:
void DataPresenter_RecordFilterDropDownOpening(object sender, Infragistics.Windows.DataPresenter.Events.RecordFilterDropDownOpeningEventArgs e)
{
RecordFilterTreeControl rftc = null;
try
{
rftc = (e.MenuItems[e.MenuItems.Count - 1] as FieldMenuDataItem).Header as RecordFilterTreeControl;
if (rftc != null)
{
rftc.Loaded += new RoutedEventHandler(rftc_Loaded);
}
}
catch (Exception ex)
{
LogInfo.LogToListeners(ex);
}
finally
{
rftc = null;
}
}
void rftc_Loaded(object sender, RoutedEventArgs e)
{
TreeView tv = null;
try
{
tv = Infragistics.Windows.Utilities.GetDescendantFromType(sender as DependencyObject, typeof(TreeView), false) as TreeView;
if (tv != null)
{
var newSource = new ObservableCollection<RecordFilterTreeItem>();
foreach (var item in tv.ItemsSource)
{
if (item is RecordFilterTreeItem)
{
newSource.Add(item as RecordFilterTreeItem);
}
}
if (newSource[newSource.Count - 1].DisplayText == "(Blanks)")
{
newSource.Move(newSource.Count - 1, 1);
}
tv.ItemsSource = newSource;// this will give a new itemsource to treeview
}
}
catch (Exception ex)
{
LogInfo.LogToListeners(ex);
}
finally
{
tv = null;
}
}
Result:

Can you replace DatePickerTextBox with a different TextBox in DatePicker and still get the validation functionality?

I replaced the DatePickerTextBox in the control template of DatePicker, and it no longer ensures a valid date value for the text entered. I tested different strings with a plain DatePickerTextBox, too, and it didn't validate them, so it must be some kind of interaction between DatePickerTextBox and DatePicker. Is there a way to get that interaction with a different TextBox control in the control template that isn't DatePickerTextBox, or will I have to recreate that validation in my own custom control?
Short explanation with answer:
In the OnApplyTemplate method of a custom TextBox control, I added:
public override void OnApplyTemplate()
{
LostFocus += OnLostFocus;
base.OnApplyTemplate();
}
And then the method:
private void OnLostFocus(object sender, RoutedEventArgs e)
{
if (!Text.Equals(oldText))
{
DateTime d;
if (!DateTime.TryParse(Text, out d))
{
Text = oldText;
}
}
oldText = Text;
}
Long explanation of why it doesn't work in the control template if you replace DatePickerTextBox:
I poked around in the reference source and discovered the following:
In the OnApplyTemplate method for DatePicker, some handlers are added, specifically for a DatePickerTextBox, which it will not apply if it doesn't find one (which explains why DatePickerTextBox doesn't validate on its own, either - DatePicker adds the handlers, not DatePickerTextBox):
_textBox = GetTemplateChild(ElementTextBox) as DatePickerTextBox;
if (this.SelectedDate == null)
{
SetWaterMarkText();
}
if (_textBox != null)
{
_textBox.AddHandler(TextBox.KeyDownEvent, new KeyEventHandler(TextBox_KeyDown), true);
_textBox.AddHandler(TextBox.TextChangedEvent, new TextChangedEventHandler(TextBox_TextChanged), true);
_textBox.AddHandler(TextBox.LostFocusEvent, new RoutedEventHandler(TextBox_LostFocus), true);
if (this.SelectedDate == null)
{
if (!string.IsNullOrEmpty(this._defaultText))
{
_textBox.Text = this._defaultText;
SetSelectedDate();
}
}
else
{
_textBox.Text = this.DateTimeToString((DateTime)this.SelectedDate);
}
}
So, tracking it down(here comes the fun part)...
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
SetSelectedDate();
}
Then:
private void SetSelectedDate()
{
if (this._textBox != null)
{
if (!string.IsNullOrEmpty(this._textBox.Text))
{
string s = this._textBox.Text;
if (this.SelectedDate != null)
{
// If the string value of the SelectedDate and the TextBox string value are equal,
// we do not parse the string again
// if we do an extra parse, we lose data in M/d/yy format
// ex: SelectedDate = DateTime(1008,12,19) but when "12/19/08" is parsed it is interpreted as DateTime(2008,12,19)
string selectedDate = DateTimeToString(this.SelectedDate.Value);
if (string.Compare(selectedDate, s, StringComparison.Ordinal) == 0)
{
return;
}
}
DateTime? d = SetTextBoxValue(s);
if (!this.SelectedDate.Equals(d))
{
this.SetCurrentValueInternal(SelectedDateProperty, d);
this.SetCurrentValueInternal(DisplayDateProperty, d);
}
}
else
{
if (this.SelectedDate.HasValue)
{
this.SetCurrentValueInternal(SelectedDateProperty, (DateTime?)null);
}
}
}
else
{
DateTime? d = SetTextBoxValue(_defaultText);
if (!this.SelectedDate.Equals(d))
{
this.SetCurrentValueInternal(SelectedDateProperty, d);
}
}
}
The important thing there is the call to SetTextBoxValue:
private DateTime? SetTextBoxValue(string s)
{
if (string.IsNullOrEmpty(s))
{
SafeSetText(s);
return this.SelectedDate;
}
else
{
DateTime? d = ParseText(s);
if (d != null)
{
SafeSetText(this.DateTimeToString((DateTime)d));
return d;
}
else
{
// If parse error:
// TextBox should have the latest valid selecteddate value:
if (this.SelectedDate != null)
{
string newtext = this.DateTimeToString((DateTime)this.SelectedDate);
SafeSetText(newtext);
return this.SelectedDate;
}
else
{
SetWaterMarkText();
return null;
}
}
}
}
And the important thing there is the call to ParseText:
private DateTime? ParseText(string text)
{
DateTime newSelectedDate;
// TryParse is not used in order to be able to pass the exception to the TextParseError event
try
{
newSelectedDate = DateTime.Parse(text, DateTimeHelper.GetDateFormat(DateTimeHelper.GetCulture(this)));
if (Calendar.IsValidDateSelection(this._calendar, newSelectedDate))
{
return newSelectedDate;
}
else
{
DatePickerDateValidationErrorEventArgs dateValidationError = new DatePickerDateValidationErrorEventArgs(new ArgumentOutOfRangeException("text", SR.Get(SRID.Calendar_OnSelectedDateChanged_InvalidValue)), text);
OnDateValidationError(dateValidationError);
if (dateValidationError.ThrowException)
{
throw dateValidationError.Exception;
}
}
}
catch (FormatException ex)
{
DatePickerDateValidationErrorEventArgs textParseError = new DatePickerDateValidationErrorEventArgs(ex, text);
OnDateValidationError(textParseError);
if (textParseError.ThrowException && textParseError.Exception != null)
{
throw textParseError.Exception;
}
}
return null;
}
The last two methods have the validation I was looking for. If ParseText returns null, then SetTextBoxValue reverts the value in the text box back to its previous value. Because DatePicker is the control that adds the handler, you won't get the validation outside of DatePicker. Since DatePicker looks specifically for a DatePickerTextBox named "PART_TextBox" (that is what the ElementTextBox string is), a DatePickerTextBox must be used, or the handler will not be applied (since _textbox will be null).

Export to Excel in silverlight 5

I use the following code for export to excel,it works fine,but how can I change it to xport directly to .xlsx file not xml file,also I do not want to use automation because it works very slow.
Thanks.
public static class DataGridxtensions
{
public static void Export(this DataGrid dg)
{
ExportDataGrid(dg);
}
public static void ExportDataGrid(DataGrid dGrid)
{
SaveFileDialog objSFD = new SaveFileDialog() { DefaultExt = "xml", Filter = "Excel XML (*.xml)|*.xml", FilterIndex = 1 };
if (objSFD.ShowDialog() == true)
{
string strFormat = objSFD.SafeFileName.Substring(objSFD.SafeFileName.IndexOf('.') + 1).ToUpper();
StringBuilder strBuilder = new StringBuilder();
if (dGrid.ItemsSource == null) return;
List<string> lstFields = new List<string>();
if (dGrid.HeadersVisibility == DataGridHeadersVisibility.Column || dGrid.HeadersVisibility == DataGridHeadersVisibility.All)
{
foreach (DataGridColumn dgcol in dGrid.Columns)
lstFields.Add(FormatField(dgcol.Header.ToString(), strFormat, false));
BuildStringOfRow(strBuilder, lstFields, strFormat);
}
foreach (object data in dGrid.ItemsSource)
{
lstFields.Clear();
foreach (DataGridColumn col in dGrid.Columns)
{
string strValue = "";
Binding objBinding = null;
if (col is DataGridBoundColumn)
objBinding = (col as DataGridBoundColumn).Binding;
if (col is DataGridTemplateColumn)
{
//This is a template column... let us see the underlying dependency object
DependencyObject objDO = (col as DataGridTemplateColumn).CellTemplate.LoadContent();
FrameworkElement oFE = (FrameworkElement)objDO;
FieldInfo oFI = oFE.GetType().GetField("TextProperty");
if (oFI != null)
{
if (oFI.GetValue(null) != null)
{
if (oFE.GetBindingExpression((DependencyProperty)oFI.GetValue(null)) != null)
objBinding = oFE.GetBindingExpression((DependencyProperty)oFI.GetValue(null)).ParentBinding;
}
}
}
if (objBinding != null)
{
if (objBinding.Path.Path != "")
{
PropertyInfo pi = data.GetType().GetProperty(objBinding.Path.Path);
if (pi != null) strValue = pi.GetValue(data, null).ToString();
}
if (objBinding.Converter != null)
{
if (strValue != "")
strValue = objBinding.Converter.Convert(strValue, typeof(string), objBinding.ConverterParameter, objBinding.ConverterCulture).ToString();
else
strValue = objBinding.Converter.Convert(data, typeof(string), objBinding.ConverterParameter, objBinding.ConverterCulture).ToString();
}
}
lstFields.Add(FormatField(strValue, strFormat, true));
}
BuildStringOfRow(strBuilder, lstFields, strFormat);
}
StreamWriter sw = new StreamWriter(objSFD.OpenFile());
if (strFormat == "XML")
{
//Let us write the headers for the Excel XML
sw.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
sw.WriteLine("<?mso-application progid=\"Excel.Sheet\"?>");
sw.WriteLine("<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\">");
sw.WriteLine("<DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">");
sw.WriteLine("<Author>Arasu Elango</Author>");
sw.WriteLine("<Created>" + DateTime.Now.ToLocalTime().ToLongDateString() + "</Created>");
sw.WriteLine("<LastSaved>" + DateTime.Now.ToLocalTime().ToLongDateString() + "</LastSaved>");
sw.WriteLine("<Company>Atom8 IT Solutions (P) Ltd.,</Company>");
sw.WriteLine("<Version>12.00</Version>");
sw.WriteLine("</DocumentProperties>");
sw.WriteLine("<Worksheet ss:Name=\"Export\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\">");
sw.WriteLine("<Table>");
}
sw.Write(strBuilder.ToString());
if (strFormat == "XML")
{
sw.WriteLine("</Table>");
sw.WriteLine("</Worksheet>");
sw.WriteLine("</Workbook>");
}
sw.Close();
}
}
private static void BuildStringOfRow(StringBuilder strBuilder, List<string> lstFields, string strFormat)
{
switch (strFormat)
{
case "XML":
strBuilder.AppendLine("<Row>");
strBuilder.AppendLine(String.Join("\r\n", lstFields.ToArray()));
strBuilder.AppendLine("</Row>");
break;
case "CSV":
strBuilder.AppendLine(String.Join(",", lstFields.ToArray()));
break;
}
}
private static string FormatField(string data, string format, bool isNumber)
{
switch (format)
{
case "XML":
if (isNumber)
{
return String.Format("<Cell><Data ss:Type=\"Number\">{0}</Data></Cell>", data);
}
else
{
return String.Format("<Cell><Data ss:Type=\"String\">{0}</Data></Cell>", data);
}
case "CSV":
return String.Format("\"{0}\"", data.Replace("\"", "\"\"\"").Replace("\n", "").Replace("\r", ""));
}
return data;
}
}
I can think of two options.
First, there are several component vendors who have solved this problem. There's SyncFusion's XlsIo, and Infragistics, and Telerik (looks like they have .xls only).
If the financial cost is too high, then you might consider OpenXml. The learning curve would be a bit steeper, and you can't use it directly from Silverlight -- you'd have to make the server convert your data to an .xlsx file and then your client would save the results. Also, you'll need to be aware of this issue.
But, it is free. I have had some success reading Excel files with it. I think this might be the NuGet package you'd need, or you can download an installer.
Fortunately for me, my employer paid for the first option above when we needed to create an .xlsx file. :-)
Yup office Automation way to slow! I had to change to, I used code from
http://www.codeproject.com/Articles/45731/Export-Silverlight-DataGrid-to-Excel-XML-CSV?msg=4829021#xx4829021xx

wpf how to get all TextBoxes in wpf application [duplicate]

I'm looking for a way to find all controls on Window by their type,
for example: find all TextBoxes, find all controls implementing specific interface etc.
This should do the trick:
public static IEnumerable<T> FindVisualChilds<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj == null) yield return (T)Enumerable.Empty<T>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject ithChild = VisualTreeHelper.GetChild(depObj, i);
if (ithChild == null) continue;
if (ithChild is T t) yield return t;
foreach (T childOfChild in FindVisualChilds<T>(ithChild)) yield return childOfChild;
}
}
then you enumerate over the controls like so
foreach (TextBlock tb in FindVisualChildren<TextBlock>(window))
{
// do something with tb here
}
This is the easiest way:
IEnumerable<myType> collection = control.Children.OfType<myType>();
where control is the root element of the window.
EDIT - As pointed out in the comments. This only goes one level deep. See the accepted answer for an option that goes deeper.
I adapted #Bryce Kahle's answer to follow #Mathias Lykkegaard Lorenzen's suggestion and use LogicalTreeHelper.
Seems to work okay. ;)
public static IEnumerable<T> FindLogicalChildren<T> ( DependencyObject depObj ) where T : DependencyObject
{
if( depObj != null )
{
foreach( object rawChild in LogicalTreeHelper.GetChildren( depObj ) )
{
if( rawChild is DependencyObject )
{
DependencyObject child = (DependencyObject)rawChild;
if( child is T )
{
yield return (T)child;
}
foreach( T childOfChild in FindLogicalChildren<T>( child ) )
{
yield return childOfChild;
}
}
}
}
}
(It still won't check tab controls or Grids inside GroupBoxes as mentioned by #Benjamin Berry & #David R respectively.)
(Also followed #noonand's suggestion & removed the redundant child != null)
Use the helper classes VisualTreeHelper or LogicalTreeHelper depending on which tree you're interested in. They both provide methods for getting the children of an element (although the syntax differs a little). I often use these classes for finding the first occurrence of a specific type, but you could easily modify it to find all objects of that type:
public static DependencyObject FindInVisualTreeDown(DependencyObject obj, Type type)
{
if (obj != null)
{
if (obj.GetType() == type)
{
return obj;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject childReturn = FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type);
if (childReturn != null)
{
return childReturn;
}
}
}
return null;
}
I found that the line, VisualTreeHelper.GetChildrenCount(depObj);, used in several examples above does not return a non-zero count for GroupBoxes, in particular, where the GroupBox contains a Grid, and the Grid contains children elements. I believe this may be because the GroupBox is not allowed to contain more than one child, and this is stored in its Content property. There is no GroupBox.Children type of property. I am sure I did not do this very efficiently, but I modified the first "FindVisualChildren" example in this chain as follows:
public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
int depObjCount = VisualTreeHelper.GetChildrenCount(depObj);
for (int i = 0; i <depObjCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
if (child is GroupBox)
{
GroupBox gb = child as GroupBox;
Object gpchild = gb.Content;
if (gpchild is T)
{
yield return (T)child;
child = gpchild as T;
}
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
Here is yet another, compact version, with the generics syntax:
public static IEnumerable<T> FindLogicalChildren<T>(DependencyObject obj) where T : DependencyObject
{
if (obj != null) {
if (obj is T)
yield return obj as T;
foreach (DependencyObject child in LogicalTreeHelper.GetChildren(obj).OfType<DependencyObject>())
foreach (T c in FindLogicalChildren<T>(child))
yield return c;
}
}
To get a list of all childs of a specific type you can use:
private static IEnumerable<DependencyObject> FindInVisualTreeDown(DependencyObject obj, Type type)
{
if (obj != null)
{
if (obj.GetType() == type)
{
yield return obj;
}
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
foreach (var child in FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type))
{
if (child != null)
{
yield return child;
}
}
}
}
yield break;
}
Small change to the recursion to so you can for example find the child tab control of a tab control.
public static DependencyObject FindInVisualTreeDown(DependencyObject obj, Type type)
{
if (obj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child.GetType() == type)
{
return child;
}
DependencyObject childReturn = FindInVisualTreeDown(child, type);
if (childReturn != null)
{
return childReturn;
}
}
}
return null;
}
And this is how it works upwards
private T FindParent<T>(DependencyObject item, Type StopAt) where T : class
{
if (item is T)
{
return item as T;
}
else
{
DependencyObject _parent = VisualTreeHelper.GetParent(item);
if (_parent == null)
{
return default(T);
}
else
{
Type _type = _parent.GetType();
if (StopAt != null)
{
if ((_type.IsSubclassOf(StopAt) == true) || (_type == StopAt))
{
return null;
}
}
if ((_type.IsSubclassOf(typeof(T)) == true) || (_type == typeof(T)))
{
return _parent as T;
}
else
{
return FindParent<T>(_parent, StopAt);
}
}
}
}
Do note that using the VisualTreeHelper does only work on controls that derive from Visual or Visual3D. If you also need to inspect other elements (e.g. TextBlock, FlowDocument etc.), using VisualTreeHelper will throw an exception.
Here's an alternative that falls back to the logical tree if necessary:
http://www.hardcodet.net/2009/06/finding-elements-in-wpf-tree-both-ways
My version for C++/CLI
template < class T, class U >
bool Isinst(U u)
{
return dynamic_cast< T >(u) != nullptr;
}
template <typename T>
T FindVisualChildByType(Windows::UI::Xaml::DependencyObject^ element, Platform::String^ name)
{
if (Isinst<T>(element) && dynamic_cast<Windows::UI::Xaml::FrameworkElement^>(element)->Name == name)
{
return dynamic_cast<T>(element);
}
int childcount = Windows::UI::Xaml::Media::VisualTreeHelper::GetChildrenCount(element);
for (int i = 0; i < childcount; ++i)
{
auto childElement = FindVisualChildByType<T>(Windows::UI::Xaml::Media::VisualTreeHelper::GetChild(element, i), name);
if (childElement != nullptr)
{
return childElement;
}
}
return nullptr;
};
#Bryce, really nice answer.
VB.NET version:
Public Shared Iterator Function FindVisualChildren(Of T As DependencyObject)(depObj As DependencyObject) As IEnumerable(Of T)
If depObj IsNot Nothing Then
For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(depObj) - 1
Dim child As DependencyObject = VisualTreeHelper.GetChild(depObj, i)
If child IsNot Nothing AndAlso TypeOf child Is T Then
Yield DirectCast(child, T)
End If
For Each childOfChild As T In FindVisualChildren(Of T)(child)
Yield childOfChild
Next
Next
End If
End Function
Usage (this disables all TextBoxes in a window):
For Each tb As TextBox In FindVisualChildren(Of TextBox)(Me)
tb.IsEnabled = False
Next
For this and more use cases you can add flowing extension method to your library:
public static List<DependencyObject> FindAllChildren(this DependencyObject dpo, Predicate<DependencyObject> predicate)
{
var results = new List<DependencyObject>();
if (predicate == null)
return results;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dpo); i++)
{
var child = VisualTreeHelper.GetChild(dpo, i);
if (predicate(child))
results.Add(child);
var subChildren = child.FindAllChildren(predicate);
results.AddRange(subChildren);
}
return results;
}
Example for your case:
var children = dpObject.FindAllChildren(child => child is TextBox);
I wanted to add a comment but I have less than 50 pts so I can only "Answer".
Be aware that if you use the "VisualTreeHelper" method to retrieve XAML "TextBlock" objects then it will also grab XAML "Button" objects. If you re-initialize the "TextBlock" object by writing to the Textblock.Text parameter then you will no longer be able to change the Button text using the Button.Content parameter. The Button will permanently show the text written to it from the Textblock.Text write action (from when it was retrieved --
foreach (TextBlock tb in FindVisualChildren<TextBlock>(window))
{
// do something with tb here
tb.Text = ""; //this will overwrite Button.Content and render the
//Button.Content{set} permanently disabled.
}
To work around this, you can try using a XAML "TextBox" and add methods (or Events) to mimic a XAMAL Button. XAML "TextBox" is not gathered by a search for "TextBlock".
For some reason, none of the answers posted here helped me to get all controls of given type contained in a given control in my MainWindow.
I needed to find all menu items in one menu to iterate them. They were not all direct descendants of the menu, so i managed to collect only the first lilne of them using any of the code above.
This extension method is my solution for the problem for anyone who will continue to read all the way down here.
public static void FindVisualChildren<T>(this ICollection<T> children, DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
var brethren = LogicalTreeHelper.GetChildren(depObj);
var brethrenOfType = LogicalTreeHelper.GetChildren(depObj).OfType<T>();
foreach (var childOfType in brethrenOfType)
{
children.Add(childOfType);
}
foreach (var rawChild in brethren)
{
if (rawChild is DependencyObject)
{
var child = rawChild as DependencyObject;
FindVisualChildren<T>(children, child);
}
}
}
}
Hope it helps.
I found it easier without Visual Tree Helpers:
foreach (UIElement element in MainWindow.Children) {
if (element is TextBox) {
if ((element as TextBox).Text != "")
{
//Do something
}
}
};
The accepted answer returns the discovered elements more or less unordered, by following the first child branch as deep as possible, while yielding the discovered elements along the way, before backtracking and repeating the steps for not yet parsed tree branches.
If you need the descendent elements in descending order, where the direct children will be yielded first, then their children and so on, the following algorithm will work:
public static IEnumerable<T> GetVisualDescendants<T>(DependencyObject parent, bool applyTemplates = false)
where T : DependencyObject
{
if (parent == null || !(child is Visual || child is Visual3D))
yield break;
var descendants = new Queue<DependencyObject>();
descendants.Enqueue(parent);
while (descendants.Count > 0)
{
var currentDescendant = descendants.Dequeue();
if (applyTemplates)
(currentDescendant as FrameworkElement)?.ApplyTemplate();
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(currentDescendant); i++)
{
var child = VisualTreeHelper.GetChild(currentDescendant, i);
if (child is Visual || child is Visual3D)
descendants.Enqueue(child);
if (child is T foundObject)
yield return foundObject;
}
}
}
The resulting elements will be ordered from nearest to farthest.
This will be useful e.g. if you are looking for the nearest child element of some type and condition:
var foundElement = GetDescendants<StackPanel>(someElement)
.FirstOrDefault(o => o.SomeProperty == SomeState);

Toolstrip tablelayout style

using c# 2008 winforms.
I may be missing something obvious here, but can anyone help me out with using tablelayout style in a toolstrip.
I was expecting it would be similar to using a tablelayout control in the designer, and being able to use the desinger to assign controls in the toolstrip to a grid tablelayout of some kind, but none of these properties are visible.
When i set the style to tablelayout, and add controls, they just end up in a vertical line, and there dont seem to be any properties to set a tablelayout style grid, and then allocate the controls to a square in the grid.
I was hoping this could all be done in the desinger.
Could anyone please advise
thanks
You can create an extender provider as explained in a MSDN blog article by jfoscoding: Using TableLayout in ToolStrip in the Designer.
Here is the (slightly reformatted) code from that page:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
namespace Microsoft.Samples {
[ProvideProperty("ColumnSpan", typeof(ToolStripItem))]
[ProvideProperty("RowSpan", typeof(ToolStripItem))]
[ProvideProperty("Anchor", typeof(ToolStripItem))]
[ProvideProperty("Dock", typeof(ToolStripItem))]
class TableLayoutToolStrip : ToolStrip, IExtenderProvider {
public TableLayoutToolStrip() {
this.LayoutStyle = ToolStripLayoutStyle.Table;
RowCount = 3;
ColumnCount = 3;
}
private TableLayoutSettings TableLayoutSettings {
get {
return LayoutSettings as TableLayoutSettings;
}
}
[DefaultValue(3)]
public int RowCount {
get {
if (TableLayoutSettings != null) {
return TableLayoutSettings.RowCount;
}
return -1;
}
set {
if (TableLayoutSettings != null) {
TableLayoutSettings.RowCount = value;
}
}
}
[DefaultValue(3)]
public int ColumnCount {
get {
if (TableLayoutSettings != null) {
return TableLayoutSettings.ColumnCount;
}
return -1;
}
set {
if (TableLayoutSettings != null) {
TableLayoutSettings.ColumnCount = value;
}
}
}
public override System.Drawing.Size GetPreferredSize(System.Drawing.Size proposedSize) {
// be friendly if there's no items left to
// pin the control open.
if (Items.Count == 0) {
return this.DefaultSize;
}
return base.GetPreferredSize(proposedSize);
}
[DefaultValue(1)]
[DisplayName("ColumnSpan")]
public int GetColumnSpan(object target) {
return TableLayoutSettings.GetColumnSpan(target);
}
public void SetColumnSpan(object target, int value) {
TableLayoutSettings.SetColumnSpan(target, value);
}
[DefaultValue(1)]
[DisplayName("RowSpan")]
public int GetRowSpan(object target) {
if (TableLayoutSettings != null) {
return TableLayoutSettings.GetRowSpan(target);
}
return 1;
}
public void SetRowSpan(object target, int value) {
if (TableLayoutSettings != null) {
TableLayoutSettings.SetRowSpan(target, value);
}
}
[Editor(typeof(System.ComponentModel.Design.CollectionEditor), typeof(System.Drawing.Design.UITypeEditor))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public TableLayoutColumnStyleCollection ColumnStyles {
get {
if (TableLayoutSettings != null) {
return TableLayoutSettings.ColumnStyles;
}
return null;
}
}
[Editor(typeof(System.ComponentModel.Design.CollectionEditor), typeof(System.Drawing.Design.UITypeEditor))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public TableLayoutRowStyleCollection RowStyles {
get {
if (TableLayoutSettings != null) {
return TableLayoutSettings.RowStyles;
}
return null;
}
}
[DisplayName("Anchor")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public AnchorStyles GetAnchor(object target) {
ToolStripItem tsi = target as ToolStripItem;
return (tsi != null) ? tsi.Anchor : AnchorStyles.None;
}
public void SetAnchor(object target, AnchorStyles value) {
ToolStripItem tsi = target as ToolStripItem;
if (tsi != null) {
tsi.Anchor = value;
}
}
[DisplayName("Dock")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DockStyle GetDock(object target) {
ToolStripItem tsi = target as ToolStripItem;
return (tsi != null) ? tsi.Dock : DockStyle.None;
}
public void SetDock(object target, DockStyle value) {
ToolStripItem tsi = target as ToolStripItem;
if (tsi != null) {
tsi.Dock = value;
}
}
bool IExtenderProvider.CanExtend(object extendee) {
ToolStripItem tsi = extendee as ToolStripItem;
return tsi != null && tsi.Owner == this;
}
}
}

Resources