2010-10-01 25 views
6

WFP DataGridComboBoxColumn, bu sütundaki tüm hücreler için tek bir ItemsSource kullanıyor. ComboBox öğelerinin aynı sıradaki diğer hücreye bağımlı olduğu bir durum var. ItemsSource'u PreparingCellForEdit etkinliğinde doldurmayı başardım. Ancak, istenildiği gibi çalışmıyor. Başlangıçta, bu sütundaki tüm hücreler boş. Bu sütunun ComboBox öğesi için ItemsSource'u doldurduğumda, ilgili tüm hücreler (aynı öğe kaynağına sahip) değerleri gösteriyor. Ancak, başka bir hücre türüne tıklarsam (farklı bir öğe kaynağı doldurulursa), tüm değerler kaybolur ve yeni tür hücreler değerleri gösterir. Bir sütun için yalnızca bir Öğe Kaynağı kümesini kullanabilirsiniz? Doğru olduğuna inanamıyorum. Bir şey mi kaçırdım? Herhangi bir geçici çözüm var mı?WPF DataGrid için hücre düzeyi ComboBox nasıl alınır?

cevap

1

Teşekkür Jonathan örneğe, benim sorun çözüldü. Çözümü vurgulamak için Jonathan'ın kodunu değiştirdim. Territory özelliğini örneğinden çıkardım çünkü problemim için buna ihtiyacım yok.

İki sütun var. İlk sütun Devlettir. İkinci sütun StateCandidate. Durum sütunu bir Devletler listesine bağlanır ve StateCandidate sütunu bir StateCandidates listesine bağlanır. Anahtar nokta, durum değiştiğinde StateCandidates listesinin yeniden oluşturulmasıdır. Dolayısıyla, her satırda farklı bir StateCandidates listesi seçilebilir (seçilen duruma göre).

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 Devlet değiştirildiğinde farklı bir satır seçildiğinde kadar, öyle ki, StateCandidates listesini güncellemek olmaz, o

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)); 
     } 
    } 
} 

Not Ayrılmış bir konu savaşacağım. İşlemeyi nasıl zorlayabileceğimi bilen var mı?

Onun ilhamı için tekrar Jonathan'a teşekkürler. Daha iyi bir çözüm aramaya devam edeceğim.

+0

Tam olarak aynı yoldan aşağıya inildim. Ama ısrar ettiğin için, işte buradaki kod: http://www.scottlogic.co.uk/blog/colin/tag/ieditableobject/ –

+2

@Jonathan: Link için çok teşekkür ederim. Ancak, bu örnek için bu işi yapamadım çünkü belki DataTable'ı kullanmıyorum. Bununla boğuşurken, bu blogda http://codefluff.blogspot.com/2010/05/commiting-bound-cell-changes.html adresine işaret eden bir yorum buldum. Bu çözüm harika çalışıyor. – newman

+0

Benim incelemelerim, yanlış link gönderdim. Ben de bir DataTable kullanmıyorum, bağlantınız aslında bittiğim bir şey. –

2

Muhtemelen bunu güvenilir bir şekilde yapamazsınız. Izgara, açılan kutuyu yeniden kullanabilir veya rastgele oluşturabilir/yok edebilir.

Şans eseri, sadece bunu yapan bir ekranda çalışıyorum. Bunlar ...

  • Kılavuzdaki her satır Ticaret türünde bir nesneye bağlı.
  • Her Ticaret Devlet özelliğine sahiptir
  • Her Ticaret Bu bana TerritoryCanidates için ItemsSource bağlanma olanağı verir

değiştirmeye TerritoryCanidates özelliğini neden olacaktır Devlet özelliğini değiştirme TerritoryCanidates özelliği

  • sahiptir özelliği. Hangi sırayla DataGrid her koşulda onurlandıracak. aşağıdaki gibi


    <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

    Kafam karıştı ... Sizin için çalışıyor mu? Sadece denedim ve işe yaramayacaktım. Denediğim şudur: ItemsSource için yeni bir koleksiyon hazırladım. Başka bir özellik değiştiğinde bu koleksiyon yeniden oluşturulacak. Açılır kutuda herhangi bir şey göremiyorum. – newman

    +0

    Garip, yerleşik birleşik kutu sütunu beklediğim gibi çalışmıyor gibi görünüyor. Örneğimi gerçek program kullanımlarım gibi şablon sütunlarını kullanarak yaptım. –

    +1

    P.S. Artık verileri düzenlemek için DataGrid'den resmen nefret ediyorum. Bunun yerine bir ItemsControl kullanacağım. –