I have a bug in my code. FindChild() is searching a Element wich is named "PasswordTextBox" but because "PasswordTextBox" is in the DataTemplate there are many TextBoxes. And if I will click on the eye (the mah:FontIcon) in the second row or third row or whatever it even changes the FontFamily of the first TextBox in the DataTemplate.
How can I change the TextBox.FontFamily of the element in the row of the DataTemplate where the eye is clicked?
That is the xaml code:
<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>
And that is my c# code behind:
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;
}
CodePudding user response:
you can search within template bounds, relative to sender
element:
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;
}
}
btw, ShowPassword should also be relative to each password box, shouldn't it?
CodePudding user response:
Maybe Triggers will help?
<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.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="IsEyeClicked" Value="True">
<Setter Property="FontFamily" Value="WhateverFontFamily"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
That's just a rough example, more info here: https://wpf-tutorial.com/styles/trigger-datatrigger-event-trigger/