在 WPF itemscontrol 中查找控件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/980120/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Finding control within WPF itemscontrol
提问by deepak
Hi i have few a single textbox within the the datatemplate for itemscontrol. When i bind the itemcontrols to a observable collection i get two text boxes. But i need to do some manipulations based on each of the text boxes for which i want to find each textbox seperatly using some id.
嗨,我在 itemscontrol 的数据模板中只有几个文本框。当我将 itemcontrols 绑定到一个 observable 集合时,我得到两个文本框。但是我需要根据每个文本框进行一些操作,我想使用一些 id 单独找到每个文本框。
Can anybody help on how to find a control witin the itemscontrol in WPF.
任何人都可以帮助如何在 WPF 中的 itemscontrol 中找到控件。
回答by Bryce Kahle
Using the ItemContainerGenerator you can obtain the generated container for an item and traverse the visual tree downwards to find your TextBox. In the case of an ItemsControl it will be a ContentPresenter, but a ListBox will return a ListBoxItem, ListView a ListViewItem, etc.
使用 ItemContainerGenerator,您可以获得为项目生成的容器,并向下遍历可视化树以找到您的 TextBox。在 ItemsControl 的情况下,它将是一个 ContentPresenter,但 ListBox 将返回一个 ListBoxItem、ListView 一个 ListViewItem 等。
ContentPresenter cp = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter;
TextBox tb = FindVisualChild<TextBox>(cp);
if (tb != null)
{
// do something with tb
}
public static T FindVisualChild<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)
{
return (T)child;
}
T childItem = FindVisualChild<T>(child);
if (childItem != null) return childItem;
}
}
return null;
}
You can also obtain the container by index if you want by using
如果需要,您还可以通过索引获取容器
itemsControl.ItemContainerGenerator.ContainerFromIndex(0);
回答by Andy Clarke
Thanks Bryce, I tried to tick the up arrow but it says my rating is too low! Sorry!
谢谢布莱斯,我试图勾选向上箭头,但它说我的评级太低了!对不起!
I amended the code to return all a list of all the children of the given type as it was what I needed and thought someone else might find it useful.
我修改了代码以返回给定类型的所有子项的所有列表,因为它是我需要的,并且认为其他人可能会发现它很有用。
Thanks again Bryce, really helpful - sorry about the rating thing!
再次感谢布莱斯,真的很有帮助 - 对评级问题感到抱歉!
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;
}
回答by Nicholas Armstrong
You may want to try using VisualTreeHelper. The properties on ItemsControl itself will only allow you to get the data its bound to, not the template instances used to visualize the data, while VisualTreeHelper allows you to browse around the visual tree as WPF has rendered it.
您可能想尝试使用VisualTreeHelper。ItemsControl 本身的属性仅允许您获取绑定到的数据,而不是用于可视化数据的模板实例,而 VisualTreeHelper 允许您在 WPF 呈现可视化树时浏览可视化树。
If you iterate through the parent ItemControl's visual children (recursively), you shouldn't have any difficulty locating the text boxes you are seeing on screen.
如果您遍历父项 ItemControl 的可视子项(递归),您应该不会有任何困难定位您在屏幕上看到的文本框。
回答by RckLN
Another example:
另一个例子:
private void DataGridBank_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
try
{
switch (e.Key)
{
case Key.Down:
if ((DataGridBank.SelectedIndex + 1) <= DataGridBank.Items.Count)
{
DataGridBank.SelectedIndex = DataGridBank.SelectedIndex + 1;
FocusCell();
}
break;
case Key.Up:
if ((DataGridBank.SelectedIndex - 1) >= 0)
{
DataGridBank.SelectedIndex = DataGridBank.SelectedIndex - 1;
FocusCell();
}
break;
case Key.Enter:
case Key.Tab:
FocusCell();
break;
}
}
catch (Exception ex)
{
}
}
private void DataGridBank_Loaded(object sender, RoutedEventArgs e)
{
try
{
if (DataGridBank.Items.Count > 0)
{
DataGridBank.SelectedIndex = 0;
FocusCell();
}
}catch(Exception ex)
{
}
}
private void FocusCell()
{
var selectedRow = (DataGridRow)DataGridBank.ItemContainerGenerator.ContainerFromItem(DataGridBank.SelectedItem);
var textImport = FindVisualChild<TextBox>(selectedRow);
textImport.Focus();
textImport.SelectAll();
}
public static T FindVisualChild<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)
{
return (T)child;
}
T childItem = FindVisualChild<T>(child);
if (childItem != null) return childItem;
}
}
return null;
}
回答by Mohamed Abdo
If you have data grid and template column, which contains data template, you can use the following code sample
如果您有数据网格和模板列,其中包含数据模板,则可以使用以下代码示例
<DataGridTemplateColumn x:Name="photoPathColumn" Header="{x:Static resx:FrmResource.Photo}">
<DataGridTemplateColumn.CellEditingTemplate x:Uid="keyelm">
<DataTemplate x:Name="dodo">
<StackPanel Orientation="Horizontal" Height="Auto">
<TextBlock x:Name="photo" x:Uid="imageFile" Text="{Binding Path=PhotoPath}" />
<Button x:Name="Browse" Content="..." Click="Browse_Click" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
photoPathColumn.CellEditingTemplate.FindName("photo",photoPathColumn.GetCellContent(CustomersDataGrid.CurrentItem))