Click here to Skip to main content
14,325,352 members

Silverlight / WPF

 
AnswerRe: How to call "customized" mahapps.metro modal-dialog window? Pin
Super Lloyd19-Nov-18 14:59
memberSuper Lloyd19-Nov-18 14:59 
QuestionCreating DataGrid IN Code Behind Pin
Kevin Marois19-Sep-18 13:00
professionalKevin Marois19-Sep-18 13:00 
AnswerRe: Creating DataGrid IN Code Behind Pin
Gerry Schmitz24-Sep-18 6:34
mveGerry Schmitz24-Sep-18 6:34 
QuestionCreating DataGrid IN Code Behind Pin
Kevin Marois19-Sep-18 13:00
professionalKevin Marois19-Sep-18 13:00 
QuestionListBox UserControl Binding Problelm Pin
Kevin Marois18-Sep-18 12:03
professionalKevin Marois18-Sep-18 12:03 
AnswerRe: ListBox UserControl Binding Problelm Pin
Richard Deeming19-Sep-18 8:14
mveRichard Deeming19-Sep-18 8:14 
GeneralRe: ListBox UserControl Binding Problelm Pin
Kevin Marois19-Sep-18 8:58
professionalKevin Marois19-Sep-18 8:58 
QuestionDynamically Created DataGrids Binding Problem Pin
Kevin Marois17-Sep-18 6:44
professionalKevin Marois17-Sep-18 6:44 
This is a bit long, but I'm really stuck and could use some help.

App Overview
I'm working on a construction management app. There are Projects with any number of houses. The houses are built in groups, or Jobs, where each Job can have any number of houses. For example, a project with 100 house might have 4 Jobs of 25 houses each.

Supplies are delivered to the jobs at specified intervals after the Project start date. These intervals are called Durations and the deliveries are called Drops.

So on the Project tab there is the Start Date and Max # Floors. If there are 1 and 2 story houses, then Max Floors is 2. On the Projects tab, when the Max Floors is set grids are created... one for each Story. See this picture. It shows the Settings dialog and the auto-generated DataGrids.

You can see that when # floors was set, the app read the data from the Settings and populated the list content. Each Story is a list row. The ListItem contains the BuildingType (Stories) and a single row data grid to hold the scheduled. values.

The columns in the grids are created from the Pack names. The numeric columns are used to specify the number of days past the Project Start Date when the deliveries arrive.

The Code
I followed this article.

View
<TabItem Header="Durations">

<pre>
<ListBox ItemsSource="{Binding ProjectDurations}">

    <ListBox.ItemTemplate>
        <DataTemplate>

            <StackPanel Orientation="Vertical"
                        Margin="5">

                <TextBlock Text="{Binding BuildingType}"
                            FontSize="14"
                            FontWeight="Bold"/>

                <DataGrid x:Name="projectPacksGrid"
                            AutoGenerateColumns="False" 
                            BorderBrush="SteelBlue"
                            BorderThickness="1"
                            ItemsSource="{Binding Path=Table2}"
                            mcb:DataGridColumnsBehavior.BindableColumns="{Binding Columns2}"/>

            </StackPanel>

        </DataTemplate>
    </ListBox.ItemTemplate>

</ListBox>




VM
/// <summary>
/// Auto-generates the listbox ItemSource, which is a list of data grids
/// </summary>
private void LoadDurationGrid()
{
    if (Project.MaxFloors > 0)
    {
        var durationData = AppCore.BizObject.GetProjectDurationPacks(Project.Id);

        ProjectDurations = new ObservableCollection<ProjectSchedulePackModel>();

        var buildingTypes = BuildingTypes.Where(x => x.NumberOfFloors <= Project.MaxFloors).ToList();

        foreach (var buildingType in buildingTypes)
        {
            List<string> data = new List<string>();

            ProjectSchedulePackModel entity = new ProjectSchedulePackModel
            {
                BuildingType = buildingType.Caption
            };

            var schedulePacks = _schedulePacks.Where(x => x.BuildingTypeId == buildingType.Id).OrderBy(x => x.Sequence).ToList();

            foreach (var schedulePack in schedulePacks)
            {
                var colName = "col" + schedulePack.Id;
                entity.Table2.Columns.Add(colName, typeof(string));
                Binding binding = new Binding(colName);

                DataGridTextColumn column = new DataGridTextColumn
                {
                    Header = schedulePack.Caption,
                    Binding = binding
                };

                entity.Columns2.Add(column);

                var day = durationData.Where(x => x.SchedulePackId == schedulePack.Id).Select(x => x.Days).FirstOrDefault();

                data.Add(day.ToString());
            }

            entity.Table2.Rows.Add(data.ToArray());
            ProjectDurations.Add(entity);
        }
    }
}

DataGridColumnsBehavior Class
public class DataGridColumnsBehavior
{
    public static readonly DependencyProperty BindableColumnsProperty =
        DependencyProperty.RegisterAttached("BindableColumns",
                                            typeof(ObservableCollection<DataGridColumn>),
                                            typeof(DataGridColumnsBehavior),
                                            new UIPropertyMetadata(null, BindableColumnsPropertyChanged));

<pre>
private static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
    DataGrid dataGrid = source as DataGrid;

    ObservableCollection<DataGridColumn> columns = e.NewValue as ObservableCollection<DataGridColumn>;
    dataGrid.Columns.Clear();

