Проблема WPF с элементами управления TreeView и Popup - PullRequest
3 голосов
/ 07 августа 2009

При использовании всплывающего окна внутри TreeView в WPF я сталкиваюсь с проблемой, когда элементы управления внутри всплывающего окна становятся непригодными для использования. Например, используя следующий код, ToggleButton внутри всплывающего окна может быть переключен только один раз, а затем не может быть переключен обратно. Есть ли способ обойти эту проблему?

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <TreeView>
            <TreeViewItem>
                <TreeViewItem.Header>
                    <StackPanel>
                        <ToggleButton>
                            Button outside popup
                        </ToggleButton>
                        <Popup IsOpen="True">
                            <ToggleButton>
                                Button inside popup
                            </ToggleButton>
                        </Popup>
                    </StackPanel>
                </TreeViewItem.Header>
            </TreeViewItem>
        </TreeView>
    </Grid>   
</Page>

Ответы [ 4 ]

3 голосов
/ 07 августа 2009

Проблема в том, что вы встраиваете Popup внутри TreeViewItem , и это каким-то образом мешает его встроенной функциональности. Я не думаю, что всплывающие окна предназначены для использования в любом случае. Поскольку вы можете указать PlacementTarget для всплывающего окна, вы можете объявить их где угодно, а затем открыть их в нужном месте. Следующая разметка демонстрирует это на вашем примере:

<StackPanel>
  <Popup IsOpen="True" PlacementTarget="{Binding ElementName=buttonPanel}"
         Placement="Bottom">
    <ToggleButton>
      Button inside popup
    </ToggleButton>
  </Popup>
  <TreeView>
    <TreeViewItem>
      <TreeViewItem.Header>
        <StackPanel Name="buttonPanel">
          <ToggleButton>
            Button outside popup
          </ToggleButton>
        </StackPanel>
      </TreeViewItem.Header>
    </TreeViewItem>
  </TreeView>
</StackPanel>

Как видите, всплывающее окно может быть объявлено где угодно. Затем вы можете использовать PlacementTarget, чтобы поместить его туда, где вы хотите. С этим изменением ToggleButton работает как положено.

1 голос
/ 18 ноября 2009

После обсуждения с командой WPF я обнаружил, что это просто проблема с WPF.

В моем случае я пытался создать диалоговое окно, которое используется для каждого TreeViewItem. Я поиграл с разными элементами управления, пытаясь получить нужный мне вид, и обнаружил, что всплывающая часть ComboBox отлично работает внутри TreeView.

Из-за этого я использовал ComboBox внутри TreeView и заставил ComboBox иметь только один элемент, который всегда выбран, и этот элемент был бы моим диалоговым окном. После этого мне просто нужно было оформить ComboBox так, чтобы он соответствовал нужному мне виду. Код ниже показывает общую идею того, что я сделал.

<TreeView>
    <TreeViewItem>
        <ComboBox HorizontalAlignment="Left" VerticalAlignment="Top">
            <ComboBox.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
            </ComboBox.Resources>
            <ComboBoxItem IsSelected="True">
                <StackPanel Orientation="Vertical">
                    <Label>Some stuff on the combobox popup</Label>
                    <RadioButton>Radio Button 1</RadioButton>
                    <RadioButton>Radio Button 2</RadioButton>
                    <CheckBox>Check Box</CheckBox>
                    <Button HorizontalAlignment="Right">Ok</Button>
                </StackPanel>
            </ComboBoxItem>
        </ComboBox>
    </TreeViewItem>
</TreeView>
1 голос
/ 07 августа 2009

Благодаря Чарли обнаружил проблему с использованием TreeView ...

Настройка Focusable на древовидной структуре на false также, кажется, работает. Но может вызвать у вас другие проблемы.

<TreeView Focusable="False">

Из того, что я могу сказать, проблема в том, какой элемент управления фокусируется, поэтому похоже, что ваше древо фокусируется на щелчке мыши вместо кнопки.

