How to access controls inside an ItemTemplate - c#

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

Related

How to take Children of a ListView in Code-Behind

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!!!

Capture RichTextBlock Hyperlink events

I'm trying to capture the click event of Hyperlinks inside a dynamically generated RichTextBlock.
I'm dynamically generating the contents of a richtextblock and then applying them with XamlReader. The content can vary quite a bit, so I can't manually parse the xaml and hook up events at that point.
My basic idea is to, once the richtextblock is loaded, find all Hyperlinks in it and hook up their click event there. This is my current code:
public class HookUpEvents()
{
foreach (var child in FindVisualChildren<Hyperlink>(richtxtblock))
{
child.Click += MyFunction;
}
}
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;
}
}
}
}
Obviously, it isn't working. It looks like the FindVisualChildren function isn't returning any Hyperlinks. Any ideas on how I can achieve this?
Well, I'm sure late to the party, but RichTextBlock won't place his Blocks and their Inlines in VisualTree most of the time. To find all Inline-based elements (Run,Span,Bold etc.) you will need to loop through all content, by visiting each Block and subsequent Inline's. I would suggest something like this:
public static IEnumerable<T> GetAllTextElements<T>(this RichTextBlock rtb) where T : TextElement
{
var result = new List<T>();
var blocks = rtb.Blocks;
foreach (var block in blocks)
{
if (block is T)
{
result.Add(block as T);
continue;
}
var inlines = ((Paragraph)block).Inlines;
var res = TraverseInline<T>(inlines);
if (res != null && res.Any())
result.AddRange(res);
}
return result;
}
private static IEnumerable<T> TraverseInline<T>(IEnumerable<Inline> inlines) where T : TextElement
{
var result = new List<T>();
foreach (var item in inlines)
{
if (item is T)
{
result.Add(item as T);
continue;
}
else if (item is Span) // first Inline derived class to have own `Inlines`
{
var spanItem = item as Span;
var spanInlines = spanItem.Inlines;
var results = TraverseInline<T>(spanInlines);
if (results != null && results.Any())
result.AddRange(results);
}
}
return result;
}
So you can look for any TextElement-derived item with it.
Usage would be something like:
var textHyperlinks = myRichTextBlock.GetAllTextElements<Hyperlink>();
This will do as far as you don't use InlineUIContainer. That type of Inline behaves differently, as you can put anything UIElement-based as it's Child property. In that case your initial approach should work.
There's a couple of things here:
If you're trying to find the hyperlink inside of the RichTextBlock, its type is: Windows.UI.Xaml.Documents.Hyperlink. Not the type of the HyperLinkButton.
You can put the Click event handler in your text and then provide the handler method in your code behind file. If you dynamically generate text that looks like:
<Paragraph>
Text with a
<Hyperlink x:Name="link" Click="link_Click">link.</Hyperlink>
</Paragraph>
Feed that to the XamlReader, and put the following code in your code behind file:
private void link_Click(Windows.UI.Xaml.Documents.Hyperlink sender, Windows.UI.Xaml.Documents.HyperlinkClickEventArgs args)
{
Debug.WriteLine("Handle link click, by: " + sender.Name);
}
Then it should connect up correctly at runtime. And you can do whatever you want on the Click event handler. Even if there are multiple links, you can name them differently and just use one click handler to process.

Remove specific object instance from Grid.Children?

I have a List<T> with some UserControls.
On the main window there is a Grid and some of the UserControls will be added to Grid.Children.
Now I would like to be able to remove specific UserControls from this Grid e.g. I would like to do something like this
layoutRoot.Children.Remove(controlList[1]);
Is this possible?
I only know FindName() and FindResource() but all the UserControls don't have names so that I can't use these methods :(
Thanks in advance!
just an idea to get you started, if you know the type of your user control, you can use methods like this:
static T FindVisualChild<T>(Visual parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
var visual = (Visual)VisualTreeHelper.GetChild(parent, i);
child = visual as T;
if (child == null)
child = FindVisualChild<T>(visual);
if (child != null)
break;
}
return child;
}

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;
}
}
}
}

Categories

Resources