Как отобразить текст по умолчанию «--Select Team -» в поле со списком при загрузке страницы в WPF? - PullRequest
93 голосов
/ 15 сентября 2009

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

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

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

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

Пожалуйста, ведите меня

Ответы [ 23 ]

93 голосов
/ 26 июля 2012

Я нашел самый простой способ сделать это:

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

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

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

86 голосов
/ 03 апреля 2010

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

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

46 голосов
/ 29 октября 2010

Мне нравится ответ 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>
31 голосов
/ 28 мая 2013

Никто не говорил, что чисто решение 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>
20 голосов
/ 06 января 2010

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

14 голосов
/ 15 сентября 2009

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

например.

<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;
}
4 голосов
/ 20 мая 2016

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

xaml style:

<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>
4 голосов
/ 15 сентября 2009

Не пробовал с комбо-боксами, но у меня это работало с другими элементами управления ...

ageektrapped пост в блоге

Для отображения водяного знака он использует слой с надписью.

2 голосов
/ 16 апреля 2015

Самый простой способ - использовать 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>
2 голосов
/ 06 февраля 2015

Решение 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...