it-swarm.com.de

Wie wird der Standardtext "--Select Team -" im Kombinationsfeld beim Laden der Seite in WPF angezeigt?

In einer WPF-App, in der MVP-App, habe ich ein Kombinationsfeld, für das ich die aus der Datenbank abgerufenen Daten anzeigen kann. Bevor die Elemente zum Kombinationsfeld hinzugefügt werden, möchte ich den Standardtext anzeigen, z

" -- Team auswählen --"

so dass auf pageload es angezeigt wird und wenn es ausgewählt wird, sollte der Text gelöscht und die Elemente angezeigt werden.

Das Auswählen von Daten aus der Datenbank findet statt. Ich muss den Standardtext anzeigen, bis der Benutzer ein Element aus dem Kombinationsfeld auswählt.

Bitte führen Sie mich

92
Ramm

Der einfachste Weg, den ich gefunden habe, ist:

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

Sie müssen natürlich Ihre anderen Optionen hinzufügen, aber dies ist wahrscheinlich der einfachste Weg, dies zu tun.

Diese Methode hat jedoch den Nachteil, dass der Text in Ihrem Kombinationsfeld nicht bearbeitet werden kann, er kann jedoch weiterhin ausgewählt werden. Angesichts der schlechten Qualität und Komplexität aller bisher gefundenen Alternativen ist dies wahrscheinlich die beste Option.

89
Chris Walter

Sie können dies auch ohne Code tun, indem Sie eine IValueConverter verwenden.

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

Hier haben Sie die Konverter-Klasse, die Sie wiederverwenden können.

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
}

Und schließlich müssen Sie Ihren Konverter in einem Ressourcenabschnitt deklarieren.

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

Wo Konverter ist der Ort, an dem Sie die Konverterklasse platziert haben. Ein Beispiel ist:

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

Das Schöne an diesem Ansatz ist, dass der Code in Ihrem Code nicht wiederholt wird.

86
Tri Q Tran

Ich mag die Antwort von Tri Q, aber diese Wertkonverter sind sehr schmerzhaft. PaulB hat es mit einem Event-Handler gemacht, aber das ist auch nicht nötig. Hier ist eine reine XAML-Lösung:

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

Niemand sagte, eine reine Xaml-Lösung muss kompliziert sein. Hier ist eine einfache, mit einem Datenauslöser im Textfeld. Margin und Position wie gewünscht

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

Setzen Sie IsEditable = True für das Combobox-Element. Dadurch wird die Text-Eigenschaft der Combobox angezeigt

20
medusa

Ich weiß nicht, ob es direkt unterstützt wird, aber Sie könnten die Kombination mit einer Beschriftung überlagern und sie auf "Verborgen" setzen, wenn die Auswahl nicht NULL ist.

z.B.

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

Dann in der Auswahl geänderter Handler ...

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

Basierend auf IceForges Antwort habe ich eine wiederverwendbare Lösung vorbereitet:

xaml-Stil:

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

anwendungsbeispiel:

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

Ich habe es nicht mit Kombinationsfeldern ausprobiert, aber das hat bei mir mit anderen Steuerelementen funktioniert ...

ageektrapped Blogpost

Er verwendet hier die Adorner-Schicht, um ein Wasserzeichen anzuzeigen.

4
Crippeoblade

Die Lösung von HappyNomad war sehr gut und half mir, diese etwas andere Lösung zu finden. 

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

Am einfachsten ist es, CompositeCollection zu verwenden, um Standardtext und -daten direkt aus der Datenbank in der ComboBox zusammenzuführen, z.

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

Definieren Sie in Resources StaticResource, um ComboBox-Optionen an Ihren DataContext zu binden, da die direkte Bindung in CollectionContainer nicht ordnungsgemäß funktioniert.

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

Auf diese Weise können Sie Ihre ComboBox-Optionen nur in xaml definieren, z. 

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

IceForges Antwort war ziemlich nahe und ist AFAIK die einfachste Lösung für dieses Problem. Aber es hat etwas versäumt, da es nicht funktionierte (zumindest für mich zeigt es nie den Text an).

