如何在 WPF 页面加载的组合框中显示默认文本“--Select Team --”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1426050/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 21:00:27  来源:igfitidea点击:

How to display default text "--Select Team --" in combo box on pageload in WPF?

wpfcombobox

提问by user301016

In a WPF app, in MVP app, I have a combo box,for which I display the data fetched from Database. Before the items added to the Combo box, I want to display the default text such as

在 WPF 应用程序中,在 MVP 应用程序中,我有一个组合框,用于显示从数据库中获取的数据。在将项目添加到 Combo 框之前,我想显示默认文本,例如

" -- Select Team --"

“——选择球队——”

so that on pageload it displays and on selecting it the text should be cleared and the items should be displayed.

以便在页面加载时显示并选择它时,应清除文本并显示项目。

Selecting data from DB is happening. I need to display the default text until the user selects an item from combo box.

从数据库中选择数据正在发生。我需要显示默认文本,直到用户从组合框中选择一个项目。

Please guide me

请指导我

采纳答案by Chris Walter

The easiest way I've found to do this is:

我发现最简单的方法是:

<ComboBox Name="MyComboBox"
 IsEditable="True"
 IsReadOnly="True"
 Text="-- Select Team --" />

You'll obviously need to add your other options, but this is probably the simplest way to do it.

您显然需要添加其他选项,但这可能是最简单的方法。

There is however one downside to this method which is while the text inside your combo box will not be editable, it is still selectable. However, given the poor quality and complexity of every alternative I've found to date, this is probably the best option out there.

然而,这种方法有一个缺点,即组合框中的文本不可编辑,但仍可以选择。然而,鉴于我迄今为止发现的每种替代方案的质量和复杂性都很差,这可能是最好的选择。

回答by Tri Q Tran

You can do this without any code behind by using a IValueConverter.

您可以使用IValueConverter.

<Grid>
   <ComboBox
       x:Name="comboBox1"
       ItemsSource="{Binding MyItemSource}"  />
   <TextBlock
       Visibility="{Binding SelectedItem, ElementName=comboBox1, Converter={StaticResource NullToVisibilityConverter}}"
       IsHitTestVisible="False"
       Text="... Select Team ..." />
</Grid>

Here you have the converter class that you can re-use.

这里有可以重用的转换器类。

public class NullToVisibilityConverter : IValueConverter
{
    #region Implementation of IValueConverter

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value == null ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

And finally, you need to declare your converter in a resource section.

最后,您需要在资源部分声明您的转换器。

<Converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />

Where Converters is the place you have placed the converter class. An example is:

其中 Converters 是您放置转换器类的地方。一个例子是:

xmlns:Converters="clr-namespace:MyProject.Resources.Converters"

The very nice thing about this approach is no repetition of code in your code behind.

这种方法的好处是在你的代码后面没有重复的代码。

回答by HappyNomad

I like Tri Q's answer, but those value converters are a pain to use. PaulB did it with an event handler, but that's also unnecessary. Here's a pure XAML solution:

我喜欢 Tri Q 的回答,但这些值转换器使用起来很麻烦。PaulB 使用事件处理程序完成了这件事,但这也是不必要的。这是一个纯 XAML 解决方案:

<ContentControl Content="{Binding YourChoices}">
    <ContentControl.ContentTemplate>
        <DataTemplate>
            <Grid>
                <ComboBox x:Name="cb" ItemsSource="{Binding}"/>
                <TextBlock x:Name="tb" Text="Select Something" IsHitTestVisible="False" Visibility="Hidden"/>
            </Grid>
            <DataTemplate.Triggers>
                <Trigger SourceName="cb" Property="SelectedItem" Value="{x:Null}">
                    <Setter TargetName="tb" Property="Visibility" Value="Visible"/>
                </Trigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </ContentControl.ContentTemplate> 
</ContentControl>

回答by IceForge

No one said a pure xaml solution has to be complicated. Here's a simple one, with 1 data trigger on the text box. Margin and position as desired

没有人说纯 xaml 解决方案必须很复杂。这是一个简单的,文本框上有 1 个数据触发器。根据需要保证金和头寸

<Grid>
    <ComboBox x:Name="mybox" ItemsSource="{Binding}"/>
    <TextBlock Text="Select Something" IsHitTestVisible="False">
           <TextBlock.Style>
                <Style TargetType="TextBlock">
                      <Setter Property="Visibility" Value="Hidden"/>
                      <Style.Triggers>
                            <DataTrigger Binding="{Binding ElementName=mybox,Path=SelectedItem}" Value="{x:Null}">
                                  <Setter Property="Visibility" Value="Visible"/>
                             </DataTrigger>
                      </Style.Triggers>
                </Style>
           </TextBlock.Style>
     </TextBlock>
</Grid>

回答by medusa

Set IsEditable="True"on the ComboBoxelement. This will display the Textproperty of the ComboBox.

IsEditable="True"ComboBox元素上设置。这将显示 的Text属性ComboBox

回答by PaulB

I dont know if it's directly supported but you could overlay the combo with a label and set it to hidden if the selection isn't null.

我不知道它是否直接受支持,但如果选择不为空,您可以用标签覆盖组合并将其设置为隐藏。

eg.

例如。

<Grid>
   <ComboBox Text="Test" Height="23" SelectionChanged="comboBox1_SelectionChanged" Name="comboBox1" VerticalAlignment="Top" ItemsSource="{Binding Source=ABCD}"  />
   <TextBlock IsHitTestVisible="False" Margin="10,5,0,0" Name="txtSelectTeam" Foreground="Gray" Text="Select Team ..."></TextBlock>
</Grid>

Then in the selection changed handler ...

然后在选择更改处理程序...

private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    txtSelectTeam.Visibility = comboBox1.SelectedItem == null ? Visibility.Visible : Visibility.Hidden;
}

