[WPF] TabControl не сохраняет значения вводимых данных
От: WSN Россия  
Дата: 03.06.13 15:01
Оценка:
Здравствуйте!

Использую паттерн 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. Можно ли как-нибудь изменить такое поведение? Может быть какие-нибуть прикрепленные свойства?

С уважением, Иван.
wpf tabcontrol shares data
Re: [WPF] TabControl не сохраняет значения вводимых данных
От: WSN Россия  
Дата: 03.06.13 15:28
Оценка:
Нашел проблемку, но решение не выходит(

http://stackoverflow.com/questions/3485789/tabcontrols-tabitems-sharing-same-content-do-not-want
Re: [WPF] TabControl не сохраняет значения вводимых данных
От: WSN Россия  
Дата: 03.06.13 15:39
Оценка:
Совершенно отлично и ожидаемо работает пример без использования шаблонов)


<TabControl>
        <TabItem Header="1">
          <TextBox/>
        </TabItem>
        <TabItem Header="2">
          <TextBox/>
        </TabItem>
        <TabItem Header="3">
          <TextBox/>
        </TabItem>
      </TabControl>
Re: [WPF] TabControl не сохраняет значения вводимых данных
От: WSN Россия  
Дата: 03.06.13 16:49
Оценка:
Нашел интересную статейку

http://www.codeproject.com/Articles/460989/WPF-TabControl-Turning-Off-Tab-Virtualization

но всё это конеш очень странно..
Re: [WPF] TabControl не сохраняет значения вводимых данных
От: TK Лес кывт.рф
Дата: 03.06.13 21:45
Оценка:
Здравствуйте, WSN, Вы писали:

WSN>Такое впечатление, что визуальное дерево шаблона строится один раз и при переключении вкладок не перестаривается, а лишь "подцепляются" значения из VM. Можно ли как-нибудь изменить такое поведение? Может быть какие-нибуть прикрепленные свойства?


"Подцепите" состояние со стороны. Состояние можно сохранить в TabItem (например, ExpandoObject в Tag или attached свойстве) и сделать конвертер который через ItemContainerGenerator найдет выбранный TabItem и expando из него.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[2]: [WPF] TabControl не сохраняет значения вводимых данных
От: WSN Россия  
Дата: 04.06.13 06:02
Оценка:
Здравствуйте, TK, Вы писали:

TK>"Подцепите" состояние со стороны. Состояние можно сохранить в TabItem (например, ExpandoObject в Tag или attached свойстве) и сделать конвертер который через ItemContainerGenerator найдет выбранный TabItem и expando из него.


Это хорошо работает для простых случаев, я столкнулся с таким поведением когда делал самописный AutocompleteControl, и использовал текстбокс для задания паттерна, список подстановок генерировался вьюмоделью и я не захотел биндить Pattern к свойству VM, потому что посчитал, что это не задача этого контрола, VM не важно что вводит пользователь, она предоставляет делегат для генерации подстановок. Ну вот и получилось что если этот Автокомплит использовать в пределах одного табконтрола на разных вкладках, то текстбокс при переключении принимает одно и тоже значение) Ладно, костыли для этой ситуации придумать можно, другое дело, что забавное поведение и стандартно както его не особо изменишь, что ни день с WPF, то чтото новое, неожиданное) Спасибо за ответ.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.