如何从代码隐藏更改 DataTemplate 中特定元素的 属性?
How to change a property of a specific element in a DataTemplate from code behind?
我的代码中有一个错误。
FindChild<T>()
正在搜索一个名为“PasswordTextBox”的元素,但因为“PasswordTextBox”在 DataTemplate 中,所以有很多文本框。如果我单击第二行或第三行中的眼睛(mah:FontIcon)或其他任何内容,它甚至会更改 DataTemplate 中第一个 TextBox 的 FontFamily。
如何更改 DataTemplate 中单击眼睛所在行的元素的 TextBox.FontFamily?
也就是xaml代码:
<HeaderedItemsControl Grid.Column="0" Grid.ColumnSpan="4" Grid.Row="1">
<ItemsControl x:Name="ListViewItems">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Margin="1 10 0 10" Height="60">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="1"
x:Name="PasswordTextBox"
Text="{Binding Password, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
Height="40"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Left"
HorizontalAlignment="Stretch"
FontFamily="pack://application:,,,/Fonts/#password"
Margin="-25 0 100 0"
Padding="6, 4, 45, 0">
</TextBox>
<mah:FontIcon Grid.Column="1"
FontFamily="Segoe MDL2 Assets"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontSize="28"
Glyph=""
Margin="0, 0, 110, 0"
Foreground="#cfcfcf"
MouseLeftButtonUp="OnEyeClicked" />
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</HeaderedItemsControl>
那是我背后的 C# 代码:
private void OnEyeClicked(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
TextBox foundTextBox = FindChild<TextBox>(Application.Current.MainWindow, "PasswordTextBox");
if (ShowPassword)
{
foundTextBox.FontFamily = new FontFamily("Segoe MDL2");
foundTextBox.Padding = new Thickness(6, 4, 45, 0);
ShowPassword = false;
}
else
{
foundTextBox.FontFamily = new FontFamily(new Uri("pack://application:,,,/"), "./Fonts/#password");
foundTextBox.Padding = new Thickness(6, 0, 45, 0);
ShowPassword = true;
}
}
public static T FindChild<T>(DependencyObject parent, string childName)
where T : DependencyObject
{
// Confirm parent and childName are valid.
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
T childType = child as T;
if (childType == null)
{
// recursively drill down the tree
foundChild = FindChild<T>(child, childName);
// If the child is found, break so we do not overwrite the found child.
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
if (frameworkElement != null && frameworkElement.Name == childName)
{
// if the child's name is of the request name
foundChild = (T)child;
break;
}
}
else
{
// child element found.
foundChild = (T)child;
break;
}
}
return foundChild;
}
您可以在模板范围内搜索,相对于 sender
元素:
private void OnEyeClicked(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var ico = (FontIcon)sender;
var grid = (Grid)ico.Parent;
TextBox foundTextBox = FindChild<TextBox>(grid, "PasswordTextBox");
if (ShowPassword)
{
foundTextBox.FontFamily = new FontFamily("Segoe MDL2");
foundTextBox.Padding = new Thickness(6, 4, 45, 0);
ShowPassword = false;
}
else
{
foundTextBox.FontFamily = new FontFamily(new Uri("pack://application:,,,/"), "./Fonts/#password");
foundTextBox.Padding = new Thickness(6, 0, 45, 0);
ShowPassword = true;
}
}
顺便说一句,ShowPassword 也应该是相对于每个密码框的,不是吗?
我的代码中有一个错误。
FindChild<T>()
正在搜索一个名为“PasswordTextBox”的元素,但因为“PasswordTextBox”在 DataTemplate 中,所以有很多文本框。如果我单击第二行或第三行中的眼睛(mah:FontIcon)或其他任何内容,它甚至会更改 DataTemplate 中第一个 TextBox 的 FontFamily。
如何更改 DataTemplate 中单击眼睛所在行的元素的 TextBox.FontFamily?
也就是xaml代码:
<HeaderedItemsControl Grid.Column="0" Grid.ColumnSpan="4" Grid.Row="1">
<ItemsControl x:Name="ListViewItems">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Margin="1 10 0 10" Height="60">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="1"
x:Name="PasswordTextBox"
Text="{Binding Password, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
Height="40"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Left"
HorizontalAlignment="Stretch"
FontFamily="pack://application:,,,/Fonts/#password"
Margin="-25 0 100 0"
Padding="6, 4, 45, 0">
</TextBox>
<mah:FontIcon Grid.Column="1"
FontFamily="Segoe MDL2 Assets"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontSize="28"
Glyph=""
Margin="0, 0, 110, 0"
Foreground="#cfcfcf"
MouseLeftButtonUp="OnEyeClicked" />
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</HeaderedItemsControl>
那是我背后的 C# 代码:
private void OnEyeClicked(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
TextBox foundTextBox = FindChild<TextBox>(Application.Current.MainWindow, "PasswordTextBox");
if (ShowPassword)
{
foundTextBox.FontFamily = new FontFamily("Segoe MDL2");
foundTextBox.Padding = new Thickness(6, 4, 45, 0);
ShowPassword = false;
}
else
{
foundTextBox.FontFamily = new FontFamily(new Uri("pack://application:,,,/"), "./Fonts/#password");
foundTextBox.Padding = new Thickness(6, 0, 45, 0);
ShowPassword = true;
}
}
public static T FindChild<T>(DependencyObject parent, string childName)
where T : DependencyObject
{
// Confirm parent and childName are valid.
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
T childType = child as T;
if (childType == null)
{
// recursively drill down the tree
foundChild = FindChild<T>(child, childName);
// If the child is found, break so we do not overwrite the found child.
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
if (frameworkElement != null && frameworkElement.Name == childName)
{
// if the child's name is of the request name
foundChild = (T)child;
break;
}
}
else
{
// child element found.
foundChild = (T)child;
break;
}
}
return foundChild;
}
您可以在模板范围内搜索,相对于 sender
元素:
private void OnEyeClicked(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var ico = (FontIcon)sender;
var grid = (Grid)ico.Parent;
TextBox foundTextBox = FindChild<TextBox>(grid, "PasswordTextBox");
if (ShowPassword)
{
foundTextBox.FontFamily = new FontFamily("Segoe MDL2");
foundTextBox.Padding = new Thickness(6, 4, 45, 0);
ShowPassword = false;
}
else
{
foundTextBox.FontFamily = new FontFamily(new Uri("pack://application:,,,/"), "./Fonts/#password");
foundTextBox.Padding = new Thickness(6, 0, 45, 0);
ShowPassword = true;
}
}
顺便说一句,ShowPassword 也应该是相对于每个密码框的,不是吗?