Può un WPF ComboBox visualizzare il testo alternativo quando la sua selezione è nullo?

G’day!

Voglio che il mio WPF ComboBox per visualizzare del testo alternativo quando la sua associazione a dati di selezione è null.

Vista modello ha previsto di proprietà:

public ThingoSelectionViewModel : INotifyPropertyChanged {
    public ThingoSelectionViewModel(IProvideThingos) {
        this.Thingos = IProvideThingos.GetThingos();
    }

    public ObservableCollection<Thingo> Thingos { get; set; }

    public Thingo SelectedThingo { 
        get { return this.selectedThingo; }
        set { //set this.selectedThingo and raise the property change notification
    }

    //...

}

La vista ha XAML associazione per il modello di visualizzazione nel modo previsto:

<ComboBox x:Name="ComboboxDrive" SelectedItem="{Binding Path=SelectedThingo}"
          IsEditable="false" HorizontalAlignment="Left" MinWidth="100" 
          IsReadOnly="false" Style="{StaticResource ComboboxStyle}"
          Grid.Column="1" Grid.Row="1" Margin="5" SelectedIndex="0">
    <ComboBox.ItemsSource>
        <CompositeCollection>
        <ComboBoxItem IsEnabled="False">Select a thingo</ComboBoxItem>
        <CollectionContainer 
            Collection="{Binding Source={StaticResource Thingos}}" />
        </CompositeCollection>
    </ComboBox.ItemsSource>
</ComboBox>

Il ComboBoxItem stretta nella parte superiore è un modo per avere un elemento in più in alto. E ‘ pura chrome: il modello di visualizzazione rimane puro e semplice. C’è solo un problema: gli utenti vogliono “Selezionare un thingo” visualizzato ogni volta che il ComboBox di selezione è null.

Gli utenti non vuole un thingo selezionata per impostazione predefinita. Vogliono vedere un messaggio che dice loro di selezionare un thingo.

Vorrei evitare di inquinare il viewmodel con un ThingoWrapper classe con un ToString restituzione del metodo “Selezionare un thingo” se il suo .ActualThingo proprietà è null, avvolgendo ogni Thingo come ho popolano Thingos, e cercare di capire qualche modo per impedire all’utente di selezionare il nulla Thingo.

C’è un modo per visualizzare “Selezionare un thingo” entro il ComboBox‘ confini utilizzando solo il codice XAML, o pure XAML e poche righe di codice in vista di classe code-behind?

  • FWIW: ho finito di attuazione della ThingoWrapper, modificando il ThingoSelectionViewModel per far fronte con selezione avvolto valore nullo, e di trovare modi per selezionare automaticamente il Whatsy e Fadoozamy oggetti e quindi non ho avuto avvolgerli, anche.
InformationsquelleAutor Garth Kidd | 2010-05-25



7 Replies
  1. 3

    Il percorso di minor resistenza qui che ho trovato è quello di utilizzare il Oggetto Null Modello Per un esempio di utilizzo di questo modello .NET Framework, considerare il valore statico Doppio.NaN se si crea un Oggetto Null per il tuo Thingo, nel tuo modello di visualizzazione è possibile aggiungerli al tuo elenco come a dire: “non è selezionato nulla”. Creare un modello di dati per il Thingo classe che ha un DataTrigger per il Null istanza di Oggetto che visualizza “Selezionare un Valore”.

    Mi potrebbe dare un esempio di codice, ma è passato il mio letto.

  2. 8

    Come severo è il tuo MVVM requisito? Si può avere un po ‘ di code-behind in vista?

    Forse, si potrebbe contenere la ComboBox in una griglia, qualcosa di simile a questo:

    <Grid>
        <ComboBox x:Name="ComboBoxControl"
                  SelectionChanged="ComboBoxControl_SelectionChanged"
                  HorizontalAlignment="Left" VerticalAlignment="Top" 
                  MinWidth="{Binding ElementName=UnselectedText, Path=ActualWidth}">
            <ComboBoxItem>One</ComboBoxItem>
            <ComboBoxItem>Two</ComboBoxItem>
            <ComboBoxItem>Three</ComboBoxItem>
        </ComboBox>
        <TextBlock IsHitTestVisible="False" 
                   x:Name="UnselectedText" 
                   HorizontalAlignment="Left" 
                   Text="Select an option..." 
                   VerticalAlignment="Top" Margin="4" 
                   Padding="0,0,30,0" />
    </Grid>

    Poi, nel code-behind, inserire un po ‘ di logica in un gestore di evento:

    Private Sub ComboBoxControl_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs)
        If ComboBoxControl.SelectedIndex = -1 Then
            UnselectedText.Visibility = Windows.Visibility.Visible
        Else
            UnselectedText.Visibility = Windows.Visibility.Hidden
        End If
    End Sub

    Impostazione del IsHitTestVisible="False" DependencyProperty sul TextBlock consente di eventi del mouse attraverso in modo che è possibile fare clic sulla casella combinata, e di impostare la visibilità di Hidden nel code-behind mantiene il layout di default ComboBox aspetto un salto di circa quando il testo del prompt è nascosto.

    • Anche se si vuole fare in modo che non devi rompere il MVVM. Basta usare un convertitore per convertire la selezione di visibilità.
  3. 4

    Non è possibile utilizzare un modello di controllo di innesco, ma si potrebbe creare un semplice modello di elemento per il controllo combobox:

    <ComboBox ItemsSource="{Binding}" >
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock x:Name="displayText" Text="{Binding}" />
                    <DataTemplate.Triggers>
                        <DataTrigger Binding="{Binding}" Value="{x:Null}">
                            <Setter TargetName="displayText" Property="Text" Value="Default Value" />
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    • Hmm. Dovrò controllare questo fuori, troppo.
  4. 3

    Edit:
    Sembra che il trigger idea è un no go. Ho aggiunto i seguenti modelli di controllo, di prova di una casella combinata inutilmente:

        <Trigger Property="SelectedItem" Value="{x:Null}">
            <Setter Property="Text" Value="No Item Selected"/>
        </Trigger>

    Inoltre, quando si cerca di modificare il modello di controllo in Blend (Modifica Attuale) mi sono lasciata con un anonimo combobox, senza colori, solo un brutto tasto (ma c’è uno spazio senza frontiere discesa). Provare a qualcun’altro suggerimento (Mike Brown forse).

    Originale:

    È possibile utilizzare un Trigger nel modello di Controllo. Qui è un esempio di utilizzo di una ListBox da un’applicazione su cui sto lavorando.

    <ControlTemplate x:Key="SnazzyFormListBoxTemplate" TargetType="{x:Type ListBox}">
        <Microsoft_Windows_Themes:ClassicBorderDecorator x:Name="Bd" SnapsToDevicePixels="True" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderStyle="Sunken" BorderThickness="{TemplateBinding BorderThickness}">
            <ScrollViewer Padding="{TemplateBinding Padding}" Focusable="False" Template="{DynamicResource SnazzyScrollViewerControlTemplate}">
                <Grid>
                <TextBlock x:Name="textBlock" Text="No Items" FontFamily="Arial" FontWeight="Bold" FontSize="13.333" Foreground="#4D000000" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,10"/>
                <ItemsPresenter x:Name="itemsPresenter" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                </Grid>
            </ScrollViewer>
        </Microsoft_Windows_Themes:ClassicBorderDecorator>
        <ControlTemplate.Triggers>
            <Trigger Property="Selector.IsSelected" Value="True"/>
            <Trigger Property="HasItems" Value="False">
                <Setter Property="Visibility" TargetName="textBlock" Value="Visible"/>
                <Setter Property="Visibility" TargetName="itemsPresenter" Value="Collapsed"/>
            </Trigger>
            <Trigger Property="HasItems" Value="True">
                <Setter Property="Visibility" TargetName="textBlock" Value="Collapsed"/>
                <Setter Property="Visibility" TargetName="itemsPresenter" Value="Visible"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

    Sopra ControlTemplate ha un Trigger che controlla la Proprietà HasItems. Se è False, un textblock dicendo “Nessun elemento” viene visualizzato al centro della ListBox. Se ci sono Elementi, questi vengono visualizzati.

    Nel tuo caso modificare il trigger per controllare per vedere se ItemSelected è x:Null e impostare la proprietà di Testo “non è Selezionato Nulla”.

    • Utente chiede come avere un “nulla di selezionato” valore della combobox, di non avere un look diverso per un vuoto combobox.
    • So. Si può impostare un trigger nel modello di controllo che consente di verificare lo stato degli Elementi selezionati e se è null, quindi impostare il valore del testo di la casella “non è Selezionato Nulla”. Speravo che l’utente potrebbe dedurre che l’esempio dato. Aggiornata la mia risposta, che si adatta meglio.
    • Marrone: ho modificato la mia risposta, in modo sarei grato se potesse remoto il downvote.
  5. 1

    So che questo è un vecchio thread, ma qui è come lo faccio. Dopo recuperare la Thingos collezione, ho semplicemente inserire un nuovo Thingo con un ID falso valore e visualizza il valore di “Selezionare un thingo.”

        public ThingoSelectionViewModel(IProvideThingos) {
                this.Thingos = IProvideThingos.GetThingos();
                Thingo newThingo = new Thingo();
                newThingo.ThingoID = -1;
                newThingo.ThingoDisplayName = "Select a thingo";
                this.Thingos.Insert(0, newThingo);
            }

    Ora, quando la ComboBox è associato a dati, la prima voce è “Selezionare un thingo.” Poi, quando un Thingo è selezionata, I test ID del SelectedThingo, e agire di conseguenza.

    • Questo è fondamentalmente l’Oggetto Nullo Modello. Io a volte uso una proprietà statica della classe per esporre l’Oggetto Nullo modo, le persone possono controllare il loro thingo contro Thingo.NotSpecified.
    • Figure….. Spesso mi sono chiesto se io o uso di “tal dei tali” una metodologia o di un processo, e credo che la risposta sia “No”. Solo per scoprire che la risposta è “Sì”, ma solo che non sapevo che cosa è stata ufficialmente chiamata. Grazie.
  6. 0

    So di resuscitare un vecchio post, ma questo è il primo che è venuto la mia ricerca su google.
    In Visual Studio, è possibile scegliere di impostare la Selezione di Default a 0, invece di -1, e solo la tua prima selezione il testo di default.

    <ComboBox x:name="ThingoSelector" SelectedIndex="0">
        <ComboBoxItem IsEnabled="False">Choose Thingo</ComboBoxItem>
        <ComboBoxItem>Thingo 1</ComboBoxItem>
    </ComboBox>
  7. 0

    Un’altra opzione:

    HTML:

    <ComboBox>
      <ComboBoxItem Visibility="Collapsed" IsSelected="True">
        <TextBlock Text="Choose item" />
      </ComboBoxItem>
      <ComboBoxItem>
        <TextBlock Text="Item 1" />
      </ComboBoxItem>
      <ComboBoxItem>
        <TextBlock Text="Item 2" />
      </ComboBoxItem>
    </ComboBox>

Lascia un commento