回答by Crippeoblade

Not tried it with combo boxes but this has worked for me with other controls...

没有尝试使用组合框,但这对我与其他控件一起工作...

ageektrapped blogpost

受年龄限制的博文

He uses the adorner layer here to display a watermark.

他在这里使用装饰层来显示水印。

回答by too

Based on IceForge's answerI prepared a reusable solution:

根据IceForge 的回答,我准备了一个可重用的解决方案:

xaml style:

xml风格:

<Style x:Key="ComboBoxSelectOverlay" TargetType="TextBlock">
    <Setter Property="Grid.ZIndex" Value="10"/>
    <Setter Property="Foreground" Value="{x:Static SystemColors.GrayTextBrush}"/>
    <Setter Property="Margin" Value="6,4,10,0"/>
    <Setter Property="IsHitTestVisible" Value="False"/>
    <Setter Property="Visibility" Value="Hidden"/>
    <Style.Triggers>
        <DataTrigger Binding="{Binding}" Value="{x:Null}">
            <Setter Property="Visibility" Value="Visible"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

example of use:

使用示例:

<Grid>
     <ComboBox x:Name="cmb"
               ItemsSource="{Binding Teams}" 
               SelectedItem="{Binding SelectedTeam}"/>
     <TextBlock DataContext="{Binding ElementName=cmb,Path=SelectedItem}"
               Text=" -- Select Team --" 
               Style="{StaticResource ComboBoxSelectOverlay}"/>
</Grid>

回答by Nick Falco

HappyNomad's solution was very good and helped me eventually arrive at this slightly different solution.

HappyNomad 的解决方案非常好,帮助我最终得出了这个略有不同的解决方案。

<ComboBox x:Name="ComboBoxUploadProject" 
    Grid.Row="2"
    Width="200" 
    Height="23"                           
    Margin="64,0,0,0"
    ItemsSource="{Binding projectList}"
    SelectedValue ="{Binding projectSelect}" 
    DisplayMemberPath="projectName"
    SelectedValuePath="projectId"
    >
    <ComboBox.Template>
        <ControlTemplate TargetType="ComboBox">
            <Grid>
                <ComboBox x:Name="cb" 
                    DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" 
                    ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource TemplatedParent}}"
                    SelectedValue ="{Binding SelectedValue, RelativeSource={RelativeSource TemplatedParent}}" 
                    DisplayMemberPath="projectName"
                    SelectedValuePath="projectId"
                    />
                <TextBlock x:Name="tb" Text="Select Item..." Margin="3,3,0,0" IsHitTestVisible="False" Visibility="Hidden"/>
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger SourceName="cb" Property="SelectedItem" Value="{x:Null}">
                    <Setter TargetName="tb" Property="Visibility" Value="Visible"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </ComboBox.Template>
</ComboBox>

回答by Zap

Easiest way is to use CompositeCollection to merge default text and data from database directly in ComboBox e.g.

最简单的方法是使用 CompositeCollection 直接在 ComboBox 中合并默认文本和数据库中的数据,例如

    <ComboBox x:Name="SelectTeamComboBox" SelectedIndex="0">
        <ComboBox.ItemsSource>
            <CompositeCollection>
                <ComboBoxItem Visibility="Collapsed">-- Select Team --</ComboBoxItem>
                <CollectionContainer Collection="{Binding Source={StaticResource ResourceKey=MyComboOptions}}"/>
            </CompositeCollection>
        </ComboBox.ItemsSource>
    </ComboBox>

And in Resources define StaticResource to bind ComboBox options to your DataContext, because direct binding in CollectionContainer doesn't work correctly.

在资源中定义 StaticResource 以将 ComboBox 选项绑定到您的 DataContext,因为 CollectionContainer 中的直接绑定无法正常工作。

<Window.Resources>
    <CollectionViewSource Source="{Binding}" x:Key="MyComboOptions" />
</Window.Resources>

This way you can define your ComboBox options only in xaml e.g.

这样你就可以只在 xaml 中定义你的 ComboBox 选项,例如

   <ComboBox x:Name="SelectTeamComboBox" SelectedIndex="0">
        <ComboBox.ItemsSource>
            <CompositeCollection>
                <ComboBoxItem Visibility="Collapsed">-- Select Team --</ComboBoxItem>
                <ComboBoxItem >Option 1</ComboBoxItem>
                <ComboBoxItem >Option 2</ComboBoxItem>
            </CompositeCollection>
        </ComboBox.ItemsSource>
    </ComboBox>