4

私が実際に達成しようとしているのは、コンボボックスをナビゲーション コントロールとして使用して、アクティブな TabItem を完全に制御することです。

これまでに得たものは次のとおりです。

    <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"/>

それでも実際に機能するのは、コンボボックスのトグルボタンを押したときに表示されるリストだけです。リストからタブアイテム名を選択しても何もせず、コンボボックスの選択された値のテキストボックスを更新することさえありません。

助けはありますか?

編集:「制御」の問題については、Steve Robbinsの答えがうまくいきました。

コンボボックスのドロップダウンリストでアイテムを選択してもコンボボックスの値が更新されないという事実はどうですか? (コンボボックスのテキストボックスはまだ空白です!!)

4

4 に答える 4

3

コンボから 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>
于 2009-02-13T14:40:07.483 に答える
1

コンボボックスでいくつかの問題が発生したため、これを見始めました。残念ながら、私は問題を解決していませんが、この問題に対する追加の洞察と回避策を提供できます。まず、元の xaml への変更から始めましょう。

    <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>

タブ コントロールから ComboBox へ、またはその逆のバインディングを作成する代わりに、タブ コントロールとコンボ コントロールの SelectedIndex の間に TwoWay バインディング (この場合のデフォルト) を作成できることに注意してください。次に、TabItems にコンテンツを追加しましょう。この時点で、Steve の提案と同様に、「制御」の問題を修正しました。つまり、選択された TabItem を変更すると、選択された ComboBox アイテムが変更され (これについて私を信頼するか、読み続ける必要があります!)、ComboBox を変更すると、選択された TabItem が変更されます。すごい!

上記の xaml は、DiplayMemberPath プロパティも "Name" に変更します。これにより、huhdbrown の「奇妙な結果」が解消されることがわかると思います。Header プロパティ (オブジェクト) が ContentPresenter によってラップされていることを思い出してください。テンプレートが提供されていない場合、デフォルトの動作は 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 に追加したコンテンツを利用します。このコードを実行すると、選択した TabItem のコンテンツが ComboBox に表示されることがわかります。さらに、リストには、TabItem ごとに "System.Windows.Controls.TabItem..." が表示されるようになりました。TextBlock バインディングを {Binding Header} に変更して Header オブジェクトを表示できますが、ComboBox には選択した TabItem のコンテンツが引き続き表示されます。金曜日の夜遅く、世界にはビールが十分にないため、考えられる理由を調べませんでした. ただし、回避策があります。

まず、TabControl の Items コレクションを使用できるものに変換する ValueConverter を作成しましょう。これがコードです。

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
}

コンバーターは、各 TabItem の文字列化された Header オブジェクトを含む TabControl の Items コレクションから新しいコレクションを作成するだけです。これは、単純な 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 コンテンツを選択として表示する理由です。明らかな説明があることは間違いありませんが、私が言ったように、それは金曜日です...

お役に立てれば!

于 2009-09-19T01:40:33.407 に答える
0

私はこれでたくさん遊んできました。選択が行われた後に ComboBox のデータバインディングのソースが変更されることについて何かがあります。か何か。

Diagnostics 名前空間を追加しました。

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

そして、 <Grid /> を大きなクラクションの数字を持つ TextBoxes に変更して、物事が実際に変化していることを確認できるようにしました。

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

アプリを実行すると、Diagnostics が奇妙な結果を報告することがわかりました。

System.Windows.Data エラー: 39: BindingExpression パス エラー: 'ヘッダー' プロパティが 'オブジェクト' ''TextBlock' (Name='tb1')' に見つかりません。BindingExpression:Path=ヘッダー; DataItem='TextBlock' (Name='tb2'); ターゲット要素は 'TextBlock' (Name='') です。ターゲット プロパティは 'Text' (タイプ '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";
    }

また、TabItem の選択と変更が行われた後も、選択されたアイテムを表示しないように CombobBox を切り替えます。TabControl が選択を変更した後、DataContext が TabControl.TabItem.TextBlock に切り替えられたかのようです。

ですから、正確な答えはありませんが、取り組むべき結果がいくつかあります。

Bea Stollnitz には、この診断手法の使用に関する優れた記事があります。「WPF バインディングをデバッグするにはどうすればよいですか?」

于 2009-02-16T03:32:17.737 に答える
0

Huhdbrown の回答に基づいて、MSDN でこの投稿を見つけました。これは、あなたの問題をバグとして説明しています。この 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>

ご覧のとおり、Length バインディングは、ドロップダウンを除いて正常に機能します。ドロップダウンでは、内部の文字列ではなく、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>
于 2009-02-16T22:46:51.927 に答える