2013-04-05 1 views
2

tabcontrol에서 탭 중 하나에 여러 탭 페이지가 있습니다. 콘텐츠에 텍스트 상자가 있습니다.WPF 컨트롤 탭을 클릭 할 때 포커스가 사라짐

이 텍스트 상자는 간단한 Path = PropertyName 및 UpdateSourceTrigger = LostFocus로 바인딩 된 내용입니다. LostFocus를 사용하는 이유는 Textbox의 Lost focus 이벤트를 잡아서 텍스트를 다시 포맷하기 때문입니다. 이것은 "시간"텍스트 상자이며 "0900"을 입력하면 "09:00"로 다시 포맷하려고합니다. 이 부분은 다음 컨트롤로 이동하기 위해 Tab 키를 누를 때 훌륭하게 작동하지만 "0900"을 입력하고 다른 탭 중 하나를 누르면 잃어버린 포커스를 누르고 텍스트 상자의 값을 다시 포맷하지만 바인딩 내 객체를 업데이트하기 위해 호출되지 않습니다. 탭으로 돌아 왔을 때 값이 공백으로 표시됩니다 (또는 개체의 원래 값으로 재설정 됨)

탭 페이지를 변경할 때 텍스트 상자가 바인딩 업데이트를 트리거하지 않는 이유는 무엇입니까?

참고 : 이는 손실 된 포커스 이벤트에 연결되는 일반 텍스트 상자에서도 발생합니다. 탭을 클릭하는 것과 관련이있는 것 같습니다.

[추가 코드] 더 노트 : 1. 나는 동적으로 탭 (즉, 그것을 함께 할 수있는 뭔가가 아닌지 확실하지) 2. 나는 프리즘을 사용하고의 탭 및 컨트롤을 만드는 오전 라이브러리

MainWindow를 XAML

<Window.Resources> 
    <DataTemplate DataType="{x:Type ctrls:myTextBoxDef}"> 
     <Grid Width="300"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="Auto" MinWidth="100" /> 
       <ColumnDefinition Width="*" /> 
      </Grid.ColumnDefinitions> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="28" /> 
      </Grid.RowDefinitions> 
      <TextBlock Grid.Column="0" 
        HorizontalAlignment="Stretch" 
        VerticalAlignment="Center" 
        Text="{Binding LabelText}" /> 

      <TextBox Grid.Column="1" 
       HorizontalAlignment="Stretch" 
       VerticalAlignment="Center" 
       Text="{Binding DocValue, 
           Mode=TwoWay, 
           ValidatesOnDataErrors=True, 
           UpdateSourceTrigger=LostFocus}" 
         /> 
     </Grid> 
    </DataTemplate> 
</Window.Resources> 


<Grid> 
    <TabControl HorizontalAlignment="Stretch" 
       VerticalAlignment="Stretch" 
       HorizontalContentAlignment="Stretch" 
       VerticalContentAlignment="Stretch" 
       IsTabStop="False"     
       ItemsSource="{Binding Tabs, Mode=OneWay}" 
       SelectedItem="{Binding SelectedTab, 
           Mode=TwoWay, 
           NotifyOnSourceUpdated=True}" 
       > 
     <TabControl.ItemTemplate> 
      <DataTemplate> 
       <Grid> 
        <TextBlock Margin="18,14,22,0"          
           Text="{Binding HeaderText}" /> 
       </Grid> 
      </DataTemplate> 
     </TabControl.ItemTemplate> 
     <!-- Content --> 
     <TabControl.ContentTemplate> 
      <DataTemplate> 
       <Grid> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="Auto" /> 
         <ColumnDefinition Width="Auto" /> 
        </Grid.ColumnDefinitions> 

        <AdornerDecorator Grid.Column="0"> 
         <ItemsControl Grid.Column="0" 
              HorizontalAlignment="Stretch" 
              VerticalAlignment="Stretch" 
              IsTabStop="False" 
              ItemsSource="{Binding Controls, 
                   Mode=OneWay}"> 
          <ItemsControl.ItemsPanel> 
           <ItemsPanelTemplate> 
            <WrapPanel Grid.Column="0" 
                Margin="10,5,0,0" 
                HorizontalAlignment="Stretch" 
                VerticalAlignment="Stretch" 
                Orientation="Vertical" /> 
           </ItemsPanelTemplate> 
          </ItemsControl.ItemsPanel> 
         </ItemsControl> 
        </AdornerDecorator> 
        </Grid> 
       </DataTemplate> 
      </TabControl.ContentTemplate> 
     </TabControl> 
    </Grid> 
</Window> 

주 창 코드