Am Ende können Sie die Eigenschaft "Visibility" des TextBlock nicht einfach auf "Hidden" setzen, damit sie ausgeblendet wird, wenn das ausgewählte Element des Kombinationsfelds nicht null ist. Sie müssen dies standardmäßig so einstellen (da Sie nicht in Triggern auf null prüfen können , indem Sie einen Setter in XAML an derselben Stelle wie die Trigger verwenden.

Hier ist die tatsächliche Lösung, die auf seinem basiert, dem fehlenden Setter, der unmittelbar vor den Triggern platziert wird:

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

Ich würde folgendes empfehlen:

Verhalten definieren

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

Benutzer das Verhalten

<ComboBox Name="cmb" Margin="72,121,0,0" VerticalAlignment="Top"
          local:ComboBoxBehaviors.DefaultText="-- Select Team --"/>
1
Usman Zafar

BEARBEITEN: Nach den Kommentaren unten ist dies keine Lösung. Ich bin nicht sicher, wie ich es hatte arbeiten lassen und kann das Projekt nicht überprüfen.

Es ist Zeit, diese Antwort für die neueste XAML zu aktualisieren. 

Als ich diese SO - Frage auf der Suche nach einer Lösung für diese Frage fand, fand ich heraus, dass die aktualisierte XAML-Spezifikation eine einfache Lösung hat.

Für diese Aufgabe steht jetzt ein Attribut mit dem Namen "Placeholder" zur Verfügung. So einfach ist das (in 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>
1
Robb Sadler

Ich habe es vor dem Binden der Combobox mit Daten aus der Datenbank in codebehind so gemacht -

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

Ein bisschen spät, aber ..

Eine einfachere Möglichkeit wäre, ein Dummy-Datenelement mit dem Parameter IsDummy = true zur Liste hinzuzufügen und sicherzustellen, dass es nicht HitTestVisable ist und seine Höhe 1 Pixel beträgt (mithilfe eines Konverters).

Dann registrieren Sie sich einfach bei SelectionChanged und setzen Sie den Index auf den Dummy-Elementindex.

Es funktioniert wie ein Zauber, und so machen Sie sich nicht mit Stil und Farben der ComboBox oder Ihrem Anwendungsthema herum.

0
Eibi

Lösung 
1. Legen Sie ein Etikett auf die Combobox. 
2. Binden Sie den Inhalt des Labels an die Combobox-Text-Eigenschaft.
3. Setzen Sie die Deckkraft der Combobox auf Null, Deckkraft = 0. 
4. Schreiben Sie Standardtext in die Combobox Text-Eigenschaft

 <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>
0
Yinon Dotan

Ich verwende eine IsNullConverter-Klasse in meinem Projekt, und es hat für mich funktioniert. Hier ist der Code dafür in c #. Erstellen Sie einen Ordner mit dem Namen Converter und fügen Sie diese Klasse in diesem Ordner hinzu, da der verwendete Auslöser keinen Wert für unterstützt null und IsNullConverter tun das einfach

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

fügen Sie den Namespace in dieser Xaml-Datei hinzu.

xmlns:Converters="clr-namespace:TymeSheet.Converter"

meint

xmlns:Converters="clr-namespace:YourProjectName.Converter"

verwenden Sie diese Zeile unterhalb der Ressourcen, um sie über XAML-Code verfügbar zu machen

<Converters:IsNullConverter x:Key="isNullConverter" />

hier ist der XAML-Code. Ich habe hier den Auslöser verwendet. Wenn also ein Element in der Combobox ausgewählt wird, wird die Sichtbarkeit Ihres Textes falsch.

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

// XAML-Code

// ViewModel-Code

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

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

Der obige Code demonstriert den einfachsten Weg, um dies zu erreichen. Deklarieren Sie nach dem Laden des Fensters den Text der Combobox mithilfe der .Text-Eigenschaft der Combobox. Dies kann auch auf DatePicker, Textbox und andere Steuerelemente erweitert werden.

0
Ketan Dubey

Nicht die beste Methode, aber es funktioniert gut ...

<ComboBox GotFocus="Focused"  x:Name="combobox1" HorizontalAlignment="Left" Margin="8,29,0,0" VerticalAlignment="Top" Width="128" Height="117"/>

Code hinter

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;
            }           
    }
}
0
Madi D.

Ich glaube, ein Wasserzeichen, wie es in diesem Beitrag in diesem Beitrag erwähnt wird, würde in diesem Fall gut funktionieren

Es wird ein bisschen Code benötigt, aber Sie können ihn für jede Combobox oder Textbox (und sogar für Passwortboxen) wiederverwenden. Ich bevorzuge diesen Weg

0
FearlessHyena