简体   繁体   中英

Binding of a DataGridTemplateColumn in DataGrid

I need to use a DataTemplate for my cells in a DataGrid. I'm creating the columns dynamially.

Itemsource of the DataGrid is a ObservableCollection:

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

The creation of the columns happes dynamically because the ListOfShifts property could contain 1 to x entrys

//Name-column
DataGridTextColumn NameColumn = new DataGridTextColumn() { Header = "Name" };
Binding NamebindingExpression = new Binding($"employee.Name") { Mode = BindingMode.OneWay };
NameColumn.Binding = NamebindingExpression;
grdRota.Columns.Add(NameColumn);

//columns for the shifts depending on ListOfShift count
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);
}

The template is easy as could be:

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

Would I use DataGridTextColumn instead of the DataGridTemplateColumn I could bind to the column and everything would be ok. But DataGridTemplateColumn has no Binding-Property.

So conclusion: Every column needs to be created dynamically and bound to the accordingly index of the ListOfShifts. Also it would be great if there would be a possibility to create the columns dynamically without working in code behind.

You need to create a specific template with a unique binding path for each column.

The key to solve this is to create the templates programmatically using the XamlReader.Parse method, eg:

const string Xaml = "<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">" +
    "<StackPanel Orientation=\"Horizontal\">" +
    "<TextBlock Text=\"{{Binding {0}}}\" Margin=\"10\"/>" +
    "</StackPanel>" +
    "</DataTemplate>";

for (int i = 0; i < MaxColumn; i++)
{
    string bindingPath = $"[{i}].Name";
    DataGridTemplateColumn column = new DataGridTemplateColumn()
    {
        Header = vm.StartDate.AddDays(i).ToShortDateString(),
        CellTemplate = XamlReader.Parse(string.Format(Xaml, bindingPath)) as DataTemplate
    };
    grdRota.Columns.Add(column);
}

I am afraid there is no support for doing this, ie replace the binding path in a template dynamically, in XAML.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM