How to take Children of a ListView in Code-Behind - c#

I have a ListView with some buttons(created in code-behind). I want to take all theese buttons and place them in a variable:
Button tg = (Button)sender;
ListView st = (ListView) tg.Parent;
var a = st.Children(this function doesn't work for ListView, but it's similar to what should resolve my problem) ;
foreach(Button btn in a)

Since ListView uses data virtualization to have a better performance. See https://learn.microsoft.com/en-us/windows/uwp/debug-test-perf/listview-and-gridview-data-optimization. So the buttons may not rendered when they are not in your viewport. This causes you can't get all buttons of your ListView.
But through some trick, we can disable ListView's data virtualization. Note that doing this may causes your app react slow when you have a mount of items in your ListView.
Suppose you want this way.
First, you need to modify ListView's ItemsPanel to StackPanel, according to doc, https://learn.microsoft.com/en-us/windows/uwp/debug-test-perf/optimize-gridview-and-listview#ui-virtualization.
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
Second, you can get all buttons using a helper function, it returns a List of your controls finded.
public static List<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
List<T> list = new List<T>();
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
list.Add((T)child);
}
List<T> childItems = FindVisualChildren<T>(child);
if (childItems != null && childItems.Count() > 0)
{
foreach (var item in childItems)
{
list.Add(item);
}
}
}
}
return list;
}
Third, you can use it this way.
var listButtons = FindVisualChildren<Button>(listView);
foreach (var btn in listButtons )
{
//to do
}
Done!!!

Related

How to know whether VerticalScrollbar of list view is visible if its visibility is 'Auto' in c# wpf?

I have a listview(checked list)
- which has checkbox on the header to select all items in the list
Now, I have concern that user should not be able to select the items which are not visible in the list (Hidden due to VerticalScrollBar)
I have 2 solutions for this problem
Select only those items which are visible in the list (which seems difficult)
Disable select all checkbox if there is vertical scroll bar visible
I am going for the 2nd solution in which
I need to know whether verticalScrollBar is appeared or not.
How to know whether VerticalScrollbar of ListView is visible if its visibility is 'Auto'?
You can use ScrollViewer
ScrollViewer sv = FindVisualChild<ScrollViewer>(myListView);
Visibility VerticalScrollbarVisibility = sv .ComputedVerticalScrollBarVisibility;
FindVisualChild implementation example from MSDN
private childItem FindVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is childItem)
return (childItem)child;
else
{
childItem childOfChild = FindVisualChild<childItem>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}

How to access controls inside an ItemTemplate

Using Windows Phone 8, C#.
What I've done is basically done is edited the pivot item. I've named it MainPivot and inside that I've edited the Pivot Item Title and added a TextBlock inside it called PivotTitletxt. XAML for that is:
<DataTemplate x:Key="DataTemplate3">
<TextBlock x:Name="PivotTitletxt" Height="34" TextWrapping="Wrap" Text="{Binding}" Width="447"/>
</DataTemplate>
How can I access this e.g. when setting opacity or changing foreground? so that I can use it on my MainPage like e.g. PivotTitletxt.Opacity = 30; ...
Thanks!
The link #Sankarann gave you is a pretty good example.
I'll try to put it on your scenario:
Your MainPivot has PivotItems right? So What you have to do on the Loaded event is:
var _mainPivot = MainPivot as Pivot
foreach (var _pivotItem in _mainPivot.Items)
{
var _container = _mainPivot.ItemContainerGenerator.ContainerFromItem(_pivotItem);
var _children = AllChildren(_container)
var _name = "PivotTitletxt";
var _control = (TextBlock)_Children.first(x=>x.Name == _name);
_control.Opacity = 30;
}
Then copy the AllChildren method exactly as the it is in the site.
The code above, might have a few adjustments because I've done it without VS...
Hope it helps.
Regards,
============ new answer ==============
Find all controls in WPF Window by type
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
Then try :
TextBlock xx = FindVisualChildren<TextBlock>(mainPivot).FirsOrDefault(x=>x.name=="PivotTitletxt");
if(xx!=null)
xx.opacity = 30
Once again, this come might need some correction...i'm doing it by heart, without VS.
Try it out

Get Children from ListBox can't get children that haven't been viewed

