3

데이터가DataGrid : 동적 DataGridTemplateColumn에 대한 동적 DataTemplate

public class Thing 
{ 
    public string Foo { get; set; } 
    public string Bar { get; set; } 
    public List<Candidate> Candidates { get; set; } 
} 

public class Candidate 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    ... 
} 

의 집합 인 데이터 격자에 데이터를 표시하려고합니다. 여기서 후보 목록의 후보 수는 런타임에 달라집니다.

원하는 그리드 레이아웃은 다음과 같습니다.

Foo | Bar | Candidate 1 | Candidate 2 | ... | Candidate N 

런타임 중에 변경을 계획하는 후보자마다 DataTemplate를 갖고 싶습니다. 사용자가 다른 컬럼에 표시되는 후보 정보를 선택할 수 있습니다. (후보자는 다만보기이다, 나는 다른 목표가있다). 즉, 하나의 큰 템플릿과 그 부분을 축소하여 실행할 수도 있지만 런타임에서 열 템플릿을 변경하려고합니다.

후보자
  • 두 경우 모두 수동으로 열을 추가하십시오. XamlReader을 사용하여 문자열에서 DataTemplate을로드해야합니다. 그 전에 원하는 후보로 바인딩을 변경하기 위해 문자열을 편집해야합니다.

    알 수없는 수의 DataGridTemplateColumn으로 DataGrid를 만드는 더 좋은 방법이 있습니까?

    이 질문은 dynamic datatemplate with valueconverter

    편집 : WPF와 Silverlight를 모두 지원해야하므로 DataGrid 구성 요소를 만들었습니다. 열. 컬렉션이 변경되면 열을 업데이트합니다.

    +0

    이 문제에 대한 해결책이나 해결책을 얻었습니까? –

    +0

    아닙니다. 내가 작성한 것처럼 커스텀'DataGrid' 컨트롤로 끝났습니다. 하지만 DataGrid가 제 작업에 상당히 무거 우므로'Grid'를 기반으로 한 사용자 정의 컨트롤을 개발할 생각입니다. –

    답변

    2

    예를 들어 우리는 2 DataTemplates과 ContentControl을을 만들 수 있습니다.

    VARIANTA & B 예제 구현 :이 도움이

    public class VariantA 
    { 
        public ObservableCollection<ViewModel1> DataList { get; set; } 
    } 
    
    public class VariantB 
    { 
        public ObservableCollection<ViewModel2> DataList { get; set; } 
    } 
    

    희망.

    +0

    불행히도 필자는 필자가 열 템플릿이 필요하다는 것을 알고 있습니다 - 전체 그리드 템플릿이 아닙니다. –

    0

    이 꽤 추한 남아 있기 때문에이하는 "더 나은"방법 인 경우 나도 몰라,하지만 난 PERSONNALY이 좋아했다 :

    • 이 소요 multibind를 사용하는 XAML
    • 에 템플릿을 현재의 바인딩 + 「올바른」dataContext를 얻기 위해서 (때문에) 컬럼에의 바인드.: 행 대신 셀)
    • 이 바인딩에서 변환기를 사용하여 원하는 속성의 값을 가져오고 검색 할 속성이 많은 경우 선택적으로 매개 변수를 추가하십시오.

    예 : (죄송합니다, 나는 당신의 프로젝트에 맞게 내 코드를 적용하지 않았다,하지만 당신은 거기에서 스스로 할 수 있어야합니다) 여기

    내 DataTemplate을 수 있습니다 :

    <DataTemplate x:Key="TreeCellTemplate"> 
        <Grid> 
         <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" Margin="5,0,0,0"> 
          <TextBlock.Text> 
           <MultiBinding Converter="{StaticResource RowColumnToCellConverter}" ConverterParameter="Text"> 
            <Binding /> 
            <Binding RelativeSource="{RelativeSource AncestorType=DataGridCell}" Path="Column" /> 
           </MultiBinding> 
          </TextBlock.Text> 
         </TextBlock> 
        </Grid> 
    </DataTemplate> 
    

    여기 내 변환기입니다 : 이것은 MVVM 모델을 저장

    public class RowColumnToCellConverter : MarkupExtension, IMultiValueConverter 
        { 
         public RowColumnToCellConverter() { } 
    
         public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
         { 
         XwpfRow row = values[0] as XwpfRow; 
         XwpfTreeColumn column = values[1] as XwpfTreeColumn; 
    
         if (row == null || column == null) return DependencyProperty.UnsetValue; 
    
         TreeCell treeCell = (TreeCell)row[column.DataGrid.Columns.IndexOf(column)]; 
         switch ((string)parameter) 
         { 
          case "Text": return treeCell.Text; 
          case "Expanded": return treeCell.Expanded; 
          case "ShowExpandSymbol": return treeCell.ShowExpandSymbol; 
          case "CurrentLevel": return new GridLength(treeCell.CurrentLevel * 14); 
    
          default: 
           throw new MissingMemberException("the property " + parameter.ToString() + " is not defined for the TreeCell object"); 
         } 
         } 
    
         public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
         { 
         throw new NotSupportedException(); 
         } 
    
         public override object ProvideValue(IServiceProvider serviceProvider) 
         { 
         return new RowColumnToCellConverter(); 
         } 
        } 
    

    , 나는 정말에 XAML 파서를 사용 싫어하는 때문에 일을이 방법을 선호 "동적 인"데이터 템플릿을 만들지 만 여전히 내 견해로는 못생긴 해킹입니다.

    나는

    희망이

    편집을하는 데 도움이 ... MS의 사람이 우리에게 대신 dataContexts가 즉석에서 템플릿 열을 생성 할 수 있도록 같은 행의 세포를 얻을 수있는 방법을 제공 텐데 : 귀하의 경우, 변환기가 실제로 훨씬 더 간단해야합니다 (실수하지 않으면 셀의 인스턴스를 직접 반환 할 수 있으며 매개 변수가 필요하지 않습니다). 그럼에도 불구하고 더 복잡한 버전을 남겨 두었습니다. 다른 누군가가 비슷한 문제가있다

    +0

    Silverlight는 '멀티 바인딩'을 지원하지 않으므로 흥미로운 아이디어입니다. –

    +0

    arf, 죄송합니다. 실버 라이트에 익숙하지 않아서 몰랐습니다. 나는 이것이 WPF에서 꽤 잘 작동한다는 것을 확인할 수 있지만, 오늘 다시 사용하고 추한 것이지만 메서드에 만족하기 시작합니다. – David

    0

    나는 simila를보고있다. r 문제가 있으며 소수의 유용한 패턴을 발견했을뿐입니다. 전체 '동적 열'문제는 실버 라이트에서 흥미로운 문제입니다.

    어제 나는 내 수색 중이 페이지 Silverlight DataGrid with Dynamic Columns을 트래비스 페티 존 (Travis Pettijohn)의 사이트에서 발견했습니다.

    이전에 나는 을 사용하는 한 환상적으로 잘 작동하는 Colin Eberhardt에 의해 윤곽이 잡힌 '인덱스 변환기'패턴을 사용하고있었습니다. 모든 것이 코드 뒤에 수행 될 수 있으며 런타임에 스타일을 적용하는 데 아무런 문제가 없었습니다. 그러나 내 요구 사항은 이제 일부 '셀 수준'서식을 적용하는 것입니다 - 셀 등의 배경을 변경합니다. 이는 DataGridTemplateColumn이 필요하다는 것을 의미합니다.

    나를 위해 DataGridTemplateColumn의 큰 문제는 코드에서 바인딩을 설정할 수 없다는 것입니다. 나는 xaml을 파싱하여 그것을 만들 수 있지만 다른 모든 사람들처럼 엄청난 해킹처럼 보이고 n 번째 유지 보수가 불가능한 것처럼 보입니다.

    Travis (위의 첫 번째 링크)에서 설명한 패턴은 완전히 다릅니다. '실행 시간'(즉, 페이지로드 시간)에 그리드에 필요한 열을 만듭니다. 즉, 컬렉션을 반복하고 적절한 머리글 등 각 항목에 대한 열을 추가합니다. RowLoaded 이벤트에 대한 처리기를 구현하고 각 행이로드 될 때 각 셀에 대해 DataContext를 설정하십시오. 적절한 속성/속성 부모의 인덱스.

    private void MyGrid_RowLoaded(object sender, EventArgs e) 
    { 
        var grid = sender as DataGrid; 
        var myItem = grid.SelectedItem as MyClass; 
        foreach (int i = 0; i < myItem.ColumnObjects.Count; i++) 
        { 
         var column = grid.Columns[i]; 
         var cell = column.GetCellContent(e.Row) 
         cell.DataContext = myItem.ColumnObjects[i]; 
        } 
    } 
    

    이로 인해 인덱스 변환기를 사용할 필요가 없어졌습니다. cell.DataContext을 설정할 때 Binding을 사용할 수도 있지만 템플릿의 경우 기본 객체에 직접 바인딩하는 것이 더 쉽습니다.

    이제는 여러 템플릿 (각 셀 객체의 동일한 속성에 바인딩 할 수 있음)을 가지고 페이지로드시 전환 할 계획을 세우고 있습니다.매우 깔끔한 솔루션.

    +0

    이'RowLoaded'는 정말 좋은 해결책처럼 보입니다. 동적으로 열을 추가하고 제거해야 할 때 솔루션으로 보지는 못합니다. 그렇다면 문자열에서 템플릿을로드하고 myItem.ColumnObjects [i] 바인딩을 실제 인덱스로 대체하는 것이 좋습니다. –

    +0

    @ LukasCenovsky 동적 열 코드를 게시하지 않았지만 링크에서 볼 수 있습니다. 앞에서 언급했듯이 그것은 쉬운 부분입니다.'foreach (columnsToAdd의 var 항목) {grid.Columns.Add (DataGridTemplateColumn() {Header = item.HeaderProperty};}) –

    +0

    @LukasCenovsky 원하는 'DataTemplate'을 추가하십시오 'Resources'로 사용하고 코드에서 참조 할 것입니다. 나중에 대답을 편집하려고합니다 ... –