将标签添加到WPF ComboBox控件的简单方法

4

这段代码在我的应用程序中越来越常见:

<StackPanel Orientation="Vertical">
    <Label Content="_ComboBox Caption" 
           Target="comboBox" 
           Margin="0" 
           Padding="5,5,5,1" />

    <ComboBox  x:Name="comboBox"
                Width="72"
                Margin="5,0,5,5"
                Padding="5,1,5,5"
                SelectedItem="{Binding ComboSelectedItem}"
                ItemsSource="{Binding ComboSourceList}" />
</StackPanel>

它可以为我渲染一个带标题的组合框。

我想要创建一个自定义控件,即 ComboBox,它可以公开标签内容并设置其他属性。如下所示:

<Controls:CaptionedComboBox  x:Name="comboBox"
                             Width="72"
                             LabelContent="_ComboBox Caption"
                             SelectedItem="{Binding ComboSelectedItem}"
                             ItemsSource="{Binding ComboSourceList}" />

然而,我研究了一下如何制作自定义控件,需要大量的样式设计。令人望而生畏

有没有办法将上述内容做成像这样的效果?

<StackPanel Orientation="Vertical">
    <Label Content="{Binding TemplateLabelContent}" 
           Target="{Binding ControlName}" 
           Margin="0" 
           Padding="5,5,5,1" />

    <InheritedComboBoxStuff/>

</StackPanel>

我知道那样做行不通。但我的观点是,如果只是为了在组合框上方添加标签就必须重新设计整个组合框,那么这似乎很荒谬。

3
你看过 UserControls 吗?它们只需要一点点样式设置,然后就可以设置 DP 属性了。 - H H
@HenkHolterman - 我的理解是,问题在于我必须重新公开 ComboBox 的所有属性。如果是这样的话,我想我只能选择两害相权取其轻了。 - Vaccano
只是你没有提到所有选项,包括ControlTemplate、UserControl和CustomControl。我认为@Sebastian的回答值得一试。 - H H
2个回答

8
您可以为此制作一个模板。
  <ControlTemplate x:Key="ComboWithHeader" TargetType="ContentControl">
        <StackPanel Orientation="Vertical">
            <Label Margin="0"
                   Content="{Binding ComboBoxHeader}"
                   DataContext="{TemplateBinding DataContext}"
                   Padding="5,5,5,1"
                   Target="comboBox" />

            <ComboBox x:Name="comboBox"
                      Width="72"
                      Margin="5,0,5,5"
                      DataContext="{TemplateBinding DataContext}"
                      ItemsSource="{Binding ComboSourceList}"
                      Padding="5,1,5,5"
                      SelectedItem="{Binding ComboSelectedItem}" />
        </StackPanel>
    </ControlTemplate>

如果您想在标题中使用组合,只需使用以下代码:

<ContentControl Template="{StaticResource ComboWithHeader}" DataContext="{Binding ComboBoxViewModel}" />

这种方法能否用于两个实例(带有不同的标签)?似乎这只会一遍又一遍地制作相同的组合框/标题组合。是否有一种方法可以在ContentControl级别绑定Label.Content、ComboBox.SelectedItem和ComboBox.ItemsSource? - Vaccano
1
我假设您使用MVVM模式,ContentControl的数据上下文将确定组合框的项源和选定项。标签内容也应从ViewModel中获取。 ComboBoxViewModel的实例应包含属性{ComboSourceList,ComboSelectedItem,ComboBoxHeader}。因此,您可以根据作为DataContext传递的ViewModel区分控件中的项目。 - Sebastian Ðymel
1
好的,那可以行得通。虽然不是我想要的,但可以行得通。(为每个ComboBoxHeader的实例创建一个单独的ViewModel有点啰嗦。) - Vaccano
1
如果您不喜欢从视图模型传递组合框标题,只需将标签内容绑定到内容控件的内容即可 :) <Label Margin="0" Content="{TemplateBinding Content}" Padding="5,5,5,1" /> 然后使用它 <ContentControl Content="My header" Template="{StaticResource ComboWithHeader}" DataContext="{Binding ComboBoxViewModel}" /> - Sebastian Ðymel

0
非常基础但又非常简单,你也可以创建一个用户控件,然后将你的控件嵌入到任何你想要的地方。例如:

SimpleGraph

<UserControl x:Class="xxx.View.TestResultsGraph"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" 
         MinHeight="50"
         d:DesignHeight="50" d:DesignWidth="300" >

    <Canvas Name="canvas" >
        <Polygon x:Name="SuccessShape" Fill="#FFF0FFF0" SnapsToDevicePixels="True"   />
        <Polyline x:Name="SuccessLine" Stroke="Green"    StrokeThickness="0.5" SnapsToDevicePixels="True"   />
        <Polygon x:Name="FailShape" Fill="#FFFFF0F0" SnapsToDevicePixels="True"   />
        <Polyline x:Name="FailLine" Stroke="Red"  StrokeThickness="0.5" SnapsToDevicePixels="True"      />
        <Polygon x:Name="PendingShape" Fill="#FFFFF0E0" SnapsToDevicePixels="True"   />
        <Polyline x:Name="PendingLine" Stroke="DarkOrange" StrokeThickness="0.5" SnapsToDevicePixels="True"    />
        <Line x:Name="xAxis" Stroke="Black" StrokeThickness="0.5" SnapsToDevicePixels="True"  />
        <Line x:Name="yAxis" Stroke="Black" StrokeThickness="0.5" SnapsToDevicePixels="True" />
    </Canvas>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接