2010-10-01 39 views
6

Có vẻ WFP DataGridComboBoxColumn đang sử dụng một ItemsSource duy nhất cho tất cả các ô trong cột này. Tôi có một trường hợp các mục ComboBox phụ thuộc vào ô khác trong cùng một hàng. Tôi quản lý để cư trú ItemsSource trong sự kiện PreparingCellForEdit. Tuy nhiên, nó không hoạt động như mong muốn. Ban đầu, tất cả các ô trong cột này đều trống. Khi tôi điền vào ItemsSource cho ComboBox của cột này, tất cả các ô có liên quan (với cùng một nguồn mục) đều hiển thị các giá trị. Tuy nhiên, nếu tôi nhấp vào một loại ô khác (một nguồn mục khác được điền), tất cả các giá trị sẽ biến mất và các ô loại mới sẽ hiển thị các giá trị. Bạn chỉ có thể sử dụng một bộ Nguồn mục cho một cột? Tôi không thể tin nó là sự thật. Tôi đã bỏ lỡ bất cứ điều gì? Có cách giải quyết nào không?Làm thế nào để có được ComboBox cấp tế bào cho WPF DataGrid?

Trả lời

1

Nhờ ví dụ của Jonathan, tôi giải quyết vấn đề của tôi như sau. Tôi đã sửa đổi mã của Jonathan để làm nổi bật giải pháp của tôi. Tôi đã xóa thuộc tính Territory khỏi ví dụ của anh ấy vì tôi không cần nó vì vấn đề của tôi.

Có hai cột. Cột đầu tiên là State. Cột thứ hai là StateCandidate. Cột trạng thái được liên kết với một danh sách các trạng thái, và cột StateCandidate được liên kết với một danh sách StateCandidates. Điểm mấu chốt là danh sách StateCandidates được tạo lại khi trạng thái được thay đổi. Vì vậy, có thể có một danh sách khác nhau của StateCandidates trong mỗi hàng (dựa trên trạng thái được chọn).

MainWindow.xaml

<Window x:Class="WpfTest1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <DataGrid Name="Zoom" AutoGenerateColumns="False" Background="DarkGray" RowHeaderWidth="50" HeadersVisibility="All"> 
      <DataGrid.Columns> 
       <DataGridTemplateColumn x:Name="colState" Header="State" Width="120"> 
        <DataGridTemplateColumn.CellTemplate> 
         <DataTemplate> 
          <TextBlock Text="{Binding State}" /> 
         </DataTemplate> 
        </DataGridTemplateColumn.CellTemplate> 
        <DataGridTemplateColumn.CellEditingTemplate> 
         <DataTemplate> 
          <ComboBox SelectedItem="{Binding State}" ItemsSource="{Binding States}" /> 
         </DataTemplate> 
        </DataGridTemplateColumn.CellEditingTemplate> 
       </DataGridTemplateColumn> 
       <DataGridTemplateColumn x:Name="colStateCandiate" Header="State Candidate" Width="200"> 
        <DataGridTemplateColumn.CellTemplate> 
         <DataTemplate> 
          <TextBlock Text="{Binding StateCandidate}" /> 
         </DataTemplate> 
        </DataGridTemplateColumn.CellTemplate> 
        <DataGridTemplateColumn.CellEditingTemplate> 
         <DataTemplate> 
          <ComboBox SelectedItem="{Binding StateCandidate}" ItemsSource="{Binding StateCandidates}" /> 
         </DataTemplate> 
        </DataGridTemplateColumn.CellEditingTemplate> 
       </DataGridTemplateColumn> 
      </DataGrid.Columns> 
     </DataGrid> 
    </Grid> 
</Window> 

MainWindow.xaml.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.ComponentModel; 

