DataGrid: dynamic DataTemplate for dynamic DataGridTemplateColumn

I want to show data in a datagrid where the data is a collection

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

where the number of candidates in the candidate list changes at run time.

The desired grid layout is as follows:

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

I would like to have DataTemplatefor each candidate, since I plan to change it at run time - the user can choose what information about the candidate is displayed in different columns (the candidate is just an example, I have a different object). This means that I also want to change the column templates at runtime, although this can be achieved by using one large template and folding its parts.

I know about two ways to achieve my goals (both are very similar):

  • AutoGeneratingColumn ""

DataTemplate XamlReader. , .

DataGrid DataGridTemplateColumn?

. datatemplate valueconverter

:. WPF Silverlight, DataGrid, DependencyProperty bindig . , .

+3
3

, 2 DataTemplates ContentControl:

<DataTemplate DataType="{x:Type viewModel:VariantA}"> <dataGrid...> </DataTemplate>
<DataTemplate DataType="{x:Type viewModel:VariantB}"> <dataGrid...> </DataTemplate>

<ContentControl Content="{Binding Path=GridModel}" />

, GridModel (, ) VariantA VariantB, DataTemplate.

VariantA B:

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

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

, .

+2

, "" , , :

  • xaml
  • multibind, + , "" 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>

:

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

MVVM-, -, xaml "" , - Hack .

, MS dataContexts, ...

,

EDIT: ( , , - ), , , - .

0

. " " silverlight.

Silverlight DataGrid .

, Colin Eberhardt, ... , DataGridTextColumn. , . " " - .., , DataGridTemplateColumn.

DataGridTemplateColumn , . , , xaml, , , n-.

, ( ), . " " (.. ) . , .. 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];
    }
}

. , Binding cell.DataContext, , .

Now I plan to have several templates (where everyone can bind to the same properties of the object of my cell) and switch between them when the page loads. Very neat solution.

0
source

Source: https://habr.com/ru/post/1784615/


All Articles