Здравствуйте!
Использую паттерн MVVM, и раньше не попадалось на глаза, т.к. все элементы управления были забиндены к слою вью-модел.
Пусть есть VM у которой есть список вкладок — элементов типа таб(тоже слой VM).
public class Shell : INotifyPropertyChanged
{
private ObservableCollection<Tab> _tabs;
public IList<Tab> Tabs
{
get { return _tabs ?? (_tabs = new ObservableCollection<Tab>()); }
}
private Tab _cu;
public Tab Current
{
get { return _cu; }
set
{
if (_cu == value) return;
_cu = value;
OnPropertyChanged("Current");
}
}
protected void OnPropertyChanged(string propertyName)
{
var h = PropertyChanged;
if (null != h) h(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class Tab : INotifyPropertyChanged
{
private string _header;
public string Header
{
get { return _header; }
set
{
if (_header == value) return;
_header = value;
OnPropertyChanged("Header");
}
}
protected void OnPropertyChanged(string propertyName)
{
var h = PropertyChanged;
if (null!=h)h(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Создание:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new Shell();
vm.Tabs.Add((vm.Current=new Tab{Header = "tab1"}));
vm.Tabs.Add(new Tab { Header = "tab2" });
vm.Tabs.Add(new Tab { Header = "tab3" });
DataContext = vm;
}
}
И собственно биндинг:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="525">
<ScrollViewer>
<ScrollViewer.Resources>
<Style TargetType="TabControl" x:Key="style1" x:Shared="false">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel>
<Label>Not Bounded:</Label>
<TextBox></TextBox>
<Label>Bounded:</Label>
<TextBox Text="{Binding Header,UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ScrollViewer.Resources>
<StackPanel>
<Label>Direct Set</Label>
<TabControl Height="150" ItemsSource="{Binding Tabs}" SelectedItem="{Binding Current}">
<TabControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Header}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<StackPanel>
<Label>Not Bounded:</Label>
<TextBox></TextBox>
<Label>Bounded:</Label>
<TextBox Text="{Binding Header,UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
<Label>Using Styles</Label>
<TabControl Style="{StaticResource style1}" Height="150" ItemsSource="{Binding Tabs}" SelectedItem="{Binding Current}">
<TabControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Header}"/>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
</StackPanel>
</ScrollViewer>
</Window>
Шаблон для вкладки — 2 текстбокса, первый никуда не биндится, второй — к свойству Header из VM Tab.
При переключении вкладок, незабинденный текстбок сохраняет свое значение. Т.е. нет сохранения.
Забинденный — соотвественно меняет.
http://clip2net.com/s/5ap2Zo
http://clip2net.com/s/5ap4wz
Такое впечатление, что визуальное дерево шаблона строится один раз и при переключении вкладок не перестаривается, а лишь "подцепляются" значения из VM. Можно ли как-нибудь изменить такое поведение? Может быть какие-нибуть прикрепленные свойства?
С уважением, Иван.
Совершенно отлично и ожидаемо работает пример без использования шаблонов)
<TabControl>
<TabItem Header="1">
<TextBox/>
</TabItem>
<TabItem Header="2">
<TextBox/>
</TabItem>
<TabItem Header="3">
<TextBox/>
</TabItem>
</TabControl>
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.