0

Имеется ListBox с шаблоном: для каждого элемента два textblock и один textbox.

Как в коде получить текст textblock и textbox?

Не знаю, как обратится в цикле к каждому элементу ListBox. Если как обычно обращться по имени к textblock, то не получается - "имя не существует в данном контексте".

 <ListBox DataContext="{Binding ElementName=cBoxGroup, Path=SelectedItem}"
               ItemsSource="{Binding Path = Atlets}"  x:Name="lbnewResult" >
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="150"/>
                                <ColumnDefinition Width="150"/>
                                <ColumnDefinition Width="150"/>
                            </Grid.ColumnDefinitions>
                             <TextBlock  x:Name="tbLast_Name"  Grid.Column ="0"  Text="{Binding Path = Last_Name}" HorizontalAlignment="Left"/>
                            <TextBlock  Grid.Column ="1"  Text="{Binding Path = First_Name}" HorizontalAlignment="Left"/>
                            <TextBox Grid.Column ="2" x:Name ="tbResult" Background="Aqua"/>
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
        </ListBox>
Viki
  • 11
  • 1
    А зачем вам это? Изменить текст, или зачем еще? Какую именно задачу вы решаете? Обращаться из C# кода к контролам напрямую в WPF - плохая практика. Вы используете Binding, что с ними не так? Чего не хватает? – aepot Feb 19 '21 at 07:54
  • В вашем вопросе Ошибка XY, вы спрашиваете "как правильно забивать гвозди микроскопом?". – aepot Feb 19 '21 at 10:33
  • У меня в базе данных отдельные таблицы - группы. атлеты.тесты. тестпротоколы. Нужно выводить фамилии согласно выбранной группе и вносить результаты теста в таблицу тестпротоколы в зависимости от Id атлета. Фамилии выводятся из базы данных. а результаты теста будет вносить пользователь. Результаты нужно получить, проверить, сформировать объект класса тестпротокол и сохранить в бд. Как это сделать не обращаясь к элементам в zaml не знаю. – Viki Feb 19 '21 at 11:27
  • Загляните сюда, у автора в принципе правильно реализована модель данных, я ему только подсказал, как пользоваться командами вместо обработчиков событий Click. Суть реализации INotifyPropertyChanged в том, что когда вы меняете данные, они автоматически меняются в интерфейсе. В результате у вас появляется возможность пилить отдельно XAML и отдельно C# код, изменения в одном практически не будут влиять на работу другого. Это сильно упростит дальнейшую разработку. То есть INotifyPropertyChanged позволяет Binding работать в обе стороны. – aepot Feb 19 '21 at 12:19
  • ...Вам же этого не хватало? – aepot Feb 19 '21 at 12:20
  • Спасибо. Проблема в том, что у меня не реализован MVVM. Посоветуйте учебные примеры. – Viki Feb 20 '21 at 09:42
  • MVVM здесь вообще дело десятое, я вам про привязки данных толкую. Про технологию, а не шаблон проектирования. учебные примеры – aepot Feb 20 '21 at 09:47

1 Answers1

1

Об этом есть статья на MSDN: How to: Find DataTemplate-Generated Elements

//Начинаем с элемента ListBox. В примере используется текущий элемент,
//Вы будете обходить элементы в списке
ListBoxItem myListBoxItem =
    (ListBoxItem)(myListBox.ItemContainerGenerator.ContainerFromItem(myListBox.Items.CurrentItem));

// Для элемента получаем ContentPresenter ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);

// Шаблон данных DataTemplate myDataTemplate = myContentPresenter.ContentTemplate; //И уже из него по имени вытаскиваем TextBlock TextBlock myTextBlock = (TextBlock)myDataTemplate.FindName("tbLast_Name", myContentPresenter);

  • Бррр, зачем так делать? Это же WPF, здесь привязки есть. – aepot Feb 19 '21 at 07:54
  • 2
    @aepot Грешен, каюсь :) Мне говорят: «Дай TextBlock», и я дал TextBlock. Если автор вопроса объяснит Вам сверхзадачу, опубликуйте «чистое» решение, я Вам плюсик поставлю. – default locale Feb 19 '21 at 08:01
  • Спасибо за решение. Пока не все понятно, но все работает. Задача была выводить из базы данных фамилии, каждому записывать результат и сохранять в базу данных. – Viki Feb 19 '21 at 09:04
  • @Viki Пожалуйста! Это решение сработает, но обычно в WPF не принято из кода обращаться напрямую к элементам интерфейса. В вашем случае наверное было бы обновлять результат напрямую в привязанные объекты, а не в сгенерированные поля. Для этого результату нужно прописать свою привязку (Binding), и тогда не понадобятся лишние циклы и поиск текстбоксов. – default locale Feb 19 '21 at 09:17
  • Возможно, но тоже не совсем понятно как реализовать, фамилии из одной таблицы, а результат заносится в другую в соответствии с Id фамилии. – Viki Feb 19 '21 at 09:24
  • Можно создать один объект (спортсмен-результат) для привязки, а затем при обработке сохранять данные по разным таблицам. Все лучше чем выковыривать результат из текстбоксов. Можете создать отдельный вопрос «как сделать лучше», может кто-нибудь с большим опытом в WPF подскажет оптимальное решение – default locale Feb 19 '21 at 09:37
  • 1
    WARNING Плохое решение для WPF, так нельзя делать, теперь каждый второй мимопроходящий гуглер будет копировать это себе в проект. По сути данное решение - костыль, когда надо реализовать какое-то специфичное поведение контролов внутри DataTemplate. Работать с данными таким образом категорически плохо, это способ писать неподдерживаемый код. То есть дальшейшее внесение измений в прект будет ломать его, потому что любое измнение интерфейса будет требовать изменений в код-бихайнде. – aepot Feb 19 '21 at 09:41
  • @aepot В комментариях выше автор озвучил детали, можете опубликовать хорошее решение. – default locale Feb 19 '21 at 09:58
  • @aepot Предупреждения такого рода нужно писать в самом ответе, а не в комментариях. Правьте не стесняясь. Только тут надо иметь ввиду что люди которые придут в этот вопрос уже ищут как извлечь UI-элемент из шаблона ListBox. Им нужно вежливо объяснить в чем проблема с архитектурой и что им нужно делать вместо этого. – default locale Feb 19 '21 at 10:03
  • Нет смысла писать ответ на вопрос, в котором уже есть принятый ответ. Править не буду. Хорошее решение тоже дать не могу, потому что автор не ответил ни на один из моих уточняющих вопросов. Ну рано или поздно до автора дойдет то, о чем я пишу, а пока пусть будет как будет. – aepot Feb 19 '21 at 10:31