Нахождение контроля в WPF itemscontrol
Привет, у меня есть несколько текстовых полей в табличке с данными для itemscontrol. Когда я связываю элемент управления с наблюдаемой коллекцией, я получаю два текстовых поля. Но мне нужно сделать некоторые манипуляции, основанные на каждом из текстовых полей, для которых я хочу найти каждое текстовое поле отдельно, используя некоторый идентификатор.
Кто-нибудь может помочь в том, как найти элемент управления с помощью элементов управления в WPF.
5 ответов
Используя ItemContainerGenerator, вы можете получить сгенерированный контейнер для элемента и пройти по визуальному дереву вниз, чтобы найти ваш TextBox. В случае ItemsControl это будет ContentPresenter, но ListBox вернет ListBoxItem, ListView a 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;
}
Вы также можете получить контейнер по индексу, если хотите, используя
itemsControl.ItemContainerGenerator.ContainerFromIndex(0);
Спасибо Брайс, я пытался поставить галочку на стрелке вверх, но там написано, что мой рейтинг слишком низкий! Сожалею!
Я исправил код, чтобы он возвращал весь список всех потомков данного типа, так как это было то, что мне было нужно, и думал, что кто-то другой может найти его полезным.
Еще раз спасибо Брайс, очень полезно - извините за оценку вещь!
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;
}
Вы можете попробовать использовать VisualTreeHelper. Свойства самого ItemsControl позволят вам получить только данные, к которым он привязан, а не экземпляры шаблона, используемые для визуализации данных, тогда как VisualTreeHelper позволяет просматривать дерево визуалов, как его визуализировал WPF.
Если вы перебираете визуальные дочерние элементы родительского ItemControl (рекурсивно), у вас не должно возникнуть никаких проблем с поиском текстовых полей, которые вы видите на экране.
Другой пример:
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;
}
Если у вас есть сетка данных и столбец шаблона, который содержит шаблон данных, вы можете использовать следующий пример кода
<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))