I am building a desktop app using WPF, I need to be able to add views dynamically in a way that will look organized.
I have created an ObservableCollection
, and set itemsControl.ItemsSource
to be that collection.
I am able to add views, it just looks awful.
All I know about the amount of views that can be added, is that there can be a maximum of 16 views.
I thought about creating a dynamic grid, that will change according to the amount of views available, as in the following image
So I tried going with the dynamic-grid idea, I am creating a new grid each time a view is to be added/removed (sounds bad), and by the size of the views collection I know how to split the grid correctly.
Then I loop over all of the existing views in the collection, and place them on the grid by the right logic. I kind of made a real mess here, so if I'm totally in the wrong direction please just let me know.
Here is the code:
public partial class DynamicTargetView : UserControl
{
private ObservableCollection<TargetView> views = new ObservableCollection<TargetView>();
public Grid grid;
public DynamicTargetView()
{
InitializeComponent();
SettingsBar.onViewChange += addOrRemoveTargetsFromPanel;
}
public void addOrRemoveTargetsFromPanel(Object sender, WeiTargetGui.EventArgs.AddOrRemoveViewEventArgs e)
{
if (e.isShown)
{
addTargetToPanel(e.id);
}
else removeTargetFromPanel(e.id);
}
public void addTargetToPanel(string id)
{
views.Add(new TargetView(Int32.Parse(id)));
ArrangeGrid();
}
public void removeTargetFromPanel(string id)
{
foreach (TargetView v in views)
{
if (v.id == Int32.Parse(id))
views.Remove(v);
}
ArrangeGrid();
}
public void ArrangeGrid()
{
int NumOfViews = views.Count();
grid = new Grid();
grid.Children.Clear();
ColumnDefinition gridCol1;
ColumnDefinition gridCol2;
ColumnDefinition gridCol3;
ColumnDefinition gridCol4;
RowDefinition gridRow1;
RowDefinition gridRow2;
RowDefinition gridRow3;
RowDefinition gridRow4;
if (NumOfViews == 1)
{
addtoGrid(0, 0);
}
else if (NumOfViews == 2)
{
gridCol1 = new ColumnDefinition();
gridCol2 = new ColumnDefinition();
grid.ColumnDefinitions.Add(gridCol1);
grid.ColumnDefinitions.Add(gridCol2);
addtoGrid(2, 0);
}
else if (NumOfViews < 5)
{
gridCol1 = new ColumnDefinition();
gridCol2 = new ColumnDefinition();
gridRow1 = new RowDefinition();
gridRow2 = new RowDefinition();
grid.ColumnDefinitions.Add(gridCol1);
grid.ColumnDefinitions.Add(gridCol2);
grid.RowDefinitions.Add(gridRow1);
grid.RowDefinitions.Add(gridRow2);
addtoGrid(2, 2);
}
else if (NumOfViews < 10)
{
gridCol1 = new ColumnDefinition();
gridCol2 = new ColumnDefinition();
gridCol3 = new ColumnDefinition();
gridRow1 = new RowDefinition();
gridRow2 = new RowDefinition();
gridRow3 = new RowDefinition();
grid.ColumnDefinitions.Add(gridCol1);
grid.ColumnDefinitions.Add(gridCol2);
grid.ColumnDefinitions.Add(gridCol3);
grid.RowDefinitions.Add(gridRow1);
grid.RowDefinitions.Add(gridRow2);
grid.RowDefinitions.Add(gridRow3);
addtoGrid(3, 3);
}
else if (NumOfViews < 17)
{
gridCol1 = new ColumnDefinition();
gridCol2 = new ColumnDefinition();
gridCol3 = new ColumnDefinition();
gridCol4 = new ColumnDefinition();
gridRow1 = new RowDefinition();
gridRow2 = new RowDefinition();
gridRow3 = new RowDefinition();
gridRow4 = new RowDefinition();
grid.ColumnDefinitions.Add(gridCol1);
grid.ColumnDefinitions.Add(gridCol2);
grid.ColumnDefinitions.Add(gridCol3);
grid.ColumnDefinitions.Add(gridCol4);
grid.RowDefinitions.Add(gridRow1);
grid.RowDefinitions.Add(gridRow2);
grid.RowDefinitions.Add(gridRow3);
grid.RowDefinitions.Add(gridRow4);
addtoGrid(4, 4);
}
}
public void addtoGrid(int cols, int rows)
{
int row = 0;
int column = 0;
foreach (var view in views)
{
if (cols == 0 && rows == 0)
{
grid.Children.Add(view);
break;
}
if (cols == 2 && rows == 0)
{
Grid.SetColumn(view, column);
column++;
grid.Children.Add(view);
}
else
{
if (column != cols)
{
Grid.SetColumn(view, column);
Grid.SetRow(view, row);
grid.Children.Add(view);
}
if (column < cols)
column++;
else
{
column = 0;
row++;
}
}
}
this.Content = grid;
}
}
TargetView
is a user-control that represents a target with some data about that target.
So here are the problems with the code -
1) When adding more then one component to the views collection I get the following exception:
System.InvalidOperationException: 'Specified element is already the logical child of another element. Disconnect it first.'
I have added the grid.Children.Clear()
- with no help.
2) Final problem - code looks really bad, I just want to make it work so I could learn and implement it better next time.
Help will be appreciated, thanks a lot.