public partial class MainWindow : Window 
{ 
    private DataContextObject obj = new DataContextObject(); 
    public MainWindow() 
    { 
     InitializeComponent(); 

     myTextBoxDef txt1 = new myTextBoxDef(obj, "Textbox 1", "TAB1TextBox1"); 
     myTextBoxDef txt1b = new myTextBoxDef(obj, "Textbox 1 value", "TAB1TextBox1"); 

     myTextBoxDef txt2 = new myTextBoxDef(obj, "Textbox 2", "TAB1TextBox2"); 
     myTextBoxDef txt2b = new myTextBoxDef(obj, "Textbox 2 value", "TAB1TextBox2"); 

     obj.Tabs.Add(new myTabDef("Tab 1", new ObservableCollection<myTextBoxDef>() { txt1, txt2 })); 
     obj.Tabs.Add(new myTabDef("Tab 2", new ObservableCollection<myTextBoxDef>() { txt1b, txt2b })); 

     obj.SelectedTab = obj.Tabs[0]; 

     this.DataContext = obj; 
    } 
} 

지원 뒤에 객체들

public class DataContextObject : NotificationObject 
{ 
    List<myTabDef> _tabs = new List<myTabDef>(); 
    public List<myTabDef> Tabs 
    { 
     get 
     { 
      return _tabs; 
     } 
    } 

    private myTabDef _item; 
    public myTabDef SelectedTab 
    { 
     get 
     { return _item; } 
     set 
     { 
      _item = value; 
      this.RaisePropertyChanged("SelectedItem"); 
     } 
    } 

    private string _txt1 = ""; 
    public string TAB1TextBox1 
    { 
     get { return _txt1; } 
     set 
     { 
      _txt1 = value; 
      this.RaisePropertyChanged("TAB1TextBox1"); 
     } 
    } 

    private string _txt2 = ""; 
    public string TAB1TextBox2 
    { 
     get { return _txt2; } 
     set 
     { 
      _txt2 = value; 
      this.RaisePropertyChanged("TAB1TextBox2"); 
     } 
    } 

    private string _txt3 = ""; 
    public string TAB2TextBox1 
    { 
     get { return _txt3; } 
     set 
     { 
      _txt3 = value; 
      this.RaisePropertyChanged("TAB2TextBox1"); 
     } 
    } 
} 

public class myTabDef 
{ 
    public myTabDef(string tabText, ObservableCollection<myTextBoxDef> controls) 
    { 
     HeaderText = tabText; 
     _left = controls; 
    } 

    public string HeaderText { get; set; } 

    private ObservableCollection<myTextBoxDef> _left = new ObservableCollection<myTextBoxDef>(); 
    public ObservableCollection<myTextBoxDef> Controls 
    { 
     get 
     { 
      return _left; 
     } 
    } 
} 

public class myTextBoxDef : NotificationObject 
{ 
    public myTextBoxDef(NotificationObject bound, string label, string bindingPath) 
    { 
     LabelText = label; 
     Path = bindingPath; 
     BoundObject = bound; 

     BoundObject.PropertyChanged += BoundObject_PropertyChanged; 
    } 

    public string LabelText 
    { 
     get; 
     set; 
    } 

    public NotificationObject BoundObject 
    { 
     get; 
     set; 
    } 

    public string DocValue 
    { 
     get 
     { 
      return PropInfo.GetValue(BoundObject, null) as string; 
     } 
     set 
     { 
      PropInfo.SetValue(BoundObject, value, null); 
     } 
    } 

    protected virtual void BoundObject_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName.Equals(Path)) 
     { 
      this.RaisePropertyChanged("DocValue"); 
     } 
    } 

    public string Path 
    { 
     get; 
     set; 
    } 

    private PropertyInfo pi = null; 
    protected PropertyInfo PropInfo 
    { 
     get 
     { 
      if (pi == null && BoundObject != null && !string.IsNullOrEmpty(Path)) 
      { 
       PropertyInfo[] properties = BoundObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); 

       pi = properties.Where((prop) => string.Compare(prop.Name, Path, true) == 0).FirstOrDefault(); 
      } 

      return pi; 
     } 
    } 
} 
+0

포스트 코드를 게시하는 다른 링크입니다. 바인딩을위한 XAML과 get 및 – Paparazzi

+0

은 단순화 된 버전으로 작업합니다. 최대한 빨리 원래 게시물의 수정 사항으로 게시 할 예정입니다. – adondero

+0

코드를 추가하여 프로젝트를 만들면 탭 1에 두 개의 텍스트 상자가 표시되고 그 값도 Tab2에 표시됩니다. 첫 번째 텍스트 상자에 값을 입력하고 두 번째 텍스트 상자에 값을 입력하고 값을 입력하십시오. 두 번째 텍스트 상자를 탭 해제하기 전에 탭을 클릭하십시오. 탭 2는 텍스트 상자 1 값으로 업데이트되지만 텍스트 상자 2로 업데이트되지 않습니다. – adondero

답변