2010-10-01 20 views
6

ऐसा लगता है कि डब्ल्यूएफपी डेटाग्रिडकंबोबॉक्स कॉलम इस कॉलम में सभी कोशिकाओं के लिए एक एकल आइटमसोर्स का उपयोग कर रहा है। मेरे पास एक ऐसा मामला है जहां कॉम्बोबॉक्स आइटम एक ही पंक्ति में दूसरे सेल पर निर्भर हैं। मैं CreateSourceCellForEdit ईवेंट में आइटम्ससोर्स को पॉप्युलेट करने में कामयाब रहा। हालांकि, यह वांछित के रूप में काम नहीं करता है। प्रारंभ में, इस कॉलम में सभी कोशिकाएं खाली हैं। एक बार जब मैं इस कॉलम के कॉम्बोबॉक्स के लिए आइटम्ससोर्स को पॉप्युलेट करता हूं, तो सभी संबंधित सेल (एक ही आइटम स्रोत के साथ) मूल्य दिखा रहे हैं। हालांकि, अगर मैं किसी अन्य प्रकार के सेल पर क्लिक करता हूं (एक अलग आइटम स्रोत पॉप्युलेट किया जाता है), सभी मान गायब हो जाते हैं और नए प्रकार के कक्ष मान दिखाते हैं। आप केवल कॉलम के लिए आइटम स्रोत के एक सेट का उपयोग कर सकते हैं? मुझे विश्वास नहीं है कि यह सच है। क्या मैं कुछ भूल गया? कोई कामकाज?WPF DataGrid के लिए सेल स्तर कॉम्बोबॉक्स कैसे प्राप्त करें?

उत्तर

1

धन्यवाद, मैं मेरी समस्या के रूप में इस संकल्प लिया। मैंने अपने समाधान को हाइलाइट करने के लिए जोनाथन के कोड को संशोधित किया। मैंने क्षेत्रीय संपत्ति को उनके उदाहरण से हटा दिया क्योंकि मुझे अपनी समस्या के लिए इसकी आवश्यकता नहीं है।

दो कॉलम हैं। पहला कॉलम राज्य है। दूसरा कॉलम स्टेट कैंडीडेट है। राज्य कॉलम एक राज्य सूची से जुड़ा हुआ है, और स्टेट कैंडीडेट कॉलम स्टेट कैंडीडेट्स सूची से जुड़ा हुआ है। मुख्य बिंदु यह है कि जब राज्य बदल जाता है तो स्टेट कैंडीडेट्स सूची को फिर से बनाया जाता है। इसलिए, प्रत्येक पंक्ति में राज्यकंडिडेट्स की एक अलग सूची हो सकती है (चयनित राज्य के आधार पर)।

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

ध्यान दें कि, जब राज्य बदल रहा है, यह StateCandidates सूची जब तक एक अलग पंक्ति का चयन किया जाता अपडेट नहीं करेंगे, जो एक अलग मुद्दा मैं लड़ूंगा। क्या कोई जानता है कि मैं प्रतिबद्ध कैसे कर सकता हूं?

जोनाथन को फिर से उनकी प्रेरणा के लिए धन्यवाद। मैं एक बेहतर समाधान की तलाश में रहूंगा।

+0

आप कहीं भी उसी सड़क पर जा रहे हैं जहां मैं था। लेकिन चूंकि आप जोर देते हैं, यहां कोड है: http://www.scottlogic.co.uk/blog/colin/tag/ieditableobject/ –

+2

@ जोनाथन: लिंक के लिए बहुत बहुत धन्यवाद। हालांकि, मैं इस नमूने के लिए यह काम नहीं कर सका, शायद क्योंकि मैं डेटाटेबल का उपयोग नहीं करता हूं। इसके साथ झुकाव करते समय, मुझे उस ब्लॉग में http://codefluff.blogspot.com/2010/05/commiting-bound-cell-changes.html पर इंगित करने में एक टिप्पणी मिली। यह समाधान बहुत अच्छा काम करता है। – newman

+0

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

2

आप शायद इसे विश्वसनीय रूप से नहीं कर सकते हैं। ग्रिड कॉम्बो बॉक्स का पुन: उपयोग कर सकता है या इसे यादृच्छिक रूप से बना/नष्ट कर सकता है।

मौका से मैं बस एक स्क्रीन पर काम करने के लिए होता हूं जो बस यही करता है। इन्हें देखते हुए ...

  • ग्रिड में प्रत्येक पंक्ति प्रकार के व्यापार की वस्तु से बंधी है।
  • प्रत्येक व्यापार एक राज्य संपत्ति है
  • प्रत्येक व्यापार एक TerritoryCanidates संपत्ति
  • राज्य संपत्ति बदलने TerritoryCanidates संपत्ति का कारण

बदलने के लिए यह मैं TerritoryCanidates को ItemsSource बाध्य करने की क्षमता देता है जाएगा संपत्ति। बदले में डेटाग्रिड सभी परिस्थितियों में सम्मान करेगा। जोनाथन के उदाहरण के लिए


<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

मैं उलझन में हूं ... क्या यह आपके लिए काम करता है? मैंने अभी कोशिश की और इसे काम नहीं कर सका। मैंने जो कोशिश की वह इस तरह है: मैंने आइटम्ससोर्स को बांधने के लिए एक नया संग्रह बनाया है। जब कोई अन्य संपत्ति बदल जाती है तो यह संग्रह फिर से बनाया जाएगा। मुझे combobox ड्रॉपडाउन में कुछ भी नहीं दिख रहा है। – newman

+0

अजीब, ऐसा लगता है कि अंतर्निहित कॉम्बो बॉक्स कॉलम मेरी अपेक्षा की तरह काम नहीं कर रहा है। मैंने अपने वास्तविक प्रोग्राम उपयोगों जैसे टेम्पलेट कॉलम का उपयोग करके अपना उदाहरण दोबारा किया। –

+1

पीएस मैं डेटा को संपादित करने के लिए आधिकारिक तौर पर डेटाग्रिड से नफरत करता हूं। मैं इसके बजाय सिर्फ एक आइटम नियंत्रण का उपयोग करने जा रहा हूँ। –

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