#wpf #silverlight #xaml #datatemplate #tabcontrol
#wpf #серебристый свет #xaml #datatemplate #tabcontrol #silverlight
Вопрос:
Если вы помещаете элементы управления в свой DataTemplate, почему их отдельные состояния копируются или отражаются на каждой вкладке в TabControl? Вы меняете его на одной вкладке, все остальные вкладки отражают, почему это так ?! Мне кажется, TabControl инициализирует только один шаблонный ContentControl, и каждый щелчок по вкладке копирует все содержимое в нем заново, оставляя старые controlstates нетронутыми. Чтобы понять, что я имею в виду, подумайте о том, чтобы поместить это в свой XAML-Pad:
<TabControl>
<TabControl.ContentTemplate>
<DataTemplate>
<Border>
<TextBox Text="test"/>
</Border>
</DataTemplate>
</TabControl.ContentTemplate>
<TabItem Header="Tab1"/>
<TabItem Header="Tab2"/>
</TabControl>
Он создаст TabControl с двумя шаблонными вкладками. Теперь введите что-то в текстовое поле и переключитесь на другую вкладку, введенный текст будет перенесен. Теперь каждая вкладка будет иметь одинаковое содержимое. Я не наблюдаю такого же поведения в ListBox или любом другом элементе управления, и это очень затрудняет практическую работу, потому что каждый маленький бит должен быть привязан к ViewModel, чтобы его можно было использовать в TabControl. Я заметил это странное поведение, когда расширители, которые я использовал в DataTemplate, открывались на всех моих вкладках, хотя я специально обратился к одной. В качестве обходного пути мне пришлось привязать «IsExpanded» к свойству в ViewModel, но это действительно отстой, когда приходится это делать.
Кто-нибудь знает, что здесь происходит?
РЕШЕНИЕ
<TabControl x:Name="MainTab" SelectedIndex="0"/>
...
Collection.CollectionChanged = new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Collection_CollectionChanged);
...
void Collection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
TabItem MyNewItem = new TabItem();
ContentPresenter MyContentPresenter = new ContentPresenter();
MyContentPresenter.ContentTemplate = (DataTemplate)this.FindResource("MyTemplate");
MyContentPresenter.Content = e.NewItems[0];
MyNewItem.Content = MyContentPresenter;
MainTab.Items.Add(MyNewItem );
}
}
Комментарии:
1. Я думаю, что свойства ContentTemplate и ItemTemplate должны применяться к элементам свойства ItemsSource, а не к явно определенным элементам. Но встроенный TabControl не имеет свойства ItemsSource, поэтому вы можете использовать расширенный TabControl: vortexwolf.wordpress.com/2011/04/09 /. … Но я не знаю, что не так с этим конкретным примером. В любом случае элемент управления вкладками silverlight отличается от своего аналога в WPF, так что, возможно, это ошибка.
2. Я попытался применить шаблон к самому TabItem, что дает тот же результат. TabControl в WPF, по крайней мере, имеет ItemsSource, который я использую для его заполнения. В вашей расширенной версии элементы управления внутри DataTemple не переносят свои состояния? Вы пробовали поставить флажок или что-то в этом роде и посмотреть, идет ли одна проверка для всех? Я мог бы попробовать … спасибо за ваше время и наилучшие пожелания
Ответ №1:
Поведение идеально, и есть способ решить эту проблему. DataTemplate должен использоваться только в случае привязки. Когда вы назначаете источник перечислимых элементов элементу управления вкладками, ваш шаблон данных должен и будет состоять из одно- или двухсторонних привязок. В случае текстового поля это должна быть двусторонняя привязка.
TabControl делает это для экономии памяти, в случае шаблона данных управление остается неизменным при переключении вкладки, но изменяется лежащий в основе связанный datacontext, а привязка отражает правильные данные. Таким образом, визуально вы чувствуете, что вкладка изменилась, но на самом деле меняются только данные, однако управление остается прежним. Это называется виртуализацией пользовательского интерфейса.
В вашем случае вам не следует использовать шаблон данных, если вы не привязываете что-либо к источнику элементов. В противном случае вы должны использовать стиль контейнера элемента.
Комментарии:
1. Ну, тогда в таком случае, почему бы вам не создать отдельные элементы вкладки и не добавить их в качестве дочерних элементов элемента управления вкладками? Я понимаю, что вы пытаетесь сделать, но в этом случае вы не можете сохранить состояние редактирования. Если вы определяете шаблон данных, то каждый раз, когда вы будете переключаться, элемент вкладки будет выгружен и будет загружен новый элемент, и если вы поместите трассировку в событие загрузки, оно будет запускаться при каждом переключении. Такое поведение характерно для визуального представления с привязкой к данным, но если вы говорите о редактировании состояния, то само состояние становится данными.
2. Если элемент управления вкладкой содержит элемент вкладки с элементом пользовательского интерфейса, он сохранит все.
3. Проблема в том, что вам нужно привязать все, а не только содержимое. В моей программе я использую привязки к данным, и, конечно, содержимое не переключается, но все остальное меняется. Например, положение полосы прокрутки в списке, выбранный элемент, состояние расширителя и т. Д., И т. Д., И т. Д. Это делает его практически непригодным для использования и сбивает с толку моих клиентов. 🙁
4. О, я извиняюсь, поэтому не позволил мне изменить свой комментарий, поэтому я удалил и создал новый, слишком поздно. Я попробую это сейчас, большое вам спасибо!! (-:
5. Это работает! большое спасибо, я быстро найду решение!
Ответ №2:
TabControls в WPF немного неприятны в работе. Во-первых, при переключении вкладок он уничтожает все на первой вкладке и загружает элементы управления для 2-й вкладки. Единственное, что не удаляется / не воссоздается, — это элементы управления, которые существуют на всех вкладках, такие как текстовое поле, созданное в шаблоне TabItem.
Таким образом, ваше текстовое поле повторно используется на других вкладках и с текстового поля.Текст ни к чему не привязан, он остается неизменным при переключении вкладок.
Чтобы изменить это поведение, либо привяжите текстовое поле.Текстовое значение для чего-либо или создайте каждый элемент TabItem с его собственной версией текстового поля.
<TabControl>
<TabItem Header="Tab1">
<local:TabControlContent />
</TabItem>
<TabItem Header="Tab2">
<local:TabControlContent />
</TabItem>
</TabControl>
Комментарии:
1. Большое спасибо, это, по крайней мере, объясняет это! Но, как я писал ранее, простого привязывания содержимого, по-видимому, недостаточно, поскольку также переносится каждое видимое состояние, позиции полосы прокрутки, выбранные элементы, расширенные состояния и т. Д. Это означало бы, что мне пришлось бы раздувать мою ViewModel мусором. Я серьезно рассматриваю возможность написания TabControl самостоятельно, я понятия не имею, как они могли бы выпустить его таким образом. 🙁
2. @hpalu Самым простым способом, вероятно, было бы создать
UserControl
ваш TabContent, а затем установить содержимое каждого TabItem в новый экземпляр UserControl. Это должно содержать отдельные экземпляры каждой вкладки, хотя не связанные значения, такие как позиции списка и расширенные значения, будут сброшены при переключении вкладок. Для поддержания этих значений я обычно использую расширенный TabControl, найденный здесь: pluralsight-training.net/community/blogs/eburke/archive/2009/04 /…3. Вау, большое спасибо, Рейчел! Если это поможет избавить меня от необходимости писать свою собственную версию, я был бы очень признателен. : D
4. Рейчел, я использовал решение Akashs, это избавляет меня от многих проблем прямо сейчас, но я все еще читаю материал, который вы мне прислали, еще раз большое спасибо!