V
V
vagitaku2019-07-22 22:53:40
WPF
vagitaku, 2019-07-22 22:53:40

How to put XAML elements into a C# array, through a loop?

I have this WPF page:

<Grid Background="White" Margin="0,0,0,-628">
        <ScrollViewer VerticalAlignment="Top" x:Name="LeftScroll"  CanContentScroll="False"  HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Visible">
        <StackPanel Height="3500" x:Name="LeftStackPanel">
            <DockPanel>
                <Label Content="Дата рождения" HorizontalAlignment="Left"/>
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="20,0,0,0">
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFourth_1" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFourth_2" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="10,0,0,0">
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFourth_3" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFourth_4" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="10,0,0,0">
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFourth_5" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFourth_6" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFourth_7" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFourth_8" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                </StackPanel>
            </DockPanel>
        </StackPanel>
        </ScrollViewer>

    </Grid>

And so I try to put all the TextBoxes that are on the page:
private TextBox[] birthDateTB;
        private ScrollViewer leftScrool;

        public HiringPage()
        {

            InitializeComponent();
            foreach (object child in LeftStackPanel.Children)
            {
                if (child.GetType().Equals(typeof(DockPanel)) || child.GetType().Equals(typeof(StackPanel))) //а тут я не знаю, что делать. Мне это все кажется крайне костыльным. Или я иду в правильном направлении? 
                {
                    foreach (object child2 in child2.Children)
                    {
                        if (child.GetType().Equals(typeof(TextBox)))
                        {

                            if (child.GetType().GetProperty("Name").GetValue(child, null).ToString().Contains("TwentyFourth"))
                            {
                                birthDateTB[birthDateTB.Length] = child as TextBox;
                            }
                        }
                    }
                }

                if (child.GetType().Equals(typeof( TextBox)))// этот способ не работает так как, так как нет заходит в DockPanel или StackPanel
                {

                    if (child.GetType().GetProperty("Name").GetValue(child, null).ToString().Contains("TwentyFourth"))
                    {
                        birthDateTB[birthDateTB.Length] = child as TextBox;
                    }
                }
            }
            MessageBox.Show(birthDateTB.Length.ToString());
        }

Putting everything in an array by name is not an option, since I have more than three hundred TextBoxes.
All TextBoxes are divided into groups by name (x:Name). For example:
<DockPanel>
                <TextBlock TextWrapping="Wrap" Text="Документ, удостоверяющий личность:" HorizontalAlignment="Left" Width="150"/>
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFifth_1" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>

                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFifth_2" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFifth_3" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFifth_4" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFifth_5" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFifth_6" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFifth_7" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFifth_8" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFifth_9" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_TwentyFifth_10" Width="20" HorizontalAlignment="Left" 
                </StackPanel>
            </DockPanel>

- this group is defined by the name "TwentyFifth".
There is another one for example:
<DockPanel>
                <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left" Text="Отчество (при наличии)" Width="79"/>
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_Twentieth_1" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>

                    <TextBox IsReadOnly="True" Text="" x:Name="TB_Twentieth_2" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_Twentieth_3" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_Twentieth_4" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_Twentieth_5" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_Twentieth_6" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_Twentieth_7" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_Twentieth_8" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_Twentieth_9" Width="20" HorizontalAlignment="Left" Foreground="Black" BorderThickness="1" BorderBrush="Black" Height="23" Background="{x:Null}" Margin="1,0,0,0"/>
                    <TextBox IsReadOnly="True" Text="" x:Name="TB_Twentieth_10" Width="20" HorizontalAlignment="Left" 
                </StackPanel>
            </DockPanel>

here the general - "Twentieth".
I need arrays in C# with each element of a group.
For example, the array private TextBox[] TwentiethTBmust have links to all xaml elements where the name (x:Name) contains "Twentieth", the TwentyFifth array must have links to all elements where the name contains "TwentyFifth" and so on.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
F
Foggy Finder, 2019-07-23
@vagitaku

The difficulty in implementation is related to the approach you choose. You need to work with data, not with controls.
In your case, you are expecting the user to enter some text.
Each text field on the right side corresponds to one property. For example, consider the cases of having only one input field. Let's call it Greeting .
First, let's define the XAML markup:

<TextBox Text="{Binding Greeting, UpdateSourceTrigger=PropertyChanged}"
         TextWrapping="Wrap" />

UpdateSourceTrigger=PropertyChanged means you want to change the Greeting property whenever the user changes something in the text field.
Now you need to define a class that will be responsible for storing and processing data, let's call it SimpleVM :
public class SimpleVM : INotifyPropertyChanged
{
    private string greeting;

    public string Greeting
    {
        get { return greeting; }
        set
        {
            greeting = value;
            OnPropertyChanged(nameof(Greeting));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName]string prop = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
    }
}

The INotifyPropertyChanged interface is required in order to notify all interested parties about changes in values ​​in an object property. Here we have an interface as an interested person. Whenever you change the Greeting property , the GUI will update its view.
It remains to display the entered word in the form of squares. An ItemsControl is perfect for this :
<ItemsControl Grid.Column="0" ItemsSource="{Binding Greeting}" >
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBox IsReadOnly="True" Text="{Binding .}" 
                     Width="20" Foreground="Black" 
                     BorderThickness="1" BorderBrush="Black" Height="23" 
                     Background="{x:Null}" Margin="1, 3" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

And do not forget to set the DataContext, for starters, you can in the main window constructor:
public MainWindow()
{
    InitializeComponent();
    DataContext = new SimpleVM();
}

As you get a little more familiar with MVVM you will be able to set the context outside of the window (as is usually done).
For now, the result is:
5d36e9309ffef101248000.gif

D
DivineDraft, 2017-11-04
@DivineDraft

New form

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question