2010-05-25 13 views
8

G'day!Bir WPF ComboBox, seçimi boş olduğunda alternatif metni görüntüleyebilir mi?

WPF ComboBox ürünümün, veriye bağlı seçimi null olduğunda bazı alternatif metinleri göstermesini istiyorum.

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 
    } 

    // ... 

} 

görünüşüdür XAML beklenen şekilde görünüşüdür modeline, bağlanma:

görünüşüdür modeli beklenen özelliklere sahip

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

ComboBoxItem bir yol için üst içine sıkışmış üstte ekstra bir öğe olsun. Bu saf krom: görünüm modeli saf ve basit kalır. Sadece bir problem var: Kullanıcılar, ComboBox 'seçiminin null olduğu her zaman "Selecto thingo" seçeneğini gösterir.

Kullanıcılar 'u yapmıyorlar, varsayılan olarak bir şey seçmek istiyorlar. Bir şey seçmelerini söyleyen bir mesaj görmek istiyorlar.

Ben ToString yöntem ben Thingos doldurmak her Thingo sarma, onun .ActualThingo özelliğinin null olması durumunda "Bir thingo seç" dönen bir ThingoWrapper sınıfı ile ViewModel kirletme zorunda kalmamak ister ve bir yolunu bulmaktan ediyorum kullanıcının nulled Thingo seçmesini engellemek.

ComboBox 'sınırlarında, saf XAML veya salt XAML ve görünümün arkadaki kod sınıfında birkaç satırlık kod kullanarak "bir şey seç" seçeneği var mı?

+0

FWIW: Ben sarılmış boş değerin seçimi ile başa çıkmak için ThingoSelectionViewModel değiştirme ve otomatik olarak seçmek için yollar bulmak, ThingoWrapper uygulanması sona erdi Whatsy ve Fadoozamy nesneleri böylece onları sarmak zorunda kalmadım. –

cevap

3

Burada bulduğum en az direnç yolu Null Object Pattern kullanmaktır. Bu modeli .NET Framework'de kullanmanın bir örneği için, Thingo'nuz için Boş Nesne oluşturuyorsanız, Double.NaN statik değerini düşünün. görünüm modelinizde "hiçbir şey seçilmediğini" belirtmek için listenizin önüne ekleyebilirsiniz. "Bir Değer Seç" yazan Boş Nesne örneği için bir DataTrigger olan Thingo sınıfı için bir DataTemplate oluşturun.

Bir kod örneği verebilir ama benim yatak zaman geçince.

3

Düzenleme: Tetik fikri bir işe yaramıyor gibi görünüyor. Ben boşuna bir test açılan kutunun kontrol şablonuna aşağıdaki eklendi:

Ayrıca, Blend kontrol şablonu düzenlemek çalışırken (Düzen Güncel) Ben özelliksiz combobox ile kaldım
<Trigger Property="SelectedItem" Value="{x:Null}"> 
     <Setter Property="Text" Value="No Item Selected"/> 
    </Trigger> 

, hiçbir renk, sadece çirkin bir düğme (ancak sınırsız bir açılır kapanır). Birisi elses önerisini deneyin (belki de Mike Brown). Orijinal

:

Denetim şablonunda bir tetikleyici kullanabilirsiniz. İşte üzerinde çalıştığım bir uygulamadan bir ListBox kullanarak bir örnek.

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

yukarıda ControlTemplate İşletme HasItems kontrol eden bir tetikleyici sahiptir. Eğer False ise, ListBox'un ortasında "No Item" yazan bir textblock görüntülenir. Öğeler varsa, görüntülenir.

Sizin durumunuzda, ItemSelected öğesinin x olup olmadığını kontrol etmek için tetiği değiştirin: Boş bırakın ve Text özelliğini "Hiçbir Şey Seçili" olarak ayarlayın.

+0

Kullanıcı, combobox'ta "hiçbir şey seçilmemiş" değerinin nasıl bulunacağını soruyor, boş bir combobox için farklı bir görünüm elde etmemek. –

+0

Biliyorum. Kontrol şablonunda seçilen Öğelerin durumunu kontrol eden bir tetikleyici belirleyebilir ve eğer boşsa o zaman kutunun metninin değerini "Hiçbir Şey Seçili" olarak ayarlayın. Kullanıcının verilen örnekten çıkarılabileceğini umuyordum. Cevabımı daha iyi uydurmak için güncellendi. – CodeWarrior

+0

@Mike Brown: Cevabımı düzenledim, bu yüzden reddetmeyi uzaktan kullanabilmen için minnettar olurdum. – CodeWarrior

4

Bir kontrol şablon tetiği kullanamazsınız, ancak combobox için basit öğe şablonu kurmak olabilir:

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

Hmm. Bunu da kontrol etmeliyim. –

8

sizin MVVM gereksinimi ne kadar sıkı? Görüşte küçük bir kodun var mı?

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 

Ayar: Bir olay işleyicisi bazı mantık eklemek

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

Sonra kod arkasında:

Belki, bir tablo içinde böyle bir şey ComboBox içerebilir TextBlock üzerinde IsHitTestVisible="False" DependencyProperty ComboBox tıklayın ve Hidden görünürlük ayarını böylece aracılığıyla fare olaylarını olanak tanıyan kod arkada olduğunda istemi etrafında atlama gelen varsayılan bir ComboBox'ın görünüm düzenini tutar metin gizli.

+1

Bunu yapmak isteseniz bile, MVVM'nizi kırmak zorunda kalmazsınız. Seçimi görünürlüğe dönüştürmek için sadece bir dönüştürücü kullanın. – Ben

1

Bu eski iplik olduğunu biliyorum, ama burada böyle yaparız. Thingos koleksiyonunu getirdikten sonra, sahte bir ID değeriyle yeni bir Thingo'yu ve "Bir thingo seçin" görüntü değeri eklemek istiyorum.

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

Şimdi, ComboBox veribound olduğunda, ilk öğe "Bir thingo seçin." Sonra bir Thingo seçildiğinde, SelectedThingo'nun kimliğini test ederim ve buna göre hareket ediyorum.

+0

Temel olarak Boş Nesne Kalıbı. Bazen boş nesneyi açığa çıkarmak için sınıfa ait statik bir özellik kullanırım, böylece insanlar Thingo.NotSpecified'a karşı kendi şeylerini kontrol edebilirler. –

+0

Rakamlar .... Sıklıkla "böyle ve böyle" bir metodoloji veya işlemi yaptığımı veya kullanıp kullanmadığımı soruyorum ve cevabın "Hayır" olduğunu düşünüyorum. Sadece cevabın 'Evet' olduğunu bulmak için ancak resmen ne çağrıldığını bilmiyordum. Teşekkürler. –

0

Ben Eski bir yayını diriltmeyi biliyorum fakat bu benim google arama geldi ilk biriydi. Visual Studio'da, Varsayılan Seçimi -1 yerine 0 olarak ayarlamayı ve yalnızca ilk seçiminizin varsayılan metin olmasını seçebilirsiniz.

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

Başka bir seçenek:

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

İlgili konular