2009-09-15 5 views
82

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

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

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

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

Пожалуйста направьте меня

ответ

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

Вместо создания обработчика SelectionChanged видимость TextBlock может быть установлена ​​в XAML. – aliceraunsbaek

0

Не лучше practice..but работает отлично ...

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

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

ageektrapped blogpost

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

+0

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

+0

Хороший материал, не только он решает проблему ComboBox, но теперь я могу избавиться от сборки WPF Tools и просто использовать это в своих текстовых блоках вместо управления WatermarkedTextBox, так что полный выигрыш :) - oh btw, это A Geek Trapped не согласованная ловушка! – dain

18

Set IsEditable = True в элементе Combobox. Это отобразит свойство текста Combobox

+1

Это самое простое решение из всей партии. –

+3

он меняет то, что выглядит элемент управления, хотя – simonalexander2005

84

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

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

+0

Хороший ответ, мне это нравится :) – Ian

+0

Все, что я могу сказать - WOW! – chopikadze

+0

Я бы хотел использовать это, но, похоже, это недопустимо в случаях, когда combobox является заголовком datagrid. , , XAML дает ошибку, что заголовок уже определен (или, возможно, не может быть определен более одного раза). Есть идеи? Я думаю просто использовать параметр с нулевым значением, который затем позволит сбросить его, выбирая его, но кажется немного неряшливым. –

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

Самый простой способ я нашел, чтобы сделать это:

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

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

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

+0

Это лучше всего подходит для combobox. Благодаря! – henon

+0

Очень простой и лучший вариант в приложении MVVM, которое я создал. Большое спасибо – Darren

+0

Отличный ответ Крис! Я бы просто добавил Focusable = «True», но это просто косметические изменения. – Slavisa

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

Понравилось это лучше, чем другие решения ... – Nishant

+4

Мне нужно было переместить «Видимость =« Скрытый »в триггер данных, затем он работал, как ожидалось. Определенно, самый прямой подход вперед, который я видел. Для повторного использования я переместил стиль в ресурс – Mitch

+0

Ответ @Mitch IceForce не работает для меня, что вы изменили, чтобы заставить его работать? – Chris

0

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

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

-3

только установить атрибут IsEditable истинного

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

Этот точный ответ уже дан ... – rene

+1

Полностью упускает точку – aateeque

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

Это работает как шарм для одной комбинированной коробки. Но когда я использую его с более чем 1 комбо, он дает мне ошибку (но компилируется и работает хорошо). «Свойство DefaultText» уже зарегистрировано «ComboBox». [Я упомянул об исправлении в своем блоге.] (Http://contractnamespace.blogspot.com/2014/04/default-text-on-wpf-combo-boxes.html) –

+0

Спасибо, что указали это. Я не смог выполнить эту ошибку на своем компьютере. Однако я согласен, что typeof (ComboBoxBehaviors) должен быть передан в третьем параметре RegisterAttached вместо typeof (ComboBox). –

+0

Хотя этот пост немного стар, я не вижу, как он может работать.Bg combo устанавливается через триггеры с несколькими условиями. Попробуйте поместить комбо в сетку и вручную установите bg на «красный». Это не влияет на область, где вы хотите, чтобы водяной знак появился. Это может повлиять только на bg за панелью выпадающего меню. Лучшим решением является копирование шаблона управления combobox и добавление нескольких триггеров и стилей для рисования визуальной кисти, состоящей из текстового блока в фоновом режиме границы. – Wade

0

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

Я знаю, что это полу старый, но что об этом так:

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

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

'ComboBox' не имеет свойства' EmptySelectionBoxTemplate'. –

1

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

В конце вы не можете просто установить свойство «Видимость» в TextBlock на «Скрытый», чтобы он был скрыт, если выбранный элемент поля со списком не равен null; вы должны установить его таким образом по умолчанию (так как вы can't check not null in triggers, используя 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> 
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> 
2

самый простой способ заключается в использовании CompositeCollection, чтобы объединить текст по умолчанию и данные из базы данных непосредственно в ComboBo x, например.

<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> 
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"); 

     } 
    } 
3

на основе 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> 
+0

Nice. Я удалил его, связав DataContext TextBlock с использованием относительного источника, чтобы избежать необходимости устанавливать имя. См. Следующий комментарий для Markup (код в комментариях SO выглядит уродливым) – Sascha

+0

Sascha

0

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

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

Чем просто зарегистрируйтесь в SelectionChanged и в нем установите индекс в индекс фиктивного элемента.

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

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

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

-1

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

Находя этот вопрос, ища решение этого вопроса, я обнаружил, что обновленная спецификация 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> 
+0

Я использовал это решение - помогает ли негативная избирательная система? Конечно, я не эксперт XAML, но он сработал. –

+0

Хотя я не являюсь ни одним из избирателей, я полагаю, что вы отказались от голосования, потому что в классе '' System.Windows.ComboBox' нет свойства 'PlaceholderText' (https://stackoverflow.com/questions/19393774/how -в-делать-все-контроль, изменение размера, соответственно-пропорционально-когда-окно-это-Maximi/19398470? noredirect = 1 # comment82731538_19398470). Это вопрос о WPF, а не WinForms. – Sheridan