Search code examples
c#wpfxaml

How can I access the text boxes in the button in the event handler?


I want to print info about elements in message box, but i don't know how to get access to the text boxes inside the button.

<Button Grid.Row="5" Grid.Column="2"
                Background="#FF9935"
                BorderBrush="#FF9935"
                Margin="0,0,0,5"
                Click="Button_Click">

            <Button.Resources>
                <Style TargetType="Border">
                    <Setter Property="CornerRadius" Value="5"></Setter>
                </Style>
            </Button.Resources>

            <Grid Height="66" Width="67">
                <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>

                <TextBlock VerticalAlignment="Top" Grid.Row="0" FontSize="9">38</TextBlock>
                <TextBlock VerticalAlignment="Center" Grid.Row="1" FontSize="20" FontWeight="Bold">Sr</TextBlock>
                <TextBlock Grid.Row="2" FontSize="10" FontWeight="DemiBold">Strontium</TextBlock>
                <TextBlock Grid.Row="3" FontSize="8">87.62</TextBlock>
            </Grid>
        </Button>

XAML

        private void Button_Click(object sender, RoutedEventArgs e)
        {

        }

UI

So i want to print in the message box info about chemical element whe user pressed on it


Solution

  • You can use VisualTreeHelper to search the child elements of the clicked button for elements with specific properties.

    For example, this helper function will look for a child element with type TextBlock and with a specific FontSize and return its content.

    public static string FindTextBlockTextByFontSize(DependencyObject depObj, double fontSize)
    {
        
        // For all child elements
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            // Get the child via VisualTreeHelper
            var child = VisualTreeHelper.GetChild(depObj, i);
    
            if ((child is TextBlock textBlock) && textBlock.FontSize == fontSize)
            {
                // If the child is a TextBlock and has the specified FontSize, return its content
                return textBlock.Text;
            }
            else
            {
                // Recurse to check this element's child elements
                string result = FindTextBlockTextByFontSize(child, fontSize);
                if (result != null) return result;
            }
        }
    
        // If none are found, return null
        return null;
    }
    

    You can then use this helper function like this:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Button clickedButton = sender as Button;
    
        string atomicNumber = FindTextBlockTextByFontSize(clickedButton, 9);
        string abbreviation = FindTextBlockTextByFontSize(clickedButton, 20);
        string fullName = FindTextBlockTextByFontSize(clickedButton, 10);
        string weight = FindTextBlockTextByFontSize(clickedButton, 8);
    
        MessageBox.Show(atomicNumber + " " + abbreviation + " " + fullName + " " + weight);
    }
    

    This is a quick and dirty solution, but not a very professional approach. The professional approach would look like this:

    Have a class ChemicalElement that represents one chemical element with all its properties.

    Keep a list or other data structure with all the known chemical elements.

    Use a WPF data or control template to define how an entry in the period table should look like based on a binding to an instance of type ChemicalElement. From the OnClick-event you can then directly access the bound ChemicalElement with all its properties.