在WPF应用程序中,在MVP应用程序中,我有一个组合框,我显示从数据库获取的数据。在项目添加到组合框之前,我想显示默认文本,例如
“ - 选择团队 - ”
以便在页面加载时显示并在选择时,应清除文本并显示项目。
正在从DB中选择数据。我需要显示默认文本,直到用户从组合框中选择一个项目。
请指导我
答案 0 :(得分:92)
我发现这样做的最简单方法是:
<ComboBox Name="MyComboBox"
IsEditable="True"
IsReadOnly="True"
Text="-- Select Team --" />
您显然需要添加其他选项,但这可能是最简单的方法。
但是这个方法有一个缺点,即组合框中的文本不可编辑,但仍然可以选择。然而,鉴于迄今为止我发现的每种替代品的质量和复杂性都很差,这可能是最好的选择。
答案 1 :(得分:86)
使用IValueConverter
<Grid>
<ComboBox
x:Name="comboBox1"
ItemsSource="{Binding MyItemSource}" />
<TextBlock
Visibility="{Binding SelectedItem, ElementName=comboBox1, Converter={StaticResource NullToVisibilityConverter}}"
IsHitTestVisible="False"
Text="... Select Team ..." />
</Grid>
这里有可以重复使用的转换器类。
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
}
最后,您需要在资源部分声明转换器。
<Converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
转换器位于转换器类的位置。一个例子是:
xmlns:Converters="clr-namespace:MyProject.Resources.Converters"
这种方法非常好用的是不会在代码中重复代码。
答案 2 :(得分:46)
我喜欢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>
答案 3 :(得分:29)
没有人说纯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>
答案 4 :(得分:20)
在ComboBox元素上设置IsEditable =“True”。这将显示ComboBox的Text属性。
答案 5 :(得分:14)
我不知道它是否直接支持,但您可以使用标签覆盖组合,如果选择不为空,则将其设置为隐藏。
例如
<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>
然后在选择更改处理程序...
private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
txtSelectTeam.Visibility = comboBox1.SelectedItem == null ? Visibility.Visible : Visibility.Hidden;
}
答案 6 :(得分:4)
基于IceForge's answer我准备了一个可重复使用的解决方案:
xaml风格:
<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>
使用示例:
<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>
答案 7 :(得分:4)
答案 8 :(得分:2)
最简单的方法是使用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>
在Resources中定义StaticResource以将ComboBox选项绑定到DataContext,因为CollectionContainer中的直接绑定无法正常工作。
<Window.Resources>
<CollectionViewSource Source="{Binding}" x:Key="MyComboOptions" />
</Window.Resources>
这样您就可以仅在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>
答案 9 :(得分:2)
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>
答案 10 :(得分:1)
编辑:根据以下评论,这不是一个解决方案。不确定我是如何工作的,并且无法检查该项目。
现在是时候更新最新XAML的答案了。
找到这个SO问题,寻找这个问题的解决方案,然后我发现更新的XAML规范有一个简单的解决方案。
一个名为&#34; Placeholder&#34;的属性现在可以完成此任务。就像这一样简单(在Visual Studio 2015中):
<ComboBox x:Name="Selection" PlaceholderText="Select...">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>
</ComboBox>
答案 11 :(得分:1)
IceForge's answer非常接近,AFAIK是解决此问题的最简单方法。但是它错过了一些东西,因为它不起作用(至少对我而言,它实际上从未显示过文本)。
最后,您不能只将TextBlock的“Visibility”属性设置为“Hidden”,以便在组合框的选定项目不为空时隐藏它;你必须默认设置它(因为你can't check not null in triggers,在XAML中使用与触发器相同位置的Setter。
这是基于他的实际解决方案,在触发器之前放置了缺少的Setter:
<ComboBox x:Name="combo"/>
<TextBlock Text="--Select Team--" IsHitTestVisible="False">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Setters>
<Setter Property="Visibility" Value="Hidden"/>
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=combo,Path=SelectedItem}" Value="{x:Null}">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
答案 12 :(得分:1)
我会推荐以下内容:
定义行为
public static class ComboBoxBehaviors
{
public static readonly DependencyProperty DefaultTextProperty =
DependencyProperty.RegisterAttached("DefaultText", typeof(String), typeof(ComboBox), new PropertyMetadata(null));
public static String GetDefaultText(DependencyObject obj)
{
return (String)obj.GetValue(DefaultTextProperty);
}
public static void SetDefaultText(DependencyObject obj, String value)
{
var combo = (ComboBox)obj;
RefreshDefaultText(combo, value);
combo.SelectionChanged += (sender, _) => RefreshDefaultText((ComboBox)sender, GetDefaultText((ComboBox)sender));
obj.SetValue(DefaultTextProperty, value);
}
static void RefreshDefaultText(ComboBox combo, string text)
{
// if item is selected and DefaultText is set
if (combo.SelectedIndex == -1 && !String.IsNullOrEmpty(text))
{
// Show DefaultText
var visual = new TextBlock()
{
FontStyle = FontStyles.Italic,
Text = text,
Foreground = Brushes.Gray
};
combo.Background = new VisualBrush(visual)
{
Stretch = Stretch.None,
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Center,
Transform = new TranslateTransform(3, 0)
};
}
else
{
// Hide DefaultText
combo.Background = null;
}
}
}
用户行为
<ComboBox Name="cmb" Margin="72,121,0,0" VerticalAlignment="Top"
local:ComboBoxBehaviors.DefaultText="-- Select Team --"/>
答案 13 :(得分:0)
InitializeComponent()
yourcombobox.text=" -- Select Team --";
上面的代码演示了实现它的最简单方法。窗口加载后,使用组合框的.Text属性声明组合框的文本。这也可以扩展到DatePicker,Textbox和其他控件。
答案 14 :(得分:0)
我在我的项目中使用了一个IsNullConverter类,它对我有用。 这里是c#中的代码,创建一个名为Converter的文件夹,并在该文件夹中添加此类,因为使用的触发器不支持null而不是null,而IsNullConverter只是这样做
public class IsNullConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value == null);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException("IsNullConverter can only be used OneWay.");
}
}
像这样在xaml文件中添加命名空间。
xmlns:Converters="clr-namespace:TymeSheet.Converter"
装置
xmlns:Converters="clr-namespace:YourProjectName.Converter"
在资源下方使用此行,通过xaml代码
使其可用<Converters:IsNullConverter x:Key="isNullConverter" />
这里是xaml代码,我在这里使用了触发器,因此每当在组合框中选择一个项目时,你的文本的可见性就会变错。
<TextBlock Text="Select Project" IsHitTestVisible="False" FontFamily="/TimeSheet;component/Resources/#Open Sans" FontSize="14" Canvas.Right="191" Canvas.Top="22">
<TextBlock.Resources>
<Converters:IsNullConverter x:Key="isNullConverter"/>
</TextBlock.Resources>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ProjectComboBox,Path=SelectedItem,Converter={StaticResource isNullConverter}}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
答案 15 :(得分:0)
我在将组合框与代码隐藏中的数据库绑定之前做到了这一点 -
Combobox.Items.Add("-- Select Team --");
Combobox.SelectedIndex = 0;
答案 16 :(得分:0)
有点晚了但是......
更简单的方法是使用参数IsDummy = true将虚拟数据项添加到列表中,并确保它不是HitTestVisable,并且它的高度是1像素(使用转换器),所以它不会被看到。
只需注册到SelectionChanged并在其中,将索引设置为虚拟项目索引。
它就像一个魅力,这样你就不会搞乱ComboBox的风格和颜色或你的应用主题。
答案 17 :(得分:0)
解决方案
1.在组合框顶部放置一个标签。
2.将标签的内容绑定到组合框的Text属性。
3.将组合框的不透明度设置为零,不透明度= 0。
4.在组合框的Text属性中写入默认文本
<Grid>
<Label Content="{Binding ElementName=cb, Path=Text}"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Center"
Height="{Binding ElementName=cb, Path=Height}"
Width="{Binding ElementName=cb, Path=Width}"/>
<ComboBox Name="cb"
Text="--Select Team--" Opacity="0"
Height="40" Width="140" >
<ComboBoxItem Content="Manchester United" />
<ComboBoxItem Content="Lester" />
</ComboBox>
</Grid>
答案 18 :(得分:0)
// XAML代码
// ViewModel代码
private CategoryModel _SelectedCategory;
public CategoryModel SelectedCategory
{
get { return _SelectedCategory; }
set
{
_SelectedCategory = value;
OnPropertyChanged("SelectedCategory");
}
}
private ObservableCollection<CategoryModel> _Categories;
public ObservableCollection<CategoryModel> Categories
{
get { return _Categories; }
set
{
_Categories = value;
_Categories.Insert(0, new CategoryModel()
{
CategoryId = 0,
CategoryName = " -- Select Category -- "
});
SelectedCategory = _Categories[0];
OnPropertyChanged("Categories");
}
}
答案 19 :(得分:0)
我认为in this post提到的水印在这种情况下效果很好
需要一些代码,但你可以将它重复用于任何组合框或文本框(甚至密码盒),所以我更喜欢这种方式
答案 20 :(得分:0)
不是最佳实践..但工作正常......
<ComboBox GotFocus="Focused" x:Name="combobox1" HorizontalAlignment="Left" Margin="8,29,0,0" VerticalAlignment="Top" Width="128" Height="117"/>
背后的代码
public partial class MainWindow : Window
{
bool clearonce = true;
bool fillonce = true;
public MainWindow()
{
this.InitializeComponent();
combobox1.Items.Insert(0, " -- Select Team --");
combobox1.SelectedIndex = 0;
}
private void Focused(object sender, RoutedEventArgs e)
{
if(clearonce)
{
combobox1.Items.Clear();
clearonce = false;
}
if (fillonce)
{
//fill the combobox items here
for (int i = 0; i < 10; i++)
{
combobox1.Items.Insert(i, i);
}
fillonce = false;
}
}
}
答案 21 :(得分:-3)
仅将IsEditable属性设置为true
<ComboBox Name="comboBox1"
Text="--Select Team--"
IsEditable="true" <---- that's all!
IsReadOnly="true"/>
答案 22 :(得分:-4)
我知道这已经半岁了但是这样呢:
<DataTemplate x:Key="italComboWM">
<TextBlock FontSize="11" FontFamily="Segoe UI" FontStyle="Italic" Text="--Select an item--" />
</DataTemplate>
<ComboBox EmptySelectionBoxTemplate="{StaticResource italComboWM}" />