namespace WpfTest1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      List<Model> list = new List<Model>(); 
      list.Add(new Model() { State = "TX", StateCandidate = "TX2" }); 
      list.Add(new Model() { State = "CA" }); 
      list.Add(new Model() { State = "NY", StateCandidate = "NY1" }); 
      list.Add(new Model() { State = "TX" }); 
      list.Add(new Model() { State = "AK" }); 
      list.Add(new Model() { State = "MN" }); 

      Zoom.ItemsSource = list; 
      Zoom.PreparingCellForEdit += new EventHandler<DataGridPreparingCellForEditEventArgs>(Zoom_PreparingCellForEdit); 
     } 

     void Zoom_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e) 
     { 
      if (e.Column == colStateCandiate) 
      {     
       DataGridCell cell = e.Column.GetCellContent(e.Row).Parent as DataGridCell; 
       cell.IsEnabled = (e.Row.Item as Model).StateCandidates != null; 
      } 
     } 
    } 
    public class Model : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     private string _state; 
     private List<string> _states = new List<string>() { "CA", "TX", "NY", "IL", "MN", "AK" }; 
     private string _stateCandidate; 
     private List<string> _stateCandidates; 

     public string State 
     { 
      get { return _state; } 
      set 
      { 
       if (_state != value) 
       { 
        _state = value; 
        _stateCandidate = null; 
        if (_state == "CA" || _state == "TX" || _state == "NY") 
         _stateCandidates = new List<string> { _state + "1", _state + "2" }; 
        else 
         _stateCandidates = null; 
        OnPropertyChanged("State"); 
       } 
      } 
     } 
     public List<string> States 
     { 
      get { return _states; } 
     } 
     public string StateCandidate 
     { 
      get { return _stateCandidate; } 
      set 
      { 
       if (_stateCandidate != value) 
       { 
        _stateCandidate = value; 
        OnPropertyChanged("StateCandidate"); 
       } 
      } 
     } 
     public List<string> StateCandidates 
     { 
      get { return _stateCandidates; } 
     } 
     public void OnPropertyChanged(string name) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
} 

Lưu ý rằng, khi Nhà nước thay đổi, nó sẽ không cập nhật danh sách StateCandidates cho đến khi một dãy ghế khác được chọn, đó là một vấn đề riêng biệt tôi sẽ chiến đấu. Có ai biết tôi có thể ép buộc không?

Cảm ơn Jonathan một lần nữa vì cảm hứng của mình. Tôi sẽ tiếp tục tìm kiếm một giải pháp tốt hơn.

+0

Bạn đang đi xuống con đường chính xác giống như hư không tôi đã ở trên. Nhưng kể từ khi bạn nhấn mạnh, đây là mã: http://www.scottlogic.co.uk/blog/colin/tag/ieditableobject/ –

+2

@ Jonathan: Cảm ơn bạn rất nhiều vì đã liên kết. Tuy nhiên, tôi không thể thực hiện công việc đó cho mẫu này, có thể vì tôi không sử dụng DataTable. Trong khi xáo trộn với điều đó, tôi đã tìm thấy một nhận xét trong blog đó trỏ đến http://codefluff.blogspot.com/2010/05/commiting-bound-cell-changes.html. Giải pháp này hoạt động rất tốt. – newman

+0

Ứng dụng của tôi, tôi đã đăng liên kết sai. Tôi cũng không sử dụng DataTable, liên kết của bạn thực sự là liên kết mà tôi đã sử dụng. –

2

Có thể bạn không thể thực hiện điều đó một cách đáng tin cậy. Lưới có thể tái sử dụng hộp kết hợp hoặc tạo ngẫu nhiên/phá hủy nó.

Cơ hội tôi chỉ tình cờ làm việc trên màn hình thực hiện điều đó. Với những ...

  • Mỗi hàng trong lưới được gắn với một đối tượng thuộc loại Thương mại.
  • Mỗi Thương mại có một tài sản Nhà nước
  • Mỗi Thương mại có một tài sản TerritoryCanidates
  • Thay đổi sở hữu Nhà nước sẽ gây ra tài sản TerritoryCanidates thay đổi

này mang lại cho tôi khả năng để ràng buộc các ItemsSource đến TerritoryCanidates bất động sản. Mà lần lượt DataGrid sẽ tôn vinh trong mọi trường hợp.


