2

ComboBoxが埋め込まれたListBoxがあります。

<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
    <DataTemplate>
        <ComboBox Width="100" IsEditable="False" Height="20">
            <TextBlock Text="Opt#1"></TextBlock>
            <TextBlock Text="Opt#2"></TextBlock>
            <TextBlock Text="Opt#3"></TextBlock>
        </ComboBox>
    </DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

ListBox行が選択されていない場合はComboBoxを単純なテキスト(TextBlockなど)として表示し、ListBox行が選択されている場合はComboBoxとして表示したいと思います。

ComboBoxテンプレートを動的に置き換えるとうまくいくと思っていました。それを達成する方法は?

ありがとう、Leszek

4

3 に答える 3

0

テンプレートを交換する最良の方法は、ListBox の ItemTemplateSelector プロパティを使用し、DataTemplateSelector から継承する作成したクラスに設定することです。

例を提供するリンクは次のとおりです 。 http://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector.aspx

于 2012-04-16T14:33:58.473 に答える
0

が選択さListBox.ItemTemplateれるたびにを置き換えるスタイルを使用するだけです。ListBoxItem

ここに簡単な例があります

<ListBox.Resources>
    <DataTemplate x:Key="TextBoxTemplate">
        <TextBlock Text="{Binding }" />
    </DataTemplate>

    <DataTemplate x:Key="ComboBoxTemplate">
        <ComboBox SelectedItem="{Binding }">
            <ComboBoxItem>Opt#1</ComboBoxItem>
            <ComboBoxItem>Opt#2</ComboBoxItem>
            <ComboBoxItem>Opt#3</ComboBoxItem>
        </ComboBox>
    </DataTemplate>

    <Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="Template" Value="{StaticResource TextBoxTemplate}" />
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Template" Value="{StaticResource ComboBoxTemplate}" />
            </Trigger>
        </Style.Triggers>
    </Style>
</ListBox.Resources>

テンプレートを使用すると、アイテムを選択済みとして設定せずにそれらを操作できるため、トリガー プロパティとしてのIsKeyboardFocusWithin代わりに使用することをお勧めします。IsSelected

于 2012-04-16T15:02:23.453 に答える
0

私を正しい方向に向けてくれた Josh と Rachel に感謝します。

レイチェルが提案したものと同様の解決策を思いつきました。私の問題は、ItemTemplateSelector を機能させることができず、リストボックスから状態 IsSelected を渡す方法がわからなかったことです。また、ListBox アイテムは単一の要素よりもはるかに複雑であるため、DataTemplate を使用することもできませんでした (以前の投稿では、例のために単純化しました)。

とにかく、私は次の解決策を思いつきました。あまりエレガントではありませんが、機能します:

  1. Application リソースで新しいスタイルを定義しました。

    <Style x:Key="TextBlockTemplate" TargetType="ComboBox">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <TextBlock Text="{Binding}" Margin="3" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
  2. ListBox に SelectionChanged および PreviewMouseDown ハンドラーを追加しました。

  3. MyListBox_PreviewMouseDown を定義しました。

    private void MyListBox_PreviewMouseDown(オブジェクト送信者, MouseButtonEventArgs e)
    {
        // 選択されたリスト ボックス項目を取得します。
        オブジェクト要素 = (e.OriginalSource as FrameworkElement).DataContext;
        var item = MyListBox.ItemContainerGenerator.ContainerFromItem(要素)
            ListBoxItemとして;

        // ListBox の行を選択済みとしてマークします。
        if (項目 != null)
            item.IsSelected = true;
    }

  1. MyListBox_SelectionChanged を定義しました。
    プライベート コンボ ボックス prevComboBox = null;
    private void MyListBox_SelectionChanged(オブジェクト送信者、SelectionChangedEventArgs e)
    {
        // リスト ボックスを取得します。
        ListBox リスト = ListBox としての送信者;

        // 選択できる項目は 1 つだけですが、
        // 選択されたすべてのアイテムを繰り返し処理します。
        foreach (list.SelectedItems の MyDataItem データ)
        {
            var item = list.ItemContainerGenerator.ContainerFromItem(dat) as ListBoxItem;
            // FindElement は、ビジュアル ツリー内の要素を検索するためのヘルパー メソッドです。
            ComboBox cbo = FindElement(item, "MyComboBox") as ComboBox;

            if (cbo != prevComboBox)
            {
                cbo.Style = null;

                if (prevComboBox != null)
                    prevComboBox.Style =
                        (Style)Application.Current.Resources["TextBlockTemplate"];

                prevComboBox = cbo;
            }
        }
    }

ありがとう、レシェク

于 2012-04-18T00:45:40.093 に答える