0

I have this XAML code and i want to access either the AccountNameTextBox or the elipse few lines below in order to display that some of the Accounts in the list are expired by adding something next to the name (ex. YouTube(Expired)) or by turning the elipse red. The thing is that i can't access them. I have tried using the VisualTreeHelper functions i saw here How can I find WPF controls by name or type? and even tried creating some of my own but nothing works. A thing i noticed was that when i used "VirtualTreeHelper.GetChild" on accountListBox the output was a Border Control and it was the only child. The code is below.

`<StackPanel x:Name="MainStackPanel" Grid.Row="1" Grid.RowSpan="2" DataContext="{StaticResource ResourceKey=accountManager}">
            <ListBox x:Name="accountListBox" ItemsSource="{Binding LoadedAccounts}" Height="600" VerticalAlignment="Bottom" Margin="10,10" Background="Transparent" DoubleTapped="accountListBox_DoubleTapped" ScrollViewer.VerticalScrollBarVisibility="Auto">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Margin="10,0,0,0">
                            <TextBlock x:Name="AccountNameTextBox" Text="{Binding AccountName}" FontFamily="Segoe Script" FontSize="30" Foreground="White"/>
                            <StackPanel Orientation="Horizontal">
                                <StackPanel>
                                    <!--<TextBlock Text="{Binding Username}" FontSize="25" Foreground="Lime"/>-->
                                    <TextBlock Text="{Binding Email}" FontStyle="Italic" FontSize="25" Foreground="DarkSeaGreen"/>
                                    <TextBlock Text="{Binding Password}" FontSize="25" Foreground="YellowGreen"/>
                                </StackPanel>
                                <Ellipse x:Name="Elipse" Height="Auto" Width="10" Margin="10,0">
                                    <Ellipse.Fill>
                                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                            <GradientStop Color="YellowGreen" Offset="0"/>
                                            <GradientStop Color="White" Offset="1"/>
                                        </LinearGradientBrush>
                                    </Ellipse.Fill>
                                </Ellipse>
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </StackPanel>`
Community
  • 1
  • 1
r4F705
  • 65
  • 1
  • 6

1 Answers1

0

Why not using Triggers or Converters? For that you have to add a single property to your bound items (i called mine IsExpired)

Then in the DataTemplate add the DataTrigger:

<DataTemplate.Triggers>
    <DataTrigger Binding="{Binding IsExpired}" Value="True">
        <Setter Property="Visibility" Value="Visible" TargetName="ExpiredTextBlock" />
        <Setter Property="Fill" Value="Red" TargetName="Elipse" />
    </DataTrigger>
</DataTemplate.Triggers>

A possibility with converter would be to add a Converter-Resource to your DataTemplate:

<DataTemplate.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</DataTemplate.Resources>

Then add your (Expired) TextBlock to the DataTemplate and bind to the property

<TextBlock Text="(Expired)" Visibility="{Binding IsExpired, Converter={StaticResource BooleanToVisibilityConverter}}"/>

For the Color you could do the same with a BooleanToColorConverter.


If you want to stick to your code approach you have to dive deeper in your visual tree:

public static T GetChildOfType<T>(this DependencyObject depObj) 
    where T : DependencyObject
{
    if (depObj == null) return null;

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
    {
        var child = VisualTreeHelper.GetChild(depObj, i);

        var result = (child as T) ?? GetChildOfType<T>(child);
        if (result != null) return result;
    }
    return null;
}

This helper method finds the first child of a given type. If you want to find it by name you have to use the name as parameter instead of the generic type and replace the (child as T) check by a name-check.

My personal preferrence would be the solution with the triggers, but it's up to you..

Spongebrot
  • 211
  • 1
  • 9
  • Thank you very much i will check your solution tonight. – r4F705 Apr 12 '16 at 13:01
  • I chose the code approach as i already had a static Helper type class in which it would fit right in and it worked like a charm. Pretty neat code also if i might add. – r4F705 Apr 12 '16 at 17:20