<Window x:Class="MainWindow" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <DataGrid Name="Zoom" AutoGenerateColumns="False"> 
     <DataGrid.Columns> 
      <DataGridTemplateColumn Header="State"> 
       <DataGridTemplateColumn.CellTemplate> 
        <DataTemplate> 
         <TextBlock Text="{Binding State}" /> 
        </DataTemplate> 
       </DataGridTemplateColumn.CellTemplate> 
       <DataGridTemplateColumn.CellEditingTemplate> 
        <DataTemplate> 
         <ComboBox SelectedItem="{Binding State}" ItemsSource="{Binding StateCanidates}" /> 
        </DataTemplate> 
       </DataGridTemplateColumn.CellEditingTemplate> 
      </DataGridTemplateColumn> 

      <DataGridTemplateColumn Header="Territory"> 
       <DataGridTemplateColumn.CellTemplate> 
        <DataTemplate> 
         <TextBlock Text="{Binding Territory}" /> 
        </DataTemplate> 
       </DataGridTemplateColumn.CellTemplate> 
       <DataGridTemplateColumn.CellEditingTemplate> 
        <DataTemplate> 
         <ComboBox SelectedItem="{Binding Territory}" ItemsSource="{Binding TerritoryCanidates}" /> 
        </DataTemplate> 
       </DataGridTemplateColumn.CellEditingTemplate> 
      </DataGridTemplateColumn> 

     </DataGrid.Columns> 

    </DataGrid> 
</Grid> 
</Window> 


Imports System.ComponentModel 

Class MainWindow 
Sub New() 

    ' This call is required by the designer. 
    InitializeComponent() 

    ' Add any initialization after the InitializeComponent() call. 
    Dim x As New List(Of Model) 
    x.Add(New Model) 
    x.Add(New Model) 
    x.Add(New Model) 

    Zoom.ItemsSource = x 
End Sub 
End Class 

Class Model 
Implements INotifyPropertyChanged 

Public ReadOnly Property StateCanidates As List(Of String) 
    Get 
     Return New List(Of String) From {"CA", "TX", "NY"} 
    End Get 
End Property 

Public ReadOnly Property TerritoryCanidates As List(Of String) 
    Get 
     If State = "" Then Return Nothing 
     Return New List(Of String) From {State & "1", State & "2"} 
    End Get 
End Property 

Private m_State As String 
Public Property State() As String 
    Get 
     Return m_State 
    End Get 
    Set(ByVal value As String) 
     m_State = value 
     OnPropertyChanged("State") 
     OnPropertyChanged("TerritoryCanidates") 
    End Set 
End Property 

Private m_Territory As String 
Public Property Territory() As String 
    Get 
     Return m_Territory 
    End Get 
    Set(ByVal value As String) 
     m_Territory = value 
     OnPropertyChanged("Territory") 
    End Set 
End Property 




Public Sub OnPropertyChanged(ByVal propertyName As String) 
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) 
End Sub 

Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged 
End Class 
+0

Tôi đang nhầm lẫn ... Tính năng này có phù hợp với bạn không? Tôi chỉ thử nó và không thể làm cho nó hoạt động được. Những gì tôi đã thử là như thế này: Tôi đã thực hiện một bộ sưu tập mới cho ItemsSource để liên kết. Bộ sưu tập này sẽ được tạo lại khi một thuộc tính khác thay đổi. Tôi không thấy bất cứ điều gì trong hộp thả xuống combobox. – newman

+0

Rất tiếc, có vẻ như cột hộp tổ hợp tích hợp không hoạt động như tôi mong đợi. Tôi đã làm ví dụ của tôi bằng cách sử dụng các cột mẫu như chương trình thực sự của tôi sử dụng. –

+1

P.S. Bây giờ tôi chính thức ghét DataGrid để chỉnh sửa dữ liệu. Tôi thay vì chỉ sử dụng một ItemsControl. –

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