I've got a listbox in WPF like the following XAML. It's full of ListBoxItems that have a checkbox and a label inside of them. One of my items at the top is a "select all" option. When I click the select all option, I have a handler that iterates through all listbox items and it's supposed to check all the checkboxes on all the other listbox children. The problem is that it's only doing the visible children and when it hits the non-visible listboxitems, the VisualTreeHelper seems to be returning null when looking for objects of a specific type (like CheckBox). It seems that VisualTreeHelper seems to be problematic here. Am I using it wrong? Any help appreciated. One other detail - if I scroll and view all listboxitems at least once, it works fine.
mj
XAML - A simple listbox with a ton of children (only the 1st child displayed for brevity)
<ListBox Grid.Row="0" Margin="0,0,0,0" Name="CharacterListBox">
<ListBoxItem>
<StackPanel Orientation="Horizontal">
<CheckBox HorizontalAlignment="Center" VerticalAlignment="Center" Click="AllCharactersClicked"></CheckBox>
<Label Padding="5">All Characters</Label>
</StackPanel>
</ListBoxItem>
C# - Two functions, the first is a helper method which walks the object tree using VisualTreeHelper (I found this on some website). The second function is the click handler for the "select all" listboxitem. It iterates through all children and attempts to check all checkboxes.
private T FindControlByType<T>(DependencyObject container, string name) where T : DependencyObject
{
T foundControl = null;
//for each child object in the container
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(container); i++)
{
//is the object of the type we are looking for?
if (VisualTreeHelper.GetChild(container, i) is T && (VisualTreeHelper.GetChild(container, i).GetValue(FrameworkElement.NameProperty).Equals(name) || name == null))
{
foundControl = (T)VisualTreeHelper.GetChild(container, i);
break;
}
//if not, does it have children?
else if (VisualTreeHelper.GetChildrenCount(VisualTreeHelper.GetChild(container, i)) > 0)
{
//recursively look at its children
foundControl = FindControlByType<T>(VisualTreeHelper.GetChild(container, i), name);
if (foundControl != null)
break;
}
}
return foundControl;
}
private void AllCharactersClicked(object sender, RoutedEventArgs e)
{
MainWindow.Instance.BadChars.Clear();
int count = 0;
foreach (ListBoxItem item in CharacterListBox.Items)
{
CheckBox cb = FindControlByType<CheckBox>(item, null);
Label l = FindControlByType<Label>(item, null);
if (cb != null && l != null)
{
count++;
cb.IsChecked = true;
if (cb.IsChecked == true)
{
string sc = (string)l.Content;
if (sc.Length == 1)
{
char c = Char.Parse(sc);
MainWindow.Instance.BadChars.Add(c);
}
}
}
}
}
Those visual tree walking methods floating around all over the place are a plague. You should almost never need any of that.
Just bind the ItemsSource to a list of objects containing properties for the CheckBoxes, create a data template (ItemTemplate) and bind that property to the CheckBox. In code just iterate over the collection bound to ItemsSource and set the porperty.

TreeViewItem and null value

Not sure it is me after a long day of work ... or something is different in WPF type trees. I'm adding data to a tree and then when it is a parent node need to add its children but SelectedItem is always null!
any comment or direction would be helpful.
Thanks.
XAML:
<TreeView x:Name="TreeView1" Grid.Row="0">
</TreeView>
Code:
TreeView myTree = FindChild<TreeView>(Application.Current.MainWindow, "TreeView1");
myTree.Items.Add(ObjEmployee.Tag);
TreeViewItem tvi = (TreeViewItem) myTree.SelectedItem;
//my assumption was that when an item is added to tree most recent used node will be selected but it seems something is avoiding it or maybe works in a different way.
You should post some code snippet .. I do not understand what you need.
If you are using Hierarchical Template ( http://msdn.microsoft.com/en-us/library/ms742521.aspx )
The object of the SelectIedtem will be one of the data you put in ItemsSource
Otherwise, the "SelectedItem" can be any type of visual component that you put inside the treeview.
var treeItem = myTree.SelectedItem;
if (treeItem != null)
treeitem.GetType().Name;
Normally using TreeViewItem inside the treeview, all objects are in treeViewItem.Items
(Edit) You can try this:
var result = FindVisualChildren<TreeViewItem>(treeView);
foreach (var item in result)
{
if (item.IsSelected)
{
....
}
}
and
public static IEnumerable<T> FindVisualChildren<T>(FrameworkElement depObj) where T : FrameworkElement
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
FrameworkElement child = (FrameworkElement)VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}

WPF TreeView Scrolled to Bottom automatically?

WPF default TreeView is scrolled to bottom of the node automatically where as we need to show the top view of the tree view. How to do that?
Also I could not get the scroll viewer by walking down the Visual Tree.
Preselect top node and call TreeViewItem.BringIntoView method on selection changed event. Call TreeView.ItemContainerGenerator.ContainerFromItem(e.NewValue) to get hold of the TreeViewItem.
This code is very rough.
The key to getting the TreeViewItem.BringIntoView() to get an item to the top, is to first scroll the TreeView to the bottom rather than the top.
To do this, we need to access the ScrollViewer inside the TreeView's control template first. Lots of messing around IMO, that should have been provided in the framework from the outset.
Your item control in this case, should be your TreeViewItem that you are trying to get to the top.
The uxTree control is the TreeView.
item.IsSelected = true;
ScrollViewer scroller = (ScrollViewer)this.FindVisualChildElement(this.uxTree, typeof(ScrollViewer));
scroller.ScrollToBottom();
item.BringIntoView();
private FrameworkElement FindVisualChildElement(DependencyObject element, Type childType)
{
int count = VisualTreeHelper.GetChildrenCount(element);
for (int i = 0; i < count; i++)
{
var dependencyObject = VisualTreeHelper.GetChild(element, i);
var fe = (FrameworkElement)dependencyObject;
if (fe.GetType() == childType)
{
return fe;
}
FrameworkElement ret = null;
if (fe.GetType().Equals(typeof(ScrollViewer)))
{
ret = FindVisualChildElement((fe as ScrollViewer).Content as FrameworkElement, childType);
}
else
{
ret = FindVisualChildElement(fe, childType);
}
if (ret != null)
{
return ret;
}
}
return null;
}

Categories

Resources