【问题标题】:Creating a WPF label with ComboBox editor in ControlTemplate在 ControlTemplate 中使用 ComboBox 编辑器创建 WPF 标签
【发布时间】:2015-04-12 04:14:56
【问题描述】:

我正在尝试创建一个 wpf 样式,该样式将使标签显示为普通标签,直到单击它进行编辑。单击它时,我希望它是一个组合框,由来自同一对象绑定的一组事物填充。我需要它尽可能通用以便重用。我对 wpf 比较陌生,并且确实在知道在哪里寻找它时遇到了问题。另外,我当前的解决方案是从互联网上窃取的,并使用文本块编辑器从类似的解决方案中修改。

我打算从用户控件中的 DataTemplate 中使用它。标签将在列表框的一行内。

<telerik:RadListBox
                Name="FileListBox"
                Margin="2"
                AllowDrop="True"
                SelectionMode="Single"
                ItemsSource="{Binding LeafNodes, Mode=OneWay}"
                ItemTemplate="{StaticResource FavoriteTemplateSelector}"
                >
            </telerik:RadListBox>

和数据模板。

<Window.Resources>
    <ResourceDictionary>

        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Project.Presentation;component/Styles/Styles.xaml" />
        </ResourceDictionary.MergedDictionaries>

        <DataTemplate x:Key="FavoriteTemplateSelector">
            <StackPanel Orientation="Horizontal">

                <Label 
                    HorizontalAlignment="Stretch"
                    VerticalAlignment="Center"
                    Content="{Binding Path=Parent}"
                    Style="{StaticResource EditableLabelComboStyle}"/>
                <!--other controls -->
            </StackPanel>
        </DataTemplate>

    </ResourceDictionary>
</Window.Resources>

因此,列表框中的 LeafNodes 绑定包含一个名为 Categories 的集合,我想用它来填充组合框。这是迄今为止我的样式控制模板中的内容。我相当确定我的问题在于我对 ComboBox ItemSource 缺乏了解。我确定我的 RelativeSource 是错误的,但我真的不知道从哪里开始。

<ControlTemplate x:Key="EditableComboBoxTemplate" TargetType="{x:Type ContentControl}">
    <ContentPresenter Name="contentHolder" 
                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                        RecognizesAccessKey="True" 
                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
        <ContentPresenter.Content>
            <Grid Margin="0">
                <Border Name="nonFocusedBorder"
                    Grid.ZIndex="3" IsHitTestVisible="False"
                    BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
                    Background="{TemplateBinding Background}" 
                    />
                <ComboBox Name="editComboBox"
                        Grid.ZIndex="1" Opacity="0"
                        Margin="0" Padding="{TemplateBinding Padding}"
                        HorizontalAlignment="Stretch" VerticalAlignment="Center"
                        ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content, Mode=TwoWay, NotifyOnTargetUpdated=True}"
                        BorderThickness="{TemplateBinding BorderThickness}" 
                        />
                <Border BorderBrush="{x:Null}" Height="{Binding ElementName=editComboBox, Path=ActualHeight}" Margin="0,0,3,0"
                    Padding="{TemplateBinding BorderThickness}">
                    <TextBlock Name="displayTextBox" 
                            Grid.ZIndex="2" IsHitTestVisible="False"
                            VerticalAlignment="Center" HorizontalAlignment="Stretch" 
                            Margin="{TemplateBinding Padding}"
                            TextAlignment="Right"
                            Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content, Mode=OneWay}"
                            />
                </Border>
                <Border/>
            </Grid>
        </ContentPresenter.Content>
    </ContentPresenter>
    <ControlTemplate.Triggers>
        <Trigger SourceName="editComboBox" Property="IsKeyboardFocused" Value="True">
            <Setter TargetName="displayTextBox" Property="Opacity" Value="0" />
            <Setter TargetName="editComboBox" Property="Opacity" Value="1" />
            <Setter TargetName="nonFocusedBorder" Property="Visibility" Value="Collapsed"/>
        </Trigger>
        <Trigger Property="BorderThickness" Value="0">
            <Setter TargetName="editComboBox" Property="BorderThickness" Value="1" />
            <Setter TargetName="nonFocusedBorder" Property="BorderThickness" Value="1" />
            <Setter TargetName="nonFocusedBorder" Property="BorderBrush" Value="Transparent" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="EditableLabelComboStyle" TargetType="{x:Type Label}">
    <Setter Property="Template" Value="{StaticResource EditableComboBoxTemplate}" />
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="Padding" Value="4" />
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="BorderThickness" Value="1" />
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="BorderBrush" Value="#B5CFFF"/>
        </Trigger>
    </Style.Triggers>
</Style>

【问题讨论】:

    标签: c# wpf xaml combobox listbox


    【解决方案1】:

    我相信您会更轻松地使组合框看起来像一个标签,直到它被点击或任何您想要的事件。最初使您的组合框 IsEditable 属性为 false。当 IsEditable == false 时,使用数据触发器设置组合框的样式,使其看起来像一个标签。使用 EventTriggers(例如 Click)相应地设置 IsEditable 属性,当您将其设置为 TRUE 时,应取消设置 IsEditable == False 设置器,并且您的组合框将恢复正常。

    选项 2: 不仅要在组合框顶部放置边框,还要放置一个文本框。在底层的 Visibility 上使用转换器,这样当顶层 Visibility=Collapsed 时,底部是 Visible,反之亦然。然后你只需要设置顶层的可见性。

    【讨论】:

    • 您的第一个选项很有趣。我会试试的。不过,我不确定我是否理解选项 2。我有一个预先填充的组合框项目集合。
    猜你喜欢
    • 2013-05-23
    • 2011-02-01
    • 2012-12-25
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-08
    相关资源
    最近更新 更多