2013-10-22 6 views
0

내 프로그램에는 UserControl의 일부인 DataGrid이 있습니다. 이 격자의 셀 값을 변경하고 데이터 모델에 저장하도록하고 싶습니다. 이는 표준 데이터 바인딩 textBox이 wpf에서 작동하는 것과 유사합니다.DataGrid에서 값 저장 및 변경 - MVVM

DataGridTextBox로 구성됩니다. 셀의 값을 변경할 수는 있지만 페이지에서 벗어난 후에 사라집니다.

UserControl을 XAML :

<DataGrid ItemsSource="{Binding DataModel.Collection}" ... > 
       <DataGrid.Columns> 
        <DataGridTemplateColumn IsReadOnly="True"> 
         <DataGridTemplateColumn.CellTemplate> 
           <DataTemplate> 
            <TextBox Text="{Binding rowNum}" /> 
           </DataTemplate> 
         </DataGridTemplateColumn.CellTemplate> 
        </DataGridTemplateColumn> 
          ....... 
        </DataGrid> 

데이터 모델 :

public class Data_Model : PropertyChangedBase 
{ 
    private string one = "One"; 
    private string two = "Two"; 
    private string three = "Three"; 
    private string four = "Four"; 
    private string a = "A"; 
    private string b = "B"; 
    private string c = "C"; 
    private string d = "D"; 

    private ObservableCollection<Class> _Collection; 

    public Data_Model() 
    { 
     Collection = new ObservableCollection<Class>(); 
     Collection.Add(new Class() { rowNum = 0, input = one, output = a }); 
     Collection.Add(new Class() { rowNum = 1, input = two, output = b}); 
     Collection.Add(new Class() { rowNum = 2, input = three, output = c}); 
     Collection.Add(new Class() { rowNum = 3, input = four, output = d}); 

    } 

    public ObservableCollection<Class> Collection {...} 
} 

public class Class //Class for DataGrid values 
{ 
    public int rowNum { set; get; } 
    public string input { set; get; } 
    public string output { set; get; } 
} 

어떻게 보통 것 (텍스트로서의 string에 대한 속성을 작성하여 같은 이들 세포에서 사용자가 입력 한 값을 저장할 수 있습니다 textBox)?

+1

클래스 이름이 나를 혼란스럽게합니다. 'DataClass'가 모델 (또는 데이터 모델)이고'Data_Model'이 실제로 viewModel 인 것 같습니다 ... –

+0

왜 열을'TextBox'es로 템플릿 화합니까? 이것이 편집 목적이라면'DataGrid'는 이것을 out-of-the-box –

+0

으로 수정했습니다. '클래스'는 단지'DataGrid'에 저장된 값을위한 것이고'Data_Model'은 제 데이터 모델입니다. 또한 ... 'TextBox'가 아니라면, 컨트롤없이 동등한 작업을 수행하려면 어떻게해야합니까? –

답변

1

나는 당신이 당신의 data_model의 각 속성에 대한 NotifyPropertyChanged ("PROPERTYNAME")을 호출하고

를 따를 때 바인딩 Mode=twoway 또한

private int rowNum; 

public int RowNum 
{ 
    get { return rowNum; } 
    set 
    { 
     rowNum = value; 
     RaisePropertyChanged("RowNum"); 
    } 
} 

, 당신은 대신에 TemplateColumn의 DataGridTextColumn을 시도 할 수 있습니다 설정해야합니다 생각

<Window.Resources> 
    <XmlDataProvider x:Key="customerdata" Source="customers.xml" XPath="Data" /> 
</Window.Resources> 
<Grid> 
    <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Source={StaticResource customerdata}, XPath=Customer}"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Header="First Name" Binding="{Binding [email protected]}" FontFamily="Arial" FontStyle="Italic" /> 
      <DataGridTextColumn Header="Last Name" Binding="{Binding [email protected]}" FontFamily="Arial" FontWeight="Bold" /> 
     </DataGrid.Columns> 
    </DataGrid> 
</Grid> 
+0

