2010-05-25 9 views
8

Gday!क्या एक WPF कॉम्बोबॉक्स वैकल्पिक चयन प्रदर्शित कर सकता है जब उसका चयन शून्य हो?

मैं जब अपने डेटा-बाउंड चयन null है मेरी WPF ComboBox कुछ वैकल्पिक पाठ प्रदर्शित करना चाहते हैं।

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 
    } 

    // ... 

} 

दृश्य XAML उम्मीद तरह से दृश्य मॉडल के लिए बाध्य किया गया है::

दृश्य मॉडल की उम्मीद गुण है

<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 शीर्ष में अंकित लिए एक रास्ता है शीर्ष पर एक अतिरिक्त आइटम प्राप्त करें। यह शुद्ध क्रोम है: दृश्य मॉडल शुद्ध और सरल रहता है। केवल एक समस्या है: जब भी कॉम्बोबॉक्स का चयन शून्य होता है तो उपयोगकर्ता प्रदर्शित होते हैं "एक चीज़ो चुनें"।

उपयोगकर्ता डिफ़ॉल्ट रूप से कोई चीज़ नहीं चुनते हैं। वे एक चीज़ को चुनने के लिए उन्हें एक संदेश देखना चाहते हैं।

मैं एक ToString विधि लौटने "एक thingo चुनें" अगर इसकी .ActualThingo संपत्ति शून्य है, प्रत्येक Thingo लपेटकर के रूप में मैं Thingos पॉप्युलेट के साथ एक ThingoWrapper वर्ग के साथ viewmodel अपवित्र से बचने के लिए चाहते हैं, और किसी तरह पता लगाना उपयोगकर्ता को Thingo को चुनने से रोकें।

क्या ComboBox 'शुद्ध एक्सएएमएल, या शुद्ध एक्सएएमएल और दृश्य कोड कोड-बैक क्लास में कोड की कुछ पंक्तियों का उपयोग करते हुए' एक चीज़ो का चयन करें 'प्रदर्शित करने का कोई तरीका है?

+0

FWIW: मैं ThingoWrapper को लागू करने समाप्त हो गया, ThingoSelectionViewModel संशोधित लिपटे शून्य मान के चयन से निपटने के लिए, और तरीके स्वचालित रूप से चयन करने के लिए खोजने Whatsy और Fadoozamy वस्तुओं तो मुझे भी उन्हें लपेटना नहीं था, भी। –

उत्तर

3

मैंने पाया है कि कम से कम प्रतिरोध का मार्ग Null Object Pattern का उपयोग करना है। इस पैटर्न का उपयोग .NET Framework में करने के उदाहरण के लिए, स्थिर मूल्य Double.NaN पर विचार करें यदि आप अपने थिंगो के लिए एक नल ऑब्जेक्ट बनाते हैं, अपने दृश्य मॉडल में आप "सूची में कुछ भी नहीं चुना गया है" को इंगित करने के लिए इसे अपनी सूची के सामने जोड़ सकते हैं। थिंगो क्लास के लिए डेटा टेम्पलेट बनाएं जिसमें नल ऑब्जेक्ट इंस्टेंस के लिए डेटाट्रिगर है जो "एक मान चुनें" दिखाता है।

मैं एक कोड नमूना दे सकता था लेकिन यह मेरे बिस्तर के समय से पहले है।

3

संपादित करें: ऐसा लगता है कि ट्रिगर विचार कोई नहीं है। मैं कोई लाभ नहीं हुआ एक परीक्षण कॉम्बो बॉक्स के नियंत्रण टेम्पलेट के लिए निम्न कहा:

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

इसके अतिरिक्त, जब मिश्रण में नियंत्रण टेम्पलेट को संपादित करने की कोशिश कर (वर्तमान संपादित करें) मैं एक कुरूप बता गया के साथ छोड़ दिया हूँ, कोई रंग, सिर्फ एक बदसूरत बटन (लेकिन एक सीमा रहित ड्रॉपडाउन है)। किसी को एल्स सुझाव (माइक ब्राउन शायद) आज़माएं।

मूल:

आप नियंत्रण टेम्पलेट में एक उत्प्रेरक का उपयोग कर सकते हैं। यहां एक ऐप से लिस्टबॉक्स का उपयोग करके एक उदाहरण दिया गया है जिस पर मैं काम कर रहा हूं।

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

उपरोक्त नियंत्रण टेम्पलेट में एक ट्रिगर है जो संपत्ति HasItems की जांच करता है। यदि गलत है, तो टेक्स्टबॉक्स के बीच में "नो आइटम" प्रदर्शित करने वाला टेक्स्टब्लॉक प्रदर्शित होता है। यदि आइटम हैं, तो वे प्रदर्शित होते हैं।

