0

I have following XAML in WPF

<Canvas>
    <WrapPanel x:Name="TimeTableMainWrapPanel" Canvas.Left="109" Canvas.Top="195" Height="601" Width="745>
        <TextBox x:Name="txtFirstLctrTime"  Height="24" TextWrapping="Wrap" Width="115"/>
        <TextBox x:Name="txtSecondLctrTime" Height="23" Canvas.Left="594" TextWrapping="Wrap" Canvas.Top="189" Width="115"/>

        <WrapPanel x:Name="TimeTableSubWrapPanel" Canvas.Left="109" Canvas.Top="195" Height="601" Width="745">
            <WrapPanel x:Name="FirstLecture" Background="#00F0F8FF" Height="392" Width="133" Margin="0,0,10,0">
                <TextBox x:Name="txtMondayFirstLctr" Width="133" Margin="0" Height="30" FontSize="13" VerticalContentAlignment="Center"/>
                <TextBox x:Name="txtTuesdayFirstLctr" Width="133" Margin="0,38,0,0" Height="30" FontSize="13" VerticalContentAlignment="Center"/>
            </WrapPanel>

            <WrapPanel x:Name="SecondLecture" Canvas.Top="220" Background="#00F0F8FF" Canvas.Left="270" Height="466" Width="133" Margin="8,0,10,0">
                <TextBox x:Name="txtMondaySecondLctr" Width="133" Margin="0,38,0,0" Height="30" VerticalContentAlignment="Center"></TextBox>
                <TextBox x:Name="txtTuesdaySecondLctr" Width="133" Margin="0,38,0,0" Height="30" VerticalContentAlignment="Center"></TextBox>
            </WrapPanel>
        </WrapPanel>
    </WrapPanel>
</Canvas>

I wanted to clear content of all textbox on button click. And for that I am doing

var firsttextboxes = this.FirstLecture.Children.OfType<TextBox>();
var secondtextboxes = this.SecondLecture.Children.OfType<TextBox>();

foreach (var textbox in firsttextboxes)
{
    textbox.Clear();
}

foreach (var textbox in secondtextboxes)
{
    textbox.Clear();
}

Is there any better way of doing this, instead of using multiple foreach loops?

Also how do I enter one value in each TextBox and move to next?

I am trying the code below, but it is inserting the same value in all TextBox objects:

foreach(var a in firsttextboxes ) 
{ 
    foreach(var b in Text) 
    { 
        a.Text = b 
    } 
} 
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Richa
  • 3,261
  • 2
  • 27
  • 51

5 Answers5

1

Use Union and combine all the sources. Then foreach over allTextboxes.

var allTextboxes = firsttextboxes
                    .Union(secondtextboxes)
                    .Union(thirdtextboxes);
                    //And so on
foreach (var textbox in allTextboxes )
{
    textbox.Clear();
}

Another approach would be looking at the visual tree to find out all the TextBoxes within the parent WrapPanel and clear them.

Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
  • One last ques, if i have Five textbox and five values how will i append one value each in respective Textbox using foreach? I trie like foreach(var a in Timetable) { foreach(var b in Text) { a.Text = b } } BUt it is inserting same value in all Textbox – Richa Apr 06 '15 at 10:10
  • 1
    @Richa You're doing it wrong. If you do this way, it will be a maintenance problem for you. Please look at `DataBinding`. Create a ViewModel class which exposes (those 5)properties and bind respective property to the `TextBox`. Then implement `INotifyPropertyChanged` interface in ViewModel, so that when the property is updated, TextBox will be automatically updated. Search for "Wpf Mvvm databinding" – Sriram Sakthivel Apr 06 '15 at 10:16
1

I have created a Generic method to do the same. PerformOperationOnVisualTreeControl method accepts parent control and an `Action method to define your operation.

public static void PerformOperationOnVisualTreeControl<T>(Visual myVisual, Action<T> action)
{
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++)
        {
            var childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);
            if (typeof(T) == childVisual.GetType())
            {
                T control = (T)System.Convert.ChangeType(childVisual, typeof(T));
                action(control);
            }

            PerformOperationOnVisualTreeControl<T>(childVisual, action);
        }
}

You can call PerformOperationOnVisualTreeControl method like below

Update : I have created a Queue to update all the TextBox with database values. Queue will Dequeue value one by one and update the TextBox

var dbValues = new Queue<int>(Enumerable.Range(1, 5));
PerformOperationOnVisualTreeControl<TextBox>(this.TimeTableSubWrapPanel, (control) =>
{
    control.Clear();
    if (dbValues.Count > 0)
    {
        control.Text = dbValues.Dequeue().ToString();
    }
});
Vimal CK
  • 3,543
  • 1
  • 26
  • 47
0
void ClearDescendantTextBoxes(Control ctrl)
{
    foreach (Control child in ctrl.Controls)
        if (child is TextBox)
            child.Text = "";
        else ClearDescendantTextBoxes(child);
}

(This is for winforms. But you can probably fix it easily for wpf.)

ispiro
  • 26,556
  • 38
  • 136
  • 291
0

In regards to MVVM, I would Create a command for the button that is responsible for clearing the textboxes.

I would then implement the command by setting the observable properties that should be bound to the textboxes to null.

This removes the code-behind that typically grows into a maintenance nightmare / God-class.

Scott Nimrod
  • 11,206
  • 11
  • 54
  • 118
0

var allTextboxes = this.mainpan.Children.OfType();

        foreach (var textbox in allTextboxes)
        {
            textbox.Clear();
        }
        var allTextboxe = this.mainpan.Children.OfType<ComboBox>();
        foreach (var textbox in allTextboxe)
        {
            textbox.SelectedIndex = 0;
        }
  • 1
    This answer could be better explained, especially since this answer is 5+ years later than the original question. Does it add anything that the other answers did not? Please elaborate if possible so that anyone who comes across this in the future will have more context. – Tori Henri Mar 24 '21 at 21:38