WPF TextBox는 기본적으로 양방향으로 바인딩됩니다. –

+0

그것은 나를 위해 일한'DataGridTextColumn'에 대한 변화였습니다. 고마워요! –

1

WPF DataGrid는 셀을 편집 할 수있을 때 트랜잭션 범위를 사용합니다. 즉, DataGrid가 현재 'View'모델에서 듣고 있지 않은 'Commit'및 'Cancel'명령을 게시하고 있음을 의미합니다. 그렇기 때문에 변경 사항이 지속되지 않는 것입니다 (즉, 해당 인스턴스에서 '커밋'을 무시하고 있음).

'Commit'및 'Cancel'메시지를 캡처하려면 바인딩 된 클래스가 IEditableObject를 구현하고 필요한 로직을 코딩해야합니다. IEditableObject의 문서 위치 : http://msdn.microsoft.com/en-us/library/system.componentmodel.ieditableobject.aspx

때 '취소'그리드는 CELLS 해당 행의에서 수행하는 모든 커밋에 롤백을 수행하는 ROW에 이루어집니다. WPF 데이터 그리드의 이러한 측면은 많은 사람들이 시어 진 있으며, 그래서 좋은이있는 ... '잡았다'는 IEditableObject에 익숙하지 않은 경우

, 볼이 MSDN 문서 의 상태를 획득 한 것 설명 및 코드 샘플. DataGrid는 을 IEditableObject 인터페이스를 통해 트랜잭션 편집 기능에 구운 것입니다. 셀 편집을 시작하면 DataGrid는 셀 편집 모드와 행 편집 모드 인 에 들어갑니다. 이것이 의미하는 바는 이 셀을 취소/확정하고 행을 취소/확정 할 수 있다는 것입니다. 예를 들어, I 셀 0을 편집하고 탭을 눌러 다음 셀로 이동합니다. 탭을 누르면 셀 0이 커밋됩니다. 셀 1에서 타이핑을 시작하고 취소 작업을 실현하고 싶습니다. 작업을 취소하십시오. 나는 'Esc'를 눌러 셀 1을 되돌립니다. 이제 이 전체 작업을 취소하고 다시 'Esc'를 누르면 현재 셀 0이 원래 값으로 되돌려집니다.

출처 :

http://blogs.msdn.com/b/vinsibal/archive/2009/04/07/5-random-gotchas-with-the-wpf-datagrid.aspx는 그래서 '클래스'클래스 IEditableObject를 구현하고 당신이 당신이 찾고있는 동작을 얻을 시작합니다. 이것은 마치면 끝나야하는 모습입니다 ...

public class Class : INotifyPropertyChanged, IEditableObject 
{ 
    private int _rowNum; 
    public int RowNum 
    { 
     [DebuggerStepThrough] 
     get { return _rowNum; } 
     [DebuggerStepThrough] 
     set 
     { 
      if (value != _rowNum) 
      { 
       _rowNum = value; 
       OnPropertyChanged("RowNum"); 
      } 
     } 
    } 
    private string _input; 
    public string Input 
    { 
     [DebuggerStepThrough] 
     get { return _input; } 
     [DebuggerStepThrough] 
     set 
     { 
      if (value != _input) 
      { 
       _input = value; 
       OnPropertyChanged("Input"); 
      } 
     } 
    } 
    private string _output; 
    public string Output 
    { 
     [DebuggerStepThrough] 
     get { return _output; } 
     [DebuggerStepThrough] 
     set 
     { 
      if (value != _output) 
      { 
       _output = value; 
       OnPropertyChanged("Output"); 
      } 
     } 
    } 
    #region INotifyPropertyChanged Implementation 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected virtual void OnPropertyChanged(string name) 
    { 
     var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null); 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
    #endregion 
    #region IEditableObject Implementationi 
    public void BeginEdit() 
    { 
     // your implementation goes here 
    } 
    public void CancelEdit() 
    { 
     // your implementation goes here 
    } 
    public void EndEdit() 
    { 
     // your implementation goes here 
    } 
    #endregion 
}