आपके मामले में यह देखने के लिए ट्रिगर को बदलें कि आइटम का चयन किया गया है x: नल और टेक्स्ट प्रॉपर्टी को "कुछ भी नहीं चुना गया" पर सेट करें।

+0

उपयोगकर्ता पूछताछ करता है कि कैसे combobox में "कुछ भी नहीं चुना गया" मूल्य है, खाली कंबोबॉक्स के लिए अलग दिखने के लिए नहीं। –

+0

मुझे पता है। वे नियंत्रण टेम्पलेट में एक ट्रिगर सेट कर सकते हैं जो चयनित आइटमों की स्थिति की जांच करता है और यदि यह शून्य है तो बॉक्स के टेक्स्ट का मान "कुछ भी नहीं चुना गया" पर सेट करें। मैं उम्मीद कर रहा था कि उपयोगकर्ता उस उदाहरण से अनुमान लगा सकता है। बेहतर फिट करने के लिए मेरा जवाब अपडेट किया गया। – CodeWarrior

+0

@ माइक ब्राउन: मैंने अपना जवाब संपादित कर लिया है, इसलिए अगर आप डाउनवोट को रिमोट कर सकते हैं तो मैं इसकी सराहना करता हूं। – CodeWarrior

4

आप एक नियंत्रण टेम्पलेट ट्रिगर उपयोग नहीं कर सकते, लेकिन आप बता गया के लिए एक सरल आइटम टेम्पलेट सेट कर सकते हैं:

<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

हम्म। मुझे इसे भी देखना होगा। –

8

कैसे सख्त अपने MVVM आवश्यकता है? क्या आपके पास दृश्य में थोड़ा कोड-पीछे हो सकता है?

शायद आप कुछ इस तरह एक ग्रिड में ComboBox हो सकता है,:

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

फिर, में कोड-पीछे, एक ईवेंट हैंडलर में कुछ तर्क सम्मिलित करें:

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 

स्थापना IsHitTestVisible="False" टेक्स्टब्लॉक पर निर्भरता प्रॉपर्टी माउस घटनाओं को इस माध्यम से करने देती है ताकि आप कॉम्बोबॉक्स पर क्लिक कर सकें और दृश्य-दृश्य को Hidden पर कोड-बैक में डिफ़ॉल्ट कॉम्बोबॉक्स की उपस्थिति को लेआउट से चारों ओर कूदने से रोकता है पाठ छिपा हुआ है।

+1

भले ही आप इसे ऐसा करना चाहते हैं, आपको अपने एमवीवीएम को तोड़ना नहीं है। चयन को दृश्यता में बदलने के लिए बस एक कनवर्टर का उपयोग करें। – Ben

1

मुझे पता है कि यह एक पुराना धागा है, लेकिन यहां मैं यह कैसे करता हूं। थिंगोस संग्रह लाने के बाद, मैं बस एक नया थिंगो एक फर्जी आईडी मान के साथ डालें और "एक चीज़ चुनें।"

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

अब, जब कॉम्बोबॉक्स डाटाबेस है, तो पहला आइटम "एक चीज़ चुनें।" फिर जब एक थिंगो का चयन किया जाता है, तो मैं चयनित टिंगो की आईडी का परीक्षण करता हूं, और उसके अनुसार कार्य करता हूं।

+0

यह मूल रूप से शून्य ऑब्जेक्ट पैटर्न है। मैं कभी-कभी कक्षा के एक स्थिर संपत्ति का उपयोग नल ऑब्जेक्ट का पर्दाफाश करने के लिए करता हूं ताकि लोग थिंगो के खिलाफ अपनी चीज़ों की जांच कर सकें। नोटस्पेसिड। –

+0

आंकड़े .... मुझे अक्सर पूछा जाता है कि क्या मैं ऐसा करता हूं या "ऐसी और ऐसी" पद्धति या प्रक्रिया का उपयोग करता हूं, और मुझे लगता है कि उत्तर 'नंबर' है। केवल यह पता लगाने के लिए कि उत्तर 'हां' है, लेकिन मुझे बस यह नहीं पता था कि इसे आधिकारिक तौर पर क्या कहा जाता था। धन्यवाद। –

0

मुझे पता है कि मैं एक पुरानी पोस्ट को पुनर्जीवित कर रहा हूं, लेकिन यह मेरी पहली खोज थी जो मेरी Google खोज पर आई थी। विजुअल स्टूडियो में, आप डिफ़ॉल्ट चयन को 0 के बजाय 0 पर सेट करना चुन सकते हैं, और बस अपना पहला चयन डिफ़ॉल्ट टेक्स्ट होना चाहिए।

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

एक अन्य विकल्प:

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

संबंधित मुद्दे