    if (columns == null)
    {
        return;
    }

    foreach (DataGridColumn column in columns)
    {
        dataGrid.Columns.Add(column);   // <============   ERROR HERE
    }

    columns.CollectionChanged += (sender, e2) =>
    {
        NotifyCollectionChangedEventArgs ne = e2 as NotifyCollectionChangedEventArgs;
        if (ne.Action == NotifyCollectionChangedAction.Reset)
        {
            dataGrid.Columns.Clear();
            if (ne.NewItems != null)
            {
                foreach (DataGridColumn column in ne.NewItems)
                {
                    dataGrid.Columns.Add(column);
                }
            }
        }
        else if (ne.Action == NotifyCollectionChangedAction.Add)
        {
            if (ne.NewItems != null)
            {
                foreach (DataGridColumn column in ne.NewItems)
                {
                    dataGrid.Columns.Add(column);
                }
            }
        }
        else if (ne.Action == NotifyCollectionChangedAction.Move)
        {
            dataGrid.Columns.Move(ne.OldStartingIndex, ne.NewStartingIndex);
        }
        else if (ne.Action == NotifyCollectionChangedAction.Remove)
        {
            if (ne.OldItems != null)
            {
                foreach (DataGridColumn column in ne.OldItems)
                {
                    dataGrid.Columns.Remove(column);
                }
            }
        }
        else if (ne.Action == NotifyCollectionChangedAction.Replace)
        {
            dataGrid.Columns[ne.NewStartingIndex] = ne.NewItems[0] as DataGridColumn;
        }
    };
}
public static void SetBindableColumns(DependencyObject element, ObservableCollection<DataGridColumn> value)
{
    element.SetValue(BindableColumnsProperty, value);
}
public static ObservableCollection<DataGridColumn> GetBindableColumns(DependencyObject element)

{
return (ObservableCollection<datagridcolumn>)element.GetValue(BindableColumnsProperty);
}
}


Problem
When I auto-generate, then switch off the Durations tab, then back, I get an error on the line above with the arrow. See this pic with the exception: https://1drv.ms/u/s!AjBmoYAYz_v2ghfz0GFmUMkyq3Hr

What I think is happening is the binding system is trying to rebind the datagrid, but that's a guess. I'm really stuck here and could use some help.

And, if anyone has a better way, I'm all ears.

Thanks
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.


modified 17-Sep-18 12:56pm.

AnswerRe: Dynamically Created DataGrids Binding Problem Pin
Gerry Schmitz17-Sep-18 15:00
mveGerry Schmitz17-Sep-18 15:00 
QuestionWPF MVVM textbox bind to SelectedItem issue Pin
miniboom6-Sep-18 3:32
memberminiboom6-Sep-18 3:32 
AnswerRe: WPF MVVM textbox bind to SelectedItem issue Pin
Mycroft Holmes6-Sep-18 12:47
memberMycroft Holmes6-Sep-18 12:47 
GeneralRe: WPF MVVM textbox bind to SelectedItem issue Pin
miniboom7-Sep-18 5:40
memberminiboom7-Sep-18 5:40 
GeneralRe: WPF MVVM textbox bind to SelectedItem issue Pin
Mycroft Holmes7-Sep-18 11:15
memberMycroft Holmes7-Sep-18 11:15 
QuestionPlease help me to figure out a purpose of this code. Pin
Pew_new4-Sep-18 10:00
memberPew_new4-Sep-18 10:00 
AnswerRe: Please help me to figure out a purpose of this code. Pin
Mycroft Holmes4-Sep-18 11:29
memberMycroft Holmes4-Sep-18 11:29 
GeneralRe: Please help me to figure out a purpose of this code. Pin
Pew_new4-Sep-18 18:31
memberPew_new4-Sep-18 18:31 
GeneralRe: Please help me to figure out a purpose of this code. Pin
Mycroft Holmes4-Sep-18 19:18
memberMycroft Holmes4-Sep-18 19:18 
GeneralRe: Please help me to figure out a purpose of this code. Pin
Pew_new4-Sep-18 22:25
memberPew_new4-Sep-18 22:25 
AnswerRe: Please help me to figure out a purpose of this code. Pin
Richard MacCutchan4-Sep-18 21:52
protectorRichard MacCutchan4-Sep-18 21:52 
GeneralRe: Please help me to figure out a purpose of this code. Pin
Pew_new4-Sep-18 22:30
memberPew_new4-Sep-18 22:30 
GeneralRe: Please help me to figure out a purpose of this code. Pin
Richard MacCutchan4-Sep-18 22:38
protectorRichard MacCutchan4-Sep-18 22:38 
GeneralRe: Please help me to figure out a purpose of this code. Pin
Pew_new4-Sep-18 22:45
memberPew_new4-Sep-18 22:45 
GeneralRe: Please help me to figure out a purpose of this code. Pin
Richard MacCutchan4-Sep-18 23:07
protectorRichard MacCutchan4-Sep-18 23:07 
GeneralRe: Please help me to figure out a purpose of this code. Pin
Pew_new4-Sep-18 23:12
memberPew_new4-Sep-18 23:12 
GeneralRe: Please help me to figure out a purpose of this code. Pin
Richard MacCutchan4-Sep-18 23:35
protectorRichard MacCutchan4-Sep-18 23:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.