2013-06-29 2 views
6

나중에 더 복잡한 데이터 열로 이동하기 위해 자체 체크 상자 열 (기본값을 바꾸기)을 만들고 있는데 다음 코드가 있습니다.WPF DataGrid - 새 사용자 지정 열 만들기

public class MyCheckBoxColumn : DataGridBoundColumn 
{ 
    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem) 
    { 
     var cb = new CheckBox(); 
     var bb = this.Binding as Binding; 
     var b = new Binding { Path = bb.Path, Source = cell.DataContext }; 
     cb.SetBinding(ToggleButton.IsCheckedProperty, b); 
     return cb; 
    } 

    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem) 
    { 
     var cb = new CheckBox(); 
     var bb = this.Binding as Binding; 
     var b = new Binding { Path = bb.Path, Source = ToggleButton.IsCheckedProperty }; 
     cb.SetBinding(ToggleButton.IsCheckedProperty, b); 
     return cb; 
    } 

    protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs) 
    { 
     var cb = editingElement as CheckBox; 
     return cb.IsChecked; 
    } 

    protected override void CancelCellEdit(FrameworkElement editingElement, object uneditedValue) 
    { 
     var cb = editingElement as CheckBox; 
     if (cb != null) cb.IsChecked = (bool)uneditedValue; 
    } 

    protected override bool CommitCellEdit(FrameworkElement editingElement) 
    { 
     var cb = editingElement as CheckBox; 
     BindingExpression binding = editingElement.GetBindingExpression(ToggleButton.IsCheckedProperty); 
     if (binding != null) binding.UpdateSource(); 
     return true;// base.CommitCellEdit(editingElement); 
    } 
} 
그리고 내 사용자 정의 데이터 그리드 :

이제
public class MyDataGrid : DataGrid 
{ 
    protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e) 
    { 
     try 
     { 
      var type = e.PropertyType; 
      if (type == typeof(bool)) 
      { 
       var col = new MyCheckBoxColumn(); 
       col.Binding = new Binding(e.PropertyName) {Mode = BindingMode.TwoWay}; 
       e.Column = col; 
      } 
      else 
      { 
       base.OnAutoGeneratingColumn(e); 
      } 
      var propDescr = e.PropertyDescriptor as System.ComponentModel.PropertyDescriptor; 
      e.Column.Header = propDescr.Description; 
     } 
     catch (Exception ex) 
     { 
      Utils.ReportException(ex); 
     } 
    } 
} 

, 모든 것이 두 가지를 제외하고 좋은 것 같다

  • 그것은 그 t을 보인다 그는 단지 MyCheckBoxColumn에있는 방법을 사용하여 GenerateElement()입니다. 다른 모든 방법은 사용되지 않습니다. 나는 그 (것)들 안에 중단 점을두고 결코 명중하지 않는다 ...
  • 나는 자료 소스로 ObservableCollection를 사용하고, 나머지 열은 그들이 변화 할 때 저에게 통지한다,이 것은이지 않는다.

이상한 점은 bool 값은 당신이/체크의 체크 박스를 체크 해제하면 변경하지만, 통지없이 CommitCellEdit()를 거치지 않고 도착한다는 것입니다. 여기에 무슨 일이 벌어지고 있는지 아는 사람이 있습니까?

편집 :

그것은 내가 다른 방법을 호출 할 수 있도록하는 TextBlock에서 GenerateElement() 내부에 돌아 오면 (알림 문제가 그래도 해결되지 않습니다) 것으로 보인다. 하지만이 기능이 CheckBoxes와 함께 작동하지 않는 이유는 무엇입니까? 기본 확인란 열은 어떻게 작동합니까 ???

답변

4

확인. 다음은 사용자 정의 CheckBox 열의 전체 코드입니다. DataGrid의 표시 (편집이 아닌) 요소로 체크 상자와 같은 컨트롤을 사용하려면 히트 테스트가 보이지 않도록해야합니다. 또는 TextBlock을 사용하여 체크 표시와 유사한 문자를 표시 할 수 있습니다.

public class MyCheckBoxColumn : DataGridBoundColumn 
{ 
    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem) 
    { 
     var cb = new CheckBox() { IsHitTestVisible = false, HorizontalAlignment = HorizontalAlignment.Center, HorizontalContentAlignment = HorizontalAlignment.Center }; 
     var bb = this.Binding as Binding; 
     var b = new Binding { Path = bb.Path, Source = dataItem, Mode = BindingMode.TwoWay }; 
     cb.SetBinding(ToggleButton.IsCheckedProperty, b); 
     return cb; 
//   var cb = new TextBlock() { TextAlignment = TextAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center }; 
//   var bb = this.Binding as Binding; 
//   var b = new Binding { Path = bb.Path, Source = dataItem, Mode = BindingMode.TwoWay, Converter = new MyBoolToMarkConverter() }; 
//   cb.SetBinding(TextBlock.TextProperty, b); 
//   return cb; 
    } 

    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem) 
    { 
     var cb = new CheckBox() { HorizontalAlignment = HorizontalAlignment.Center, HorizontalContentAlignment = HorizontalAlignment.Center }; 
     var bb = this.Binding as Binding; 
     var b = new Binding { Path = bb.Path, Source = dataItem, Mode = BindingMode.TwoWay }; 
     cb.SetBinding(ToggleButton.IsCheckedProperty, b); 
     return cb; 
    } 

    protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs) 
    { 
     var cb = editingElement as CheckBox; 
     if (cb != null) return cb.IsChecked; 
     return false; 
    } 

    protected override void CancelCellEdit(FrameworkElement editingElement, object uneditedValue) 
    { 
     var cb = editingElement as CheckBox; 
     if (cb != null) cb.IsChecked = (bool)uneditedValue; 
    } 

    protected override bool CommitCellEdit(FrameworkElement editingElement) 
    { 
     // The following 2 lines seem to help when sometimes the commit doesn't happen (for unknown to me reasons). 
     //var cb = editingElement as CheckBox; 
     //cb.IsChecked = cb.IsChecked; 
     BindingExpression binding = editingElement.GetBindingExpression(ToggleButton.IsCheckedProperty); 
     if (binding != null) binding.UpdateSource(); 
     return true;// base.CommitCellEdit(editingElement); 
    } 
} 
//-------------------------------------------------------------------------------------------- 
public class MyBoolToMarkConverter : IValueConverter 
{ 
    const string cTick = "■"; 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value.GetType() != typeof(bool)) return ""; 
     bool val = (bool)value; 
     return val ? cTick : ""; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value.GetType() != typeof(string)) return false; 
     string val = (string)value; 
     return val == cTick; 
    } 
} 
//-------------------------------------------------------------------------------------------- 
+0

아무도 내 질문에 대답하지 않는 이유를 모르겠습니다. WPF가 M $에 의해 버려지기로되어 있고 더 이상 신경 쓰지 않기 때문입니까? 당신이 그 답을 모른다는 것입니까? 어쨌든, WinForms, 그리고 더 많은 것들이 버려진 기술이되어 버렸지 만 오늘날에도 여전히 사용 중입니다. M $은 개발자가 휴대 전화 장난감을 홍보하기를 원합니다. – NoOne

+2

WPF가 버려진다고는 말할 수 없지만, 많은 사람들이 컨트롤 작성에이 문제를 깊이 파고 들지는 않을 것으로 기대합니다. –