2010-05-25 27 views
8

G'day!Hộp Combo WPF có thể hiển thị văn bản thay thế khi lựa chọn của nó là null không?

Tôi muốn WPF ComboBox của mình hiển thị một số văn bản thay thế khi lựa chọn giới hạn dữ liệu là null.

Mô hình xem có các thuộc tính mong đợi:

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 
    } 

    // ... 

} 

Quan điểm đã XAML ràng buộc với mô hình điểm trong cách dự kiến:

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

Các ComboBoxItem rúc vào đầu là một cách để có thêm một mục ở trên cùng. Đó là chrome thuần túy: mô hình xem vẫn tinh khiết và đơn giản. Chỉ có một vấn đề: người dùng muốn "Chọn một điều" được hiển thị bất cứ khi nào lựa chọn của ComboBox là rỗng.

Người dùng thực hiện không muốn điều được chọn theo mặc định. Họ muốn thấy một thông báo bảo họ chọn một điều.

Tôi muốn tránh việc gây ô nhiễm viewmodel với một lớp ThingoWrapper với một phương pháp ToString trở về "Chọn một thingo" nếu tài sản .ActualThingo của nó là null, gói mỗi Thingo như tôi cư Thingos, và tìm ra một số cách để ngăn người dùng lựa chọn số Thingo.

Có cách nào để hiển thị "Chọn một điều" trong ranh giới ComboBox 'sử dụng XAML thuần túy hoặc XAML thuần túy và một vài dòng mã trong lớp mã sau của chế độ xem không?

+0

FWIW: tôi đã kết thúc thực hiện ThingoWrapper, sửa đổi ThingoSelectionViewModel để đối phó với sự lựa chọn của các giá trị null bọc, và tìm cách để tự động chọn các vật thể Whatsy và Fadoozamy nên tôi cũng không phải quấn chúng nữa. –

Trả lời

3

Đường dẫn kháng cự ít nhất ở đây mà tôi đã tìm thấy là sử dụng Null Object Pattern Ví dụ về cách sử dụng mẫu này trong Khuôn khổ .NET, hãy xem xét giá trị tĩnh Double.NaN nếu bạn tạo đối tượng Null cho Thingo, trong mô hình chế độ xem của mình, bạn có thể thêm nó vào mặt trước của danh sách để biểu thị "không có gì được chọn". Tạo một DataTemplate cho lớp Thingo có một DataTrigger cho đối tượng Null Object hiển thị "Select a Value".

Tôi có thể cung cấp mẫu mã nhưng đã qua thời gian đi ngủ của tôi.

3

Chỉnh sửa: Có vẻ như ý tưởng kích hoạt là không có. Tôi được thêm vào sau vào mẫu kiểm soát của một hộp kiểm tra kết hợp không có kết quả:

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

Thêm vào đó, khi cố gắng chỉnh sửa các mẫu kiểm soát trong Blend (Edit Current) Tôi đang trái với một combobox gì đặc biệt, không có màu sắc, chỉ là một nút xấu xí (nhưng có một trình đơn thả xuống không viền). Hãy thử một đề nghị elses ai đó (Mike Brown có lẽ).

gốc:

Bạn có thể sử dụng một Trigger trong mẫu kiểm soát. Dưới đây là một ví dụ bằng cách sử dụng ListBox từ một ứng dụng tôi đang làm việc.

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

ControlTemplate ở trên có Trình kích hoạt kiểm tra thuộc tính sản phẩm. Nếu False, một textblock nói "No Items" được hiển thị ở giữa ListBox. Nếu có các mục, chúng được hiển thị.

Trong trường hợp của bạn, hãy thay đổi trình kích hoạt để kiểm tra xem ItemSelected là x: Null và đặt thuộc tính Text thành "Nothing Selected".

+0

Người dùng đang yêu cầu cách có giá trị "không có gì được chọn" trong combobox, không có giao diện khác cho combobox trống. –

+0

Tôi biết. Họ có thể thiết lập một kích hoạt trong mẫu điều khiển kiểm tra trạng thái của các mục được chọn và nếu nó là null sau đó đặt giá trị của văn bản của hộp thành "Không có gì được chọn". Tôi đã hy vọng người dùng có thể phỏng đoán điều đó từ ví dụ được đưa ra. Cập nhật câu trả lời của tôi để phù hợp hơn. – CodeWarrior

+0

@Mike Brown: Tôi đã chỉnh sửa câu trả lời của tôi, vì vậy tôi sẽ đánh giá cao nếu bạn có thể từ xa downvote. – CodeWarrior

4

Bạn không thể sử dụng một điều khiển mẫu cò, nhưng bạn có thể thiết lập một mục khung mẫu đơn giản cho các 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> 
+0

Hmm. Tôi cũng sẽ phải kiểm tra cái này. –

8

Làm thế nào nghiêm ngặt là yêu cầu MVVM của bạn? Bạn có thể có một chút code-behind trong xem?

lẽ bạn có thể chứa ComboBox trong một mạng lưới, một cái gì đó như thế này:

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

Sau đó, trong code-behind, chèn một số logic trong một event handler:

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 

Thiết lập IsHitTestVisible="False" DependencyProperty trên TextBlock cho phép các sự kiện chuột thông qua để bạn có thể bấm vào ComboBox, và thiết lập khả năng hiển thị thành Hidden trong mã-đằng sau giữ bố cục xuất hiện của ComboBox mặc định khi nhảy xung quanh khi lời nhắc văn bản bị ẩn.

+1

Thậm chí nếu bạn muốn làm điều đó theo cách bạn không phải phá vỡ MVVM của bạn. Chỉ cần sử dụng công cụ chuyển đổi để chuyển đổi lựa chọn thành chế độ hiển thị. – Ben

1

Tôi biết đây là một chủ đề cũ, nhưng đây là cách tôi làm điều đó. Sau khi tôi lấy bộ sưu tập Thingos, tôi chỉ cần chèn một Thingo mới với một giá trị ID không có thật và một giá trị hiển thị của "Chọn một điều."

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

Bây giờ, khi ComboBox là databound, mục đầu tiên là "Chọn một điều". Sau đó, khi một Thingo được chọn, tôi kiểm tra ID của SelectedThingo, và hành động trên nó cho phù hợp.

+0

Về cơ bản là Mẫu đối tượng Null. Đôi khi tôi sử dụng một thuộc tính tĩnh của lớp để lộ đối tượng Null để mọi người có thể kiểm tra điều của họ đối với Thingo.NotSpecified. –

+0

Hình .... Tôi thường được hỏi liệu tôi có sử dụng hoặc sử dụng phương pháp hoặc quy trình "như vậy và như vậy" và tôi nghĩ câu trả lời là 'Không'. Chỉ để tìm ra câu trả lời là 'Có', nhưng tôi đơn giản là không biết nó được chính thức gọi là gì. Cảm ơn. –

0

Tôi biết tôi đang hồi sinh bài đăng cũ, nhưng đây là bài đăng đầu tiên xuất hiện trên tìm kiếm google của tôi. Trong Visual Studio, bạn có thể chọn đặt Default Selection thành 0, thay vì -1 và chỉ có lựa chọn đầu tiên của bạn là văn bản mặc định.

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

Một tùy chọn khác:

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

Các vấn đề liên quan