0 голосов
/ 18 января 2012

Ну, у меня была та же проблема, когда древовидное представление отображало иерархические элементы с использованием шаблона данных и нескольких пользовательских элементов управления, а один из пользовательских элементов управления - это кнопка переключения со всплывающим меню.

Это полностью замерзнет и не будет отвечать вообще. Проблема связана со свойством Focus, но установка Focusable на false не всегда работает.

Посмотрев на решения, представленные выше, мне понравился последний, который использует поле со списком внутри дерева. Но это приводит к еще одной проблеме. Всякий раз, когда пользователь выбирает (один) элемент комбинированного списка, он отображается в комбинированном списке как selectedValue, и я просто хочу вести себя как переключатель с всплывающим окном.

Также я хотел изменить треугольник на выпадающем списке на многоточие. Поэтому я попробовал это решение, изменив шаблон управления.

Вот мое решение:

... ...

    <Style x:Key="ComboBoxStyle1" TargetType="{x:Type ComboBox}">
        <Setter Property="FocusVisualStyle" Value="{StaticResource ComboBoxFocusVisual}"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
        <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
        <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
        <Setter Property="Padding" Value="4,3"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ComboBox}">
                    <Grid x:Name="MainGrid" SnapsToDevicePixels="true">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Popup x:Name="PART_Popup" Margin="1" 
                               AllowsTransparency="true" 
                               IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" 
                               Placement="Bottom" 
                               PopupAnimation="Fade">
                            <Microsoft_Windows_Themes:SystemDropShadowChrome x:Name="Shdw" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=MainGrid}" Color="Transparent">
                                <Border x:Name="DropDownBorder" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="2" CornerRadius="0,4,4,4">
                                    <ScrollViewer CanContentScroll="true">
                                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.DirectionalNavigation="Contained"/>
                                    </ScrollViewer>
                                </Border>
                            </Microsoft_Windows_Themes:SystemDropShadowChrome>
                        </Popup>
                        <ToggleButton Style="{StaticResource ComboBoxReadonlyToggleButton}" 
                                      Background="{TemplateBinding Background}" 
                                      BorderBrush="{TemplateBinding BorderBrush}" 
                                      IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
                            <Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/>
                            <Setter Property="Color" TargetName="Shdw" Value="#71000000"/>
                        </Trigger>
                        <Trigger Property="HasItems" Value="false">
                            <Setter Property="Height" TargetName="DropDownBorder" Value="95"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            <Setter Property="Background" Value="#FFF4F4F4"/>
                        </Trigger>
                        <Trigger Property="IsGrouping" Value="true">
                            <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="IsEditable" Value="true">
                <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
                <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
                <Setter Property="IsTabStop" Value="false"/>
                <Setter Property="Padding" Value="3"/>
            </Trigger>
        </Style.Triggers>
    </Style>
    <Style x:Key="ComboBoxItemStyle1" TargetType="{x:Type ComboBoxItem}">
        <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="Padding" Value="3,0,3,0"/>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                    <Border x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsHighlighted" Value="true">
                            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>
<TreeView >
    <TreeViewItem IsExpanded="True">
        <ComboBox HorizontalAlignment="Left" VerticalAlignment="Top"
                  IsEditable="False"
                  Style="{StaticResource ComboBoxStyle1}">
            <ComboBox.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
            </ComboBox.Resources>
            <ComboBoxItem IsSelected="False">
                <StackPanel Orientation="Vertical">
                    <Label>Some stuff on the combobox popup</Label>
                    <RadioButton>Radio Button 1</RadioButton>
                    <RadioButton>Radio Button 2</RadioButton>
                    <CheckBox>Check Box</CheckBox>
                    <Button HorizontalAlignment="Right">Ok</Button>
                </StackPanel>
            </ComboBoxItem>
        </ComboBox>
    </TreeViewItem>
</TreeView>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...