2009-07-27 31 views
28

Supponiamo di avere un collegamento DataSource a una raccolta dal database. Non esiste ovviamente un oggetto nullo. Come aggiungere un elemento vuoto in un ComboBox, in modo che al primo caricamento l'utente possa vedere una stringa vuota. Non voglio aggiungere un oggetto fittizio/vuoto alla Raccolta. Ottimamente in XAML. Qualche proposta?ComboBox con articolo vuoto?

+3

Attenzione, che la soluzione fornita non funziona con il legame. – Cartesius00

+2

Ho trovato un modo per aggirare il problema di binding vedere questo post: http://stackoverflow.com/questions/6446699/how-do-you-bind-a-collectioncontainer-to-a-collection-in-a-view-model – Frinavale

risposta

36
<ComboBox Name="myComboBox" Width="200" Background="White">  
    <ComboBox.ItemsSource>  
     <CompositeCollection> 
      <ComboBoxItem IsEnabled="False" Foreground="Black">Select Item</ComboBoxItem> 
      <CollectionContainer Collection="{Binding Source={StaticResource DataKey}}" />  
     </CompositeCollection> 
    </ComboBox.ItemsSource> 
</ComboBox> 

EDIT

Come @surfen menzionato nel commento, BindingProxy è soluzione per il problema di legame

+0

OK meraviglioso. Ma come rendere il primo oggetto non selezionabile? È possibile selezionare solo gli elementi dell'origine dati. –

+2

Vedere post modificato, è sufficiente aggiungere IsEnabled = "False" Primo piano = "Nero" alle proprietà degli articoli –

+0

OK scusate non ho notato che proprietà. Grazie ! –

2
<UserControl.Resources> 
    <CollectionViewSource x:Key="Modules" Source="{Binding Path=Modules}" /> 
</UserControl.Resources> 

<abv:ComboBox SelectedIndex="0" IsNullable="True" 
    SelectedItem="{Binding Path=SelectedModule, Mode=TwoWay}"> 
    <abv:ComboBox.ItemsSource> 
     <CompositeCollection> 
      <ComboBoxItem Content="{DynamicResource EmptyModuleComboBox}"/> 
      <CollectionContainer Collection="{Binding Source={StaticResource Modules}}" /> 
     </CompositeCollection> 
    </abv:ComboBox.ItemsSource> 
</abv:ComboBox> 

public class ComboBox : System.Windows.Controls.ComboBox 
{ 
    public static readonly DependencyProperty IsNullableProperty = 
     DependencyProperty.Register("IsNullable", typeof(bool), typeof(ComboBox)); 

    public bool IsNullable 
    { 
     get { return (bool)GetValue(IsNullableProperty); } 
     set { SetValue(IsNullableProperty, value); } 
    } 

    public ComboBox() 
    { 
     Loaded += ComboBox_Loaded; 
    } 

    void ComboBox_Loaded(object sender, RoutedEventArgs e) 
    { 

     if (IsNullable) 
     { 
      this.ItemContainerStyle = new Style(); 

      this.ItemContainerStyle.Setters.Add(new EventSetter() 
      { 
       Event = ComboBoxItem.PreviewMouseUpEvent, 
       Handler = new MouseButtonEventHandler(cmbItem_PreviewMouseUp) 
      }); 
     } 
    } 

    public void cmbItem_PreviewMouseUp(object sender, MouseButtonEventArgs e) 
    { 
     if (Items.IndexOf(sender as ComboBoxItem) == 0) 
     { 
      SelectedItem = null; 
     } 
    } 
} 
+1

Puoi spiegare perché questo lavori? – nikaltipar

+0

Questo funziona per abbonarsi all'evento mouse up –

1

Per vincolante per MVVM oggetto:

     <ComboBox Name="cbbFiltres" SelectedItem="{Binding ElmtInfo, Mode=TwoWay}" Height="26" MinWidth="90" SelectedIndex="0" SelectedValuePath="Id"> 
         <ComboBox.Resources> 
          <CollectionViewSource x:Key="cvsFiltres" Source="{Binding Elmts.items}"/> 
         </ComboBox.Resources> 
         <ComboBox.ItemsSource> 
          <CompositeCollection> 
           <model:tblFiltreChamps Desc="{x:Static resx:resMain.enumAucun}" Id="0"/> 
           <CollectionContainer Collection="{Binding Source={StaticResource cvsFiltres}}" /> 
          </CompositeCollection> 
         </ComboBox.ItemsSource> 
        </ComboBox> 

E per il legame on:

<Label Visibility="{Binding Path=SelectedValue, ElementName=cbbFiltres, Converter={StaticResource NullToVisibility}}" /> 

e il convertitore generico:

public class ConvNullToVisibility : IValueConverter { 
    /// <summary>Convertisseur pour le Get.</summary> 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { 
     if (DesignerProperties.GetIsInDesignMode(new DependencyObject())) return Visibility.Visible; // Pour annuler l'effet dans le designer: http://stackoverflow.com/questions/33401900/wpf-detect-design-mode-in-a-converter 
     return ((value == null) || (string.IsNullOrEmpty(value.ToString())) || (value.ToString() == "0")) ? Visibility.Collapsed : Visibility.Visible; 
    } 

    /// <summary>Convertisseur inverse, pour le Set (Binding).</summary> 
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { 
     if (value is Visibility) { 
      return (((Visibility)value) == Visibility.Visible) ? true : false; 
     } else return false; 
    } 
} 

Proprio importante dichiarare il SelectedValuePath in combobox. :-)

0

Prova la casella combinata di Mahapps.

xmlns: controlli = "http://metro.mahapps.com/winfx/xaml/controls"

<ComboBox x:Name="bars" **controls:TextBoxHelper.ClearTextButton="True"** 
       DisplayMemberPath="Name" 
       Height="21" 
       SelectedItem="{Binding Bar}"/> 

Combo Box View