1

I followed this and somer other links: How to retrieve the text of a dynamically created textbox and display its as a content of dynamically created button in wpf c#

But for me its not working. I generate my TextBlock here:

TextBox NameBox = new TextBox();
NameBox.Text = expander.Header.ToString();
MaterialDesignThemes.Wpf.HintAssist.SetHint(NameBox, "Rolename");
MaterialDesignThemes.Wpf.HintAssist.SetIsFloating(NameBox, true);
NameBox.Opacity = .68;
NameBox.Width = 200;
NameBox.Name = "roleNameBox";
DockPanel.SetDock(NameBox, Dock.Left);

and its successfull. But if I try to get the Text from it via generated Button:

Button saveBtn = new Button();
saveBtn.Name = "SaveRoleBtn";
saveBtn.Style = (Style)FindResource("MaterialDesignToolButton");
saveBtn.Margin = new Thickness(0, 0, 8, 0);
saveBtn.ToolTip = "Save Role";
saveBtn.Height = 24;
saveBtn.Width = 24;
saveBtn.Click += SaveRoleBtn_Click;
MaterialDesignThemes.Wpf.RippleAssist.SetIsCentered(saveBtn, true);
DockPanel.SetDock(saveBtn, Dock.Right);

And the Event:

private void SaveRoleBtn_Click(object sender, RoutedEventArgs e)
{
    var button = sender as Button;
    var parent = button.Parent as FrameworkElement;
    var roleName = parent.FindName("roleNameBox") as TextBox;

    if (roleName != null)
        MessageBox.Show(roleName.Text);
    else
        MessageBox.Show("Is null");
}

It is null everytime. How is this possible? Is the ´as FrameWorkElement;´ wrong? And what I have to put there else?

This would be the XAML if the Code would be not generated:

<ScrollViewer Grid.Row="1">
        <materialDesign:Card Grid.Row="1" Background="{DynamicResource MaterialDesignBackground}">
            <StackPanel x:Name="roleListSp" Grid.Row="1">
                <!-- HERE STARTS GENERATED CONTROLS -->
                <Expander HorizontalAlignment="Stretch" Header="Rolle 1">
                    <StackPanel Orientation="Vertical" TextBlock.Foreground="{DynamicResource MaterialDesignBody}" Margin="24,8,24,16">
                        <DockPanel LastChildFill="False">
                            <Button x:Name="saveRoleBtn" Style="{StaticResource MaterialDesignToolButton}" DockPanel.Dock="Right" Margin="0 0 8 0" HorizontalAlignment="Left" ToolTip="Save Role" Width="24" Height="24" materialDesign:RippleAssist.IsCentered="True" Click="SaveRoleBtn_Click">
                                <materialDesign:PackIcon Kind="ContentSave" Height="16" Width="16" />
                            </Button>
                            <Button x:Name="deleteRoleBtn" Style="{StaticResource MaterialDesignToolButton}" DockPanel.Dock="Right" Margin="0 0 8 0" HorizontalAlignment="Left" ToolTip="Delete Role" Width="24" Height="24" materialDesign:RippleAssist.IsCentered="True" Click="deleteRoleBtn_Click">
                                <materialDesign:PackIcon Kind="Delete" Height="16" Width="16" />
                            </Button>
                            <TextBox x:Name="roleNameBox" Opacity=".68" materialDesign:HintAssist.Hint="Role Name" Width="200" materialDesign:HintAssist.IsFloating="True"/>
                        </DockPanel>
                        <TextBox x:Name="roleDescBox" Opacity=".68" materialDesign:HintAssist.Hint="Description" materialDesign:HintAssist.IsFloating="True" TextWrapping="Wrap" MouseDown="Beschreibung_MouseDown"/>
                        <TextBlock Text="Rights" Margin="0,10,0,0" />
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                            <StackPanel Grid.Column="0">
                                <DockPanel LastChildFill="False">
                                    <TextBlock Opacity=".68" Text="Can Add:" DockPanel.Dock="Left" />
                                    <ToggleButton DockPanel.Dock="Right" PreviewMouseDown="ToggleButton_PreviewMouseDown"/>
                                </DockPanel>
                                <DockPanel Margin="0,2,0,0" LastChildFill="False">
                                    <TextBlock Opacity=".68" Text="Can Edit:" DockPanel.Dock="Left" />
                                    <ToggleButton DockPanel.Dock="Right" PreviewMouseDown="ToggleButton_PreviewMouseDown" />
                                </DockPanel>
                            </StackPanel>
                            <StackPanel Grid.Column="1">
                                <DockPanel LastChildFill="False">
                                    <TextBlock Opacity=".68" Text="Can Delete:" DockPanel.Dock="Left"/>
                                    <ToggleButton IsChecked="True" DockPanel.Dock="Right" PreviewMouseDown="ToggleButton_PreviewMouseDown"/>
                                </DockPanel>
                                <DockPanel LastChildFill="False" Margin="0,2,0,0">
                                    <TextBlock Opacity=".68" Text="Administration:" DockPanel.Dock="Left" />
                                    <ToggleButton DockPanel.Dock="Right" PreviewMouseDown="ToggleButton_PreviewMouseDown" />
                                </DockPanel>
                            </StackPanel>
                        </Grid>
                    </StackPanel>
                </Expander>
                <!-- HERE ENDS GENERATED CONTROLS -->
            </StackPanel>
        </materialDesign:Card>
    </ScrollViewer>
