2015-05-19 251 views
0

我一直在尋找解決這個問題的小時。 我有IM使用填充選項卡控制WPF數據綁定用戶控件

public partial class TabAdapter : UserControl 
{ 
    public static readonly DependencyProperty fileNameProperty = 
     DependencyProperty.Register(
      "fileName", 
      typeof(string), 
      typeof(TabAdapter), 
      new FrameworkPropertyMetadata(
       string.Empty, 
       FrameworkPropertyMetadataOptions.AffectsRender, 
       new PropertyChangedCallback(OnFileNamePropertyChanged), 
       new CoerceValueCallback(coerceFileName) 
       ), 
      new ValidateValueCallback(fileNameValidationCallback) 
     ); 

    public TabAdapter() 
    { 
     InitializeComponent(); 
     //initializeInterior(); 
     CreateSaveCommand(); 
     TabAdapterContent.DataContext = this; 
     Console.WriteLine("constructor hit."); 
    } 

    public string fileName 
    { 
     get { return (string)GetValue(fileNameProperty); } 
     set { SetValue(fileNameProperty, value); } 
    } 

    private ColumnMapper _columnMap; 

    private TableMapper _tableMap; 

    private TabType tabType; 

    private enum TabType { TABLE_MAPPER, COLUMN_MAPPER, ERROR_MSG } 

    private static object coerceFileName(DependencyObject d, object value) 
    { 
     return fileName; 
    } 

    private static bool fileNameValidationCallback(object Value) 
    { 
     string fn = (string)Value; 
     if (fn.Equals(string.Empty)) 
     { 
      return true; 
     } 
     FileInfo fi = new FileInfo(fn); 
     return ((fi.Exists && fi.Extension.Equals(".csv"))); 
    } 

    private static void OnFileNamePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs args) 
    { 
     TabAdapter source = d as TabAdapter; 
     Console.WriteLine("got to property changer: " + (string)args.NewValue + " :new/old: " + (string)args.OldValue); 
     source.initializeInterior(); 
    } 

    private void initializeInterior() 
    { 
     Console.WriteLine("initializing Interior filename: " + fileName); 
     if (Regex.IsMatch(fileName, @".*_SourceTableMapping.csv$")) 
     { 
      tabType = TabType.TABLE_MAPPER; 
      _tableMap = new TableMapper(fileName); 
      Grid.SetRow(_tableMap, 0); 
      Grid.SetColumn(_tableMap, 0); 
      //clear out the content. 
      this.TabAdapterContent.Children.Clear(); 
      //add new content 
      this.TabAdapterContent.Children.Add(_tableMap); 
     } 
     else if (fileName.EndsWith(".csv")) 
     { 
      tabType = TabType.TABLE_MAPPER; 
      _columnMap = new ColumnMapper(fileName); 
      Grid.SetRow(_columnMap, 0); 
      Grid.SetColumn(_columnMap, 0); 
      //clear out the content. 
      this.TabAdapterContent.Children.Clear(); 
      //add new content 
      this.TabAdapterContent.Children.Add(_columnMap); 
     } 
     else 
     { 
      tabType = TabType.ERROR_MSG; 
      TextBlock tb = new TextBlock(); 
      tb.Text = "The File: " + fileName + " is not a valid mapping file."; 
      Grid.SetRow(tb, 0); 
      Grid.SetColumn(tb, 0); 
      //clear out the content. 
      this.TabAdapterContent.Children.Clear(); 
      //add new content 
      this.TabAdapterContent.Children.Add(tb); 
     } 
    } 
} 

的這點是確定被添加的文件的類型和加載了正確的用戶控制其內部,以顯示文件中的選項卡適配器類。

我的選項卡控件主窗口XAML是

<TabControl x:Name="tabControl" Grid.Column="1" Grid.Row="0" ItemsSource="{Binding openFileNames, Mode=OneWay}"> 
      <TabControl.LayoutTransform> 
       <!-- Allows to zoom the control's content using the slider --> 
       <ScaleTransform CenterX="0" 
        CenterY="0" /> 
       <!-- part of scale transform ScaleX="{Binding ElementName=uiScaleSlider,Path=Value}" 
        ScaleY="{Binding ElementName=uiScaleSlider,Path=Value}" />--> 
      </TabControl.LayoutTransform> 
      <!-- Header --> 
      <TabControl.ItemTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Header}" /> 
       </DataTemplate> 
      </TabControl.ItemTemplate> 
      <!-- Content --> 
      <TabControl.ContentTemplate> 
       <DataTemplate> 
        <local:TabAdapter fileName="{Binding fileName}" /> 
       </DataTemplate> 
      </TabControl.ContentTemplate> 
     </TabControl> 

頭的作品,如果我改變

<local:TabAdapter fileName="{Binding fileName}" /> 

<TextBlock Text="{Binding fileName}" /> 

然後一切都正確地結合,我有一種感覺,它與我的選項卡適配器上的數據上下文有關。但並不完全確定需要設置什麼。

我對選項卡適配器XAML是

<UserControl x:Class="ImportMappingGui.TabAdapter" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300"> 
<Grid x:Name="TabAdapterContent"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height = "*" /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*" /> 
    </Grid.ColumnDefinitions> 
</Grid> 

它都將編譯和運行,但只有用戶控件的構造函數中被擊中,在那個只有一次,無論多少標籤我創造。 這是我的第一個WPF應用程序,所以我很抱歉,如果它是愚蠢的我想念的東西。 (或者如果我設置各種適配器的方法不是解決此問題的最佳方法)。

+0

如果你[使用Snoop](http://snoopwpf.codeplex.com),它表明TabControl的DataContext被設置爲什麼? –

回答

0

請勿在UserControl本身內設置的。它擊敗了「無形」控制的全部內容,可用於顯示任何通過它的內容。

fileName綁定失敗,因爲DataContext = this,並thisTabAdapter控制本身,TabAdapter.fileName實際上不設置任何東西。 (請記住,綁定以告訴屬性在其他位置檢索其值是不同於直接設置值)

至於構造函數不會運行多次,這是設計。既然您告訴TabControl使用TabAdapter控件作爲模板,它將創建TabAdapter的一個副本,並且只要切換標籤即可簡單替換控件背後的.DataContext。這可以提高性能,因爲它不必爲每個選項卡進行初始化和跟蹤單獨控制,並減少了使用的內存。