@vagitaku

Как поместить XAML элементы в C# массив, чрез цикл?

Есть такая WPF страница:
<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>

И так я пытаюсь поместить все TextBox'ы, которые есть на странице:
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());
        }

Заносить все в массив по имени не вариант, так как у меня больше трехсот TextBox`ов.

Все ТекстБоксы разделены на группы по имени (x:Name). Например:
<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>

- эту группу определеяет имя "TwentyFifth".
Есть еще такой например:
<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>

тут общее - "Twentieth".
Мне нужны в C# массивы с каждым элементом группы.
Например массив private TextBox[] TwentiethTB должен иметь ссылки на все xaml элементы где в имени (x:Name) присутствует "Twentieth", массив TwentyFifth должен иметь ссылки на все элементы, где в имени попадается "TwentyFifth" и так далее.
  • Вопрос задан
  • 1435 просмотров
Решения вопроса 1
FoggyFinder
@FoggyFinder
Сложность в реализации связана с выбранным вами подходом. Нужно работать с данными, а не с элементами управления.

В вашем случае вы ожидаете от пользователя ввод какого-то текста.
Каждому текстовому полю с правой стороны отвечает одно свойство. Для примера рассмотрим случаи наличия только одного поля для ввода. Назовем его Greeting.

Для начала определим XAML разметку:

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


UpdateSourceTrigger=PropertyChanged означает что вы хотите изменять свойство Greeting всякий раз когда пользователь меняет что-то в текстовом поле.

Теперь нужно определить класс который будет отвечать за хранения и обработку данных, назовем его 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));
    }
}


Интерфейс INotifyPropertyChanged необходим для того чтобы оповещать всех интересующихся об изменениях значений в свойстве объекта. В роли интересующегося здесь у нас выступает интерфейс. Всякий раз когда вы будете изменять свойство Greeting графический интерфейс будет обновлять свое представление.

Осталось отобразить вводимое слово в виде квадратиков. Для этого прекрасно подойдет ItemsControl:

<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>


И не забываем установить DataContext, для начала можно в конструкторе главного окна:

public MainWindow()
{
    InitializeComponent();
    DataContext = new SimpleVM();
}


Когда вы станет познакомитесь с MVVM немного больше вы сможете устанавливать контекст снаружи окна (как это обычно и делается).

А пока результат получается следующим:

5d36e9309ffef101248000.gif
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы