Laden...

Binding bei DataGridTemplateColumn

Erstellt von Kriz vor 2 Jahren Letzter Beitrag vor 2 Jahren 592 Views
K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 2 Jahren
Binding bei DataGridTemplateColumn

Folgendes Problem:
Ich möchte in meinem DataGrid ein DataTemplate für meine Cells benutzen. Nur kann man daran (anscheinend) nicht dynamisch binden. Welche Möglichkeiten gibt es?

ItemSource des DataGrid ist eine ObservableCollection<EmployeeRota>:


class EmployeeRota : BaseViewModel
    {
        private Employee _employee;

        public Employee employee
        {
            get { return _employee; }
            set { _employee = value;
                OnPropertyChanged(nameof(employee));
            }
        }

        private ObservableCollection<Shift> _ListOfShifts;

        public ObservableCollection<Shift> ListOfShifts
        {
            get { return _ListOfShifts; }
            set { _ListOfShifts = value;
                OnPropertyChanged(nameof(ListOfShifts));
            }
        }
}

Das erstellen der Spalten erfolgt dynamisch, da ListOfShifts 1 - x Elemente enthalten kann:


            //Spalte für den Namen erstellen
            DataGridTextColumn NameColumn = new DataGridTextColumn() { Header = "Name" };
            Binding NamebindingExpression = new Binding($"employee.Name") { Mode = BindingMode.OneWay };
            NameColumn.Binding = NamebindingExpression;
            grdRota.Columns.Add(NameColumn);

            //Spalten für die Schichten abhängig der Anzahl der Einträge erstellen
            DataTemplate template = (DataTemplate)grdRota.FindResource("template");
            int MaxColumn = vm.ListOfEmployeeRotas.Max(x => x.ListOfShifts.Count);
            for (int i = 0; i < MaxColumn; i++)
            {                
                DataGridTemplateColumn column = new DataGridTemplateColumn() { Header = vm.StartDate.AddDays(i).ToShortDateString(), CellTemplate = template };
                grdRota.Columns.Add(column);
            }

Das Template ist recht einfach:


                <DataTemplate x:Key="template">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Name}" Margin="10"/>
                    </StackPanel>
                </DataTemplate>

Würde ich nun eine DataGridTextColumn statt der DataGridTemplateColumn nutzen, könnte ich mit


                Binding bindingExpression = new Binding($"ListOfShifts[{i}]") { Mode = BindingMode.OneWay };
                column.Binding = bindingExpression;

das gewünschte Ergebnis erhalten, aber DataGridTemplateColumn enthält keine Eigenschaft Binding. Und ich würde gern DataGridTemplateColumn nutzen.

Also zusammen gefasst:
Jede Zelle/Spalte muss dynamisch an den entsprechenden Index einer ObservableCollection gebunden werden.
Mit DataGridTextColumn kein Problem, es muss aber DataGridTemplateColumn benutzt werden.
Ein Bonus wäre auch, wenn ich die Spalten im XAML erstellen könnte und dafür nicht extra im Code-Behind rumwurschteln müsste.

Danke schonmal im Vorraus!
Kriz

2.078 Beiträge seit 2012
vor 2 Jahren

Also Du vermisst an der DataGridTemplateColumn eine Binding-Property?

Füge den Bindings im Template doch einfach die Property mit hinzu?
Ansonsten - wenn es sowieso in C#-Code aufgebaut wird - gibt der Column als Template-Inhalt ein ContenControl bindest die Content-Property wie Du es brauchst und dein "richtiges" Template bekommt die ContentTemplate-Property.

Also sowas, nur eben dynamisch:


<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ContentControl Content="{Binding ...}">
              <ContentControl.ContentTemplate>
                  <DataTemplate>
                      </TextBlock Text="{Binding Name}" Margin="10"/>
                  </DataTemplate>
              </ContentControl.ContentTemplate>
            </ContentControl>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Oder - wenn das Margin das Ziel ist - Du nutzt DataGridTextColumn.ElementStyle und definierst das Margin als Style.

K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 2 Jahren

Jein, mir fehlt die Möglichkeit dynamisch an die Propertys zu binden.

Ich kann bei einer DataGridTextColumn dynamisch an jeden Index meiner ObservableCollection binden, bei einer DataGridTemplateColumn leider nicht. Da kann ich nur die gesamte ObservableCollection dran binden, das bringt mir aber nichts.


for (int i = 0; i < MaxColumn; i++)
{
    DataGridTemplateColumn column = new DataGridTemplateColumn() { Header = vm.StartDate.AddDays(i).ToShortDateString(), CellTemplate = template };
    grdRota.Columns.Add(column);
}

Mit diesem Code ist der DataContext jeder Spalte die gesamte ObservableCollection, ich möchte aber pro Spalte den jeweiligen Index haben.

Ich habe mittlerweile auch DataTables ausprobiert, das fühlt sich aber sehr wie Flickschusterei an.

K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 2 Jahren

Th69, danke Dir, aber den Beitrag hatte ich schon mehrfach durchforstet.