2009-02-13 55 views
4

我真正想要實現的是通過使用組合框作爲導航控件來完全控制活動的TabItem。用組合框控制TabControl活動標籤

這裏是香港專業教育學院走到這一步:

<TabControl Canvas.Left="26" Canvas.Top="27" Height="100" Name="TabControl1" Width="220"> 
     <TabItem Header="TabItem1" x:Name="TabItem1"> 
      <Grid /> 
     </TabItem> 
     <TabItem Header="TabItem2" x:Name="TabItem2"> 
      <Grid /> 
     </TabItem> 
    </TabControl> 


    <ComboBox Canvas.Left="126" Canvas.Top="134" Height="23" Name="CmbTabs" Width="120" 
       ItemsSource="{Binding ElementName=TabControl1, Path=Items}" 
       SelectedValue="{Binding ElementName=TabControl1, Path=SelectedIndex}" 
       SelectedValuePath="TabIndex" 
       DisplayMemberPath="Header"/> 

仍然是唯一的東西,實際工作原理是當我按下組合框的切換按鈕,顯示在列表。 即使通過列表選擇tabitem名稱也不會執行任何操作,它甚至不更新組合框的選定值文本框。

任何幫助?

編輯: 好的,史蒂夫羅賓斯的答案在「控制」問題上工作得很好。

在combobox下拉列表中選擇一個項目不會更新組合框的值,那麼怎麼樣? (組合框文本框仍然是空白的!)

+0

你發現DisplayMemberPath =「Header」爲什麼不起作用嗎? – Coder14 2015-05-21 13:58:27

回答

3

如果您試圖從Combo控制TabControl,那麼它會向後看起來有點向後..如果您更改選項卡控件上的SelectedIndex以將其綁定到組合它應該工作:

<TabControl Canvas.Left="26" Canvas.Top="27" Height="100" Name="TabControl1" Width="220" SelectedIndex="{Binding ElementName=CmbTabs, Path=SelectedIndex}"> 
     <TabItem Header="TabItem1" x:Name="TabItem1"> 
      <Grid /> 
     </TabItem> 
     <TabItem Header="TabItem2" x:Name="TabItem2"> 
      <Grid /> 
     </TabItem> 
    </TabControl> 
0

我一直在玩這個很多。在選擇之後,ComboBox的數據綁定的來源有所變化。或者其他的東西。

我增加了診斷的命名空間:

xmlns:debug="clr-namespace:System.Diagnostics;assembly=WindowsBase" 

我改變了你的<網/ >與大鳴喇叭數字文本框,這樣我可以看到這樣的東西真的正在發生變化:

<TabItem Header="TabItem1" x:Name="TabItem1"> 
     <TextBlock Name="tb1" FontSize="24" Text="1" Width="100" Height="26" /> 
    </TabItem> 

而且當我運行應用程序時,我發現Diagnostics報告了一個奇怪的結果:

System.Windows.Data Error: 39 : BindingExpression path error: 'Header' property not found on 'object' ''TextBlock' (Name='tb1')'. BindingExpression:Path=Header; DataItem='TextBlock' (Name='tb2'); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

我試圖設置綁定一次,代碼,在啓動時:

public Window1() 
    { 
     InitializeComponent(); 

     Binding positionBinding = new Binding("Items"); 
     positionBinding.ElementName = "TabControl1"; 
     positionBinding.Path = new PropertyPath("Items"); 
     positionBinding.Mode = BindingMode.OneTime; 

     CmbTabs.SetBinding(ComboBox.ItemsSourceProperty, positionBinding); 
     CmbTabs.DisplayMemberPath = "Header"; 
    } 

它仍然切換CombobBox的選擇和TabItem的變化後沒有顯示出所選項目而成。就好像在TabControl改變選擇後DataContext切換到TabControl.TabItem.TextBlock。

所以我不完全有你的答案,但我有一些結果讓你去工作。

Bea Stollnitz在使用這種診斷技術方面有很好的文章。 "How can I debug WPF bindings?"

0

關於hughdbrown的回答,我找到了this post on MSDN,它描述了你的問題是一個bug。您可以使用此XAML複製它(其中有相反的問題,因爲你的XAML):

<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <TabControl Name="TabControl1" Width="220" Height="100" Canvas.Left="26" Canvas.Top="27"> 
     <TabItem x:Name="TabItem1" Header="TabItem1"> 
      foobar 
     </TabItem> 
     <TabItem x:Name="TabItem2" Header="TabItem2"> 
      fizzbuzz 
     </TabItem> 
    </TabControl> 
    <ComboBox Name="CmbTabs" Width="120" Height="23" Canvas.Left="126" Canvas.Top="134" 
       ItemsSource="{Binding ElementName=TabControl1, Path=Items}" 
       DisplayMemberPath="Length" 
       SelectedIndex="{Binding ElementName=TabControl1, Path=SelectedIndex}"/> 
</Canvas> 

正如你所看到的長度綁定工作正常,除了在下拉列表中,它會關閉的TabItem代替字符串裏面。

我不知道它是非常適合你的目的,但你可以是少一點,優雅與ComboBoxItems重現你的頭繞過它:

