Как отобразить текст по умолчанию "--Select Team -" в поле со списком в pageload в WPF?

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

"- Выберите команду -"

чтобы на странице pageload оно отображалось, и при его выборе текст должен быть очищен и элементы должны отображаться.

Выбор данных из БД происходит. Мне нужно отобразить текст по умолчанию, пока пользователь не выберет элемент из поля со списком.

Прошу вас уведомить

Ответ 1

Самый простой способ найти это:

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

Вам, очевидно, нужно будет добавить другие параметры, но это, вероятно, самый простой способ сделать это.

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

Ответ 2

Вы можете сделать это без какого-либо кода, используя 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"

Очень приятная вещь в этом подходе - это не повторение кода в вашем коде.

Ответ 3

Мне нравится 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>

Ответ 4

Никто не сказал, что чистое решение 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>

Ответ 5

Установите IsEditable = "True" в элементе ComboBox. Это отобразит свойство Text ComboBox.

Ответ 6

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

например.

<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;
}

Ответ 7

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

ageektrapped blogpost

Он использует слой adorner здесь, чтобы отобразить водяной знак.

Ответ 8

На основе ответа IceForge Я подготовил многоразовое решение:

стиль 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>

Ответ 9

Решение 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

Самый простой способ - использовать 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>

И в ресурсах определить StaticResource для привязки параметров ComboBox к вашему DataContext, потому что прямая привязка в CollectionContainer работает некорректно.

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

Таким образом вы можете определить свои параметры ComboBox только в xaml, например.

   <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>

Ответ 11

Я бы порекомендовал следующее:

Определить поведение

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 --"/>

Ответ 12

Ответ IceForge был довольно близок, и AFAIK является самым простым решением этой проблемы. Но он что-то пропустил, поскольку он не работал (по крайней мере для меня, он никогда не отображает текст).

В конце вы не можете просто установить для свойства "Видимость" TextBlock значение "Скрытый", чтобы он был скрыт, если выбранный элемент со списком не равен null; вы должны установить его таким образом по умолчанию (поскольку вы не можете проверить значение null в триггерах, используя Setter в XAML в том же месте, что и триггеры.

Здесь фактическое решение, основанное на его, отсутствующем 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>

Ответ 13

EDIT: По комментариям ниже, это не решение. Не знаю, как я работал, и не могу проверить этот проект.

Настало время обновить этот ответ для новейшего XAML.

Обнаружив этот вопрос SO, который ищет решение этого вопроса, я обнаружил, что обновленная спецификация XAML имеет простое решение.

Для выполнения этой задачи теперь доступен атрибут "Заполнитель". Это так же просто, как это (в 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>

Ответ 14

Не лучшая практика... но отлично работает...

<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;
            }           
    }
}

Ответ 15

Я считаю, что водяной знак, упомянутый в этом сообщении, будет хорошо работать в этом случае

Здесь требуется немного кода, но вы можете его повторно использовать для любого combobox или текстового поля (и даже для паролей), поэтому я предпочитаю этот путь

Ответ 16

Я использую класс IsNullConverter в своем проекте, и это сработало для меня. вот код для него в С#, создайте папку с именем Converter и добавьте этот класс в эту папку, поскольку используемый триггер не поддерживает значение, а не 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>

Ответ 17

//Код 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");

        }
    }

Ответ 18

Немного поздно, но..

Более простым способом было бы добавить фиктивный элемент данных в список с параметром IsDummy = true и убедиться, что он не является HitTestVisable, а его высота составляет 1 пиксель (с использованием конвертера), поэтому его не видно.

Вместо того, чтобы просто зарегистрироваться в SelectionChanged и в нем, установите индекс в индекс фиктивного элемента.

Он работает как шарм, и таким образом вы не возитесь со стилем и цветами ComboBox или вашей темы приложения.

Ответ 19

InitializeComponent()
yourcombobox.text=" -- Select Team --";

Приведенный выше код демонстрирует самый простой способ его достижения. После загрузки окна объявите текст комбобокса, используя свойство .Text в поле со списком. Это также можно расширить до DatePicker, Textbox и других элементов управления.

Ответ 20

Я сделал это, прежде чем связывать combobox с данными из базы данных в codebehind вот так:

Combobox.Items.Add("-- Select Team --");
Combobox.SelectedIndex = 0;

Ответ 21

Решение
1. Поместите этикетку на верхнюю часть комбинированного списка.
2. Привязать содержимое метки к свойству текста в выпадающем списке.
3. Установите непрозрачность комбинированного списка на ноль, непрозрачность = 0.
4. Введите текст по умолчанию в поле со списком.

 <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>

Ответ 22

Установите для атрибута IsEditable значение true

<ComboBox Name="comboBox1"            
          Text="--Select Team--"
          IsEditable="true"  <---- that all!
          IsReadOnly="true"/>

Ответ 23

Я знаю, что это полу-старое, но как насчет этого:

<DataTemplate x:Key="italComboWM">
    <TextBlock FontSize="11" FontFamily="Segoe UI" FontStyle="Italic" Text="--Select an item--" />
</DataTemplate>

<ComboBox EmptySelectionBoxTemplate="{StaticResource italComboWM}" />