Community
  • 1
  • 1
O Jean
  • 105
  • 9

1 Answers1

1

If you add the TextBox to the same DockPanel as the Button you could look for it in the DockPanel's Children collection:

private void SaveRoleBtn_Click(object sender, RoutedEventArgs e)
{
    var button = sender as Button;
    var parent = button.Parent as DockPanel;
    if(parent != null)
    {
        var textBox = parent.Children.OfType<TextBox>().FirstOrDefault();
        if (textBox != null)
            MessageBox.Show(textBox.Text);
        else
            MessageBox.Show("Is null");
    }
}

If the TextBox may be located in different child panels, you could use a helper method that searches for it in the visual tree:

How can I find WPF controls by name or type?

var textBox = FindChild<TextBox>(roleListSp, "roleNameBox");
Community
  • 1
  • 1
mm8
  • 163,881
  • 10
  • 57
  • 88
  • I have more TextBoxes in other Panels. My hardcored Panel is roleListSp (StackPanel) but if i search Name of roleListSp it cant find too: `TextBox roleName = (TextBox)roleListSp.FindName("roleNameBox");` I added XAML of how it would look like if its not generated above. I want the Text of roleNameBox, roleDescBox and the IsChecked from the ToggleButtons. They all are in different Panels thats the problem. But all are in roleListSp Stackpanel – O Jean Apr 05 '17 at 11:59
  • Did you try my code? It should give the Text of the roleNameBox. – mm8 Apr 05 '17 at 12:02
  • Yes it gives the Text of roleNameBox. But i dont think that this will work with the other textboxes too because they are in different panels. – O Jean Apr 05 '17 at 12:04
  • Well, you didn't mention this in your original question. Please see my edited answer. – mm8 Apr 05 '17 at 12:05
  • Oh sorry then :/ the FindChild method doesn't work. I tried `TextBox roleName = FindChild(Application.Current.MainWindow, "roleNameBox");` too. And FindName doesn't work too. – O Jean Apr 05 '17 at 12:16
  • Set the IsExpanded property of the Expander to true. If it is collapsed, there are no child elements added to the visual tree. – mm8 Apr 05 '17 at 12:25
  • `Expander expander = new Expander(); expander.HorizontalAlignment = HorizontalAlignment.Stretch; expander.Header = "Rolename"; expander.IsExpanded = true;` it is :/ (forgot to add in XAML above, but it is Expanded) – O Jean Apr 05 '17 at 12:46
  • Then FindChild(roleListSp, "roleNameBox") should work. It does for me when I try it using the XAML markup you have posted. – mm8 Apr 05 '17 at 12:48
  • Then maybe it bugs cuz i have more then 1 Expaner? I read items from database and all have the name roleNameBox. But i have an idea. I can give the SaveButton the Tag 1,2 or 3 for example. And if i search roleNameBox i can search for "roleNameBox" + saveBtn.Tag Hope this will work. Of course it bugs cuz i have more Expander.. sorry for my stupidity im not concentrated today.. – O Jean Apr 05 '17 at 12:54
  • You should provide a reproducible sample of your issue when asking a question: https://stackoverflow.com/help/mcve. Another idea; since you are creating the TextBox dynamically, why can't you just save a reference to it i a class-level field? Then you don't need to search for it. – mm8 Apr 05 '17 at 13:03