<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <TabControl Name="TabControl1" Width="220" Height="100" Canvas.Left="26" Canvas.Top="27"> 
     <TabItem x:Name="TabItem1" Header="TabItem1"> 
      <Grid/> 
     </TabItem> 
     <TabItem x:Name="TabItem2" Header="TabItem2"> 
      <Grid/> 
     </TabItem> 
    </TabControl> 
    <ComboBox Name="CmbTabs" Width="120" Height="23" Canvas.Left="126" Canvas.Top="134" 
       SelectedIndex="{Binding ElementName=TabControl1, Path=SelectedIndex}"> 
     <ComboBoxItem>TabItem1</ComboBoxItem> 
     <ComboBoxItem>TabItem2</ComboBoxItem> 
    </ComboBox> 
</Canvas> 
0

我開始因爲一些問題看這個我正在用組合框。不幸的是,我沒有解決我的問題,但我可以提供一些額外的見解和解決此問題的方法。首先,讓我開始對原始xaml進行更改。而不是創建從標籤控制到ComboBox的結合,並且反之亦然,我們可以將標籤和組合控制的selectedIndex之間建立一個雙向綁定(在這種情況下,默認)

<TabControl Height="100" Name="TabControl1" Width="220"> 
     <TabItem Header="TabItem1" x:Name="TabItem1"> 
      <TextBlock Text="TabItem1 Content" /> 
     </TabItem> 
     <TabItem Header="TabItem2" x:Name="TabItem2"> 
      <TextBlock Text="TabItem2 Content" /> 
     </TabItem> 
    </TabControl> 


    <ComboBox Height="23" Name="CmbTabs" Width="120" 
     ItemsSource="{Binding ElementName=TabControl1, Path=Items}" 
     SelectedIndex="{Binding ElementName=TabControl1, Path=SelectedIndex}" 
     DisplayMemberPath="Name" 
     > 
    </ComboBox> 

注意。接下來,我們添加一些內容到TabItems。在這一點上,類似於史蒂夫的建議,我們已經解決了「控制」問題。也就是說,更改選定的TabItem會更改選定的組合框項目(您必須信任此項或繼續閱讀!),並且更改組合框會更改所選的TabItem。大!

上述xaml還將DiplayMemberPath屬性更改爲「名稱」。我想你會發現這消除了hughdbrown的「怪異結果」。回想一下,ContentPresenter封裝了Header屬性(一個對象)。我相信,如果沒有提供模板,默認行爲是將Header對象顯示爲TextBlock中的字符串。因此,「奇怪的結果」正確地報告TextBlock控件不包含Header屬性。

現在讓我們對之前的ComboBox xaml進行一些更改。

<ComboBox Height="23" Name="CmbTabs" Width="120" 
     ItemsSource="{Binding ElementName=TabControl1, Path=Items}" 
     SelectedIndex="{Binding ElementName=TabControl1, Path=SelectedIndex}" 
     > 
     <ComboBox.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding}"/> 
      </DataTemplate> 
     </ComboBox.ItemTemplate> 
    </ComboBox> 

這實際上產生了一個有趣的結果,並利用我們添加到每個TabItem的內容。當此代碼運行時,您會注意到ComboBox現在顯示選定的TabItem的內容。此外,列表現在爲每個TabItem顯示「System.Windows.Controls.TabItem ...」。我們可以將TextBlock綁定更改爲{Binding Header}並顯示Header對象,但ComboBox仍然顯示所選TabItem的內容。由於週五晚上已經很晚了,世界上沒有足夠的啤酒,我沒有看到可能的原因。不過,我有一個解決方法!

首先,我們創建一個ValueConverter,將TabControl的Items集合轉換爲我們可以使用的東西。這是代碼。

public class TabItemCollectionConverter : IValueConverter 
{ 
    #region IValueConverter Members 

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     ItemCollection collection = value as ItemCollection; 
     IList<string> names = new List<string>(); 
     foreach (TabItem ti in collection.SourceCollection) 
     { 
      names.Add(ti.Header.ToString()); 
     } 
     return names; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 

    #endregion 
} 

轉換器只需從TabControl的的項目集合,其中包含從每個TabItem的字符串,美化版標題對象創建一個新的集合。這對於簡單的Header對象工作正常,但顯然有侷限性。現在讓我們考慮一下我們如何在xaml中使用它。

<ComboBox Height="23" Name="CmbTabs" Width="120" 
     ItemsSource="{Binding ElementName=TabControl1, Path=Items, Converter={StaticResource ItemConverter}}" 
     SelectedIndex="{Binding ElementName=TabControl1, Path=SelectedIndex}" 
     > 
     <ComboBox.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding}"/> 
      </DataTemplate> 
     </ComboBox.ItemTemplate> 
    </ComboBox> 

請記住,在ItemsSource綁定中使用的ValueConverter會返回一個新集合。在這種情況下,我們將TabControl的Items集合轉換爲一個字符串集合。不要忘記創建轉換器StaticResource!它看起來像這樣。

<local:TabItemCollectionConverter x:Key="ItemConverter"/> 

現在,使用轉換器,整個蠟球按預期工作。

讓我感到困惑的是,爲什麼ComboBox在列表中顯示TabItem標題,而TabItem的內容顯示爲選擇內容。毫無疑問,有一些明顯的解釋,但正如我所說,這是星期五...

希望這有助於!

+0

我剛剛注意到羅伯特的帖子中,他提供了一個鏈接,聲稱ComboBox當前項目顯示的問題是一個錯誤。感謝羅伯特救了我一些頭/牆撞! – dan 2009-09-19 01:48:40