How to use C# to setup UI with XAML Grid - c#

Context: Windows 8.1 windows store app codeing in C# and XAML. Using Visual Studio Express 2013.
Hi, I've been trying to code XAML app for windows store, but I just can't seem to linking the XAML control (Page, Grid, ContentPresenter, or whatever) to the c# code properly.
This has caused much frustration and I can't seem to find anything that answers this problem explicitly and directly.
So I'm asking for help with a very specific context:
I'm trying to build the xaml UI in c# to be executed when the app starts, but I can't seem to reference the control properly to GIVE my UI, or the line execution order is wrong, I just don't know.
I have a Page in my Main.xaml code:
<Page
x:Class="App4.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App4"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
>
<Grid x:Name="pgMain"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
>
</Grid>
I tried alternating x:Name with Name too...
Anyway, the C# code is this part, and here I am trying to set the Grid "pgMain" to the Grid object I create using my custom method.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace App4 {
public sealed partial class MainPage : Page
{
public MainPage() {
//this right here. is the line order wrong? Tried that.
//Is it impossible to do what I want before/after InitializeComponent?
//If so, then is there another way to achieve this???
pgMain = buildUIGrid();
this.InitializeComponent();
}
public Grid buildUIGrid() {
Grid g = new Grid();
int[] dimensions = { 3, 3 };//grid is 3 by 3
//setup grid definitions
for (int i = 0; i < dimensions[0]; i++)
g.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(0, GridUnitType.Star) });
for (int i = 0; i < dimensions[1]; i++)
g.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(0, GridUnitType.Star) });
//setup testing textboxes
for (int i = 0; i < dimensions[0]; i++) {
for (int j = 0; j < dimensions[1]; j++){
TextBlock tb = new TextBlock();
tb.Text = "test at col "+i+", row "+j;
Grid.SetColumn(tb, i);
Grid.SetRow(tb, j);
g.Children.Add(tb);
}
}
return g;
}
}
}
Alternatively, try this method for a single 200x200 grid with 1 textblock
public Grid buildUIGrid() {
Grid g = new Grid();
g.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(200, GridUnitType.Pixel) });
g.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(200, GridUnitType.Pixel) });
int i, j; i = 0; j = 0;
TextBlock tb = new TextBlock();
tb.Text = "test at col "+i+", row "+j;
Grid.SetColumn(tb, i);
Grid.SetRow(tb, j);
g.Children.Add(tb);
return g;
}
Please do not generalize, just answer to the given scenario.

Your problem is in the constructor:
public MainPage() {
//this right here. is the line order wrong? Tried that.
//Is it impossible to do what I want before/after InitializeComponent?
//If so, then is there another way to achieve this???
pgMain = buildUIGrid();
this.InitializeComponent();
}
The XAML file is parsed in the InitializeComponent method (look in your project folders for a file name MainPage.i.g.cs and you'll see that pgMain is set in that method). Before that pgMain is null.
Just move pgMain = buildUIGrid below InitializeComponent:
public MainPage() {
this.InitializeComponent();
buildUIGrid(pgMain);
}
Also update buildUIGrid:
public void buildUIGrid(Grid g) {
g.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(200, GridUnitType.Pixel) });
g.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(200, GridUnitType.Pixel) });
int i, j; i = 0; j = 0;
TextBlock tb = new TextBlock();
tb.Text = "test at col "+i+", row "+j;
Grid.SetColumn(tb, i);
Grid.SetRow(tb, j);
g.Children.Add(tb);
}

Related

Programmatically generated expanders with scrollable content resizing to window

I'm looking for a better way to make a programmatically generated window with the following behavior.
That is: List of expanders that can be initialized programmatically, each of which contains scrollable content larger than can be displayed in the window (in this case a datagrid). When an expander is expanded it's contents are limited to the available size of the window, while allowing all the rest of the expanders to be seen and manipulated. Additionally only one expander can be open at any given time.
This functionality seems that it could be useful in a lot of application menus, so I was surprised how difficult it was to implement. Is there a better way than what I did?
XAML (surprisingly simple):
<Window x:Class="ExpanderScrollExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="200">
<Grid>
<ItemsControl ItemsSource="{Binding Dict}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid Loaded="GridLoaded" ScrollViewer.CanContentScroll="False"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander Header ="{Binding Key, Mode=OneWay}" Expanded="Expander_Expanded" Collapsed="Expander_Collapsed">
<DataGrid ItemsSource="{Binding Path=Value}"/>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Code Behind (with most of the magic):
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace ExpanderScrollExample
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
private void GridLoaded(object sender, RoutedEventArgs e)
{
Grid grid = sender as Grid;
grid.LayoutUpdated += (s, e2) =>
{
var childCount = grid.Children.Count;
int rowsToAdd = (childCount - grid.RowDefinitions.Count);
for (int row = 0; row < rowsToAdd; row++)
{
RowDefinition rowDefinition = new RowDefinition();
rowDefinition.Height = new GridLength(0, GridUnitType.Auto);
grid.RowDefinitions.Add(rowDefinition);
}
for (int i = 0; i < childCount; i++)
{
var child = grid.Children[i] as FrameworkElement;
Grid.SetRow(child, i);
}
};
}
private void Expander_Expanded(object sender, RoutedEventArgs e)
{
ContentPresenter parentDataContext = VisualTreeHelper.GetParent(sender as DependencyObject) as ContentPresenter;
Grid grid = VisualTreeHelper.GetParent(parentDataContext as DependencyObject) as Grid;
grid.RowDefinitions[Grid.GetRow(parentDataContext)].Height = new GridLength(1, GridUnitType.Star);
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(grid); i++)
{
DependencyObject neighborDataContext = VisualTreeHelper.GetChild(grid, i);
for (int j = 0; j < VisualTreeHelper.GetChildrenCount(neighborDataContext); j++)
{
DependencyObject neighborExpander = VisualTreeHelper.GetChild(neighborDataContext, j);
if (neighborExpander is Expander && neighborExpander != sender)
{
((Expander)neighborExpander).IsExpanded = false;
this.Collapse(neighborExpander as Expander);
}
}
}
}
private void Expander_Collapsed(object sender, RoutedEventArgs e)
{
this.Collapse(sender as Expander);
}
private void Collapse(Expander expander)
{
ContentPresenter parent = VisualTreeHelper.GetParent(expander as DependencyObject) as ContentPresenter;
Grid grandparent = VisualTreeHelper.GetParent(parent as DependencyObject) as Grid;
grandparent.RowDefinitions[Grid.GetRow(parent)].Height = new GridLength(0, GridUnitType.Auto);
}
}
}
ViewModel (only for data generation)
using System.Collections.Generic;
namespace ExpanderScrollExample
{
class MainWindowViewModel
{
public Dictionary<string, List<MyClass>> Dict { get; }
public MainWindowViewModel()
{
Dict = new Dictionary<string, List<MyClass>>();
for ( int i = 0; i < 5; i++ )
{
string key = "Header " + i.ToString();
Dict[key] = new List<MyClass>();
for ( int j = 0; j < 100; j++)
{
Dict[key].Add(new MyClass(j, i*100 + j));
}
}
}
public class MyClass
{
public int Column1 {get; set;}
public int Column2 { get; set; }
public MyClass( int column1, int column2)
{
Column1 = column1;
Column2 = column2;
}
}
}
}
I also typically try to confirm with MVVM pattern, but was unable to do so in this case.
Generating items controls in grid is taken from here.
I also considered using style triggers to expand/collapse and set size as described in this answer but I couldn't think of a good way how to bind the dynamically generated rows with expanders.
Is there a better way to do this?
1. Only one Expander expanded at a given time
To make sure that only one Expander is expanded at a given time, you can create an Attached Behavior. I implemented one for reference.
ExpanderGroupBehavior (inspired by RadioButton)
<Expander wpf:ExpanderGroupBehavior.GroupName="ExpanderGroup01" />
This makes sure that only one Expander within the same group is expanded.
2. Expanded Expander fill available space
To achieve that, you may create your own Panel which handles that for you.
See How to get controls in WPF to fill available space? and https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/how-to-create-a-custom-panel-element

Create StackPanels dynamically and refer to any of them in code behind

In its simplest form...
I would like to create as many StackPanels as I want and then add Rectangles in them. Then to be able to change the Fill color of any one of the Rectangles when I click the Start Button for instance. All in Code Behind.
Any help would be appreciated.
For example, if our favorite beer wrote the framework I could do it like this:
XAML:
<Page
x:Class="Test2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Test2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Button Name="StartButton" Content="Start" Click="StartButton_Click" Height="30" Width="200" Margin="5"/>
</StackPanel>
<StackPanel Grid.Row="1" Name="myStackPanel" VerticalAlignment="Top"/>
</Grid>
</Page>
Code Behind:
namespace Test2
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
for (var i = 0; i < 5; i++) // The 5 here could be any number
{
myStackPanel.Children.Add(new StackPanel
{
Name = "myPanel" + i,
Orientation = Orientation.Horizontal
});
for (var j = 0; j < 10; j++) // The 10 here could be any number
{
("myPanel" + i).Children.Add(new Rectangle
{
Name = "myRectangle" + i + "-" + j,
Fill = new SolidColorBrush(Colors.Black),
Width = 20,
Height = 20,
Margin = new Thickness(1)
});
}
}
}
private void StartButton_Click(object sender, RoutedEventArgs e)
{
// E.G. To change the Fill color of Rectangle4 in StackPanel2
("myRectangle" + 2 + "-" + 4).Fill = new SolidColorBrush(Colors.Red);
}
}
}
Firstly, to add Rectangle shapes, we can create an instance of StackPanel and manipulate its Children elements:
for (var i = 0; i < 5; i++) // The 5 here could be any number
{
StackPanel sp = new StackPanel
{
Name = "myPanel" + i,
Orientation = Orientation.Horizontal
};
myStackPanel.Children.Add(sp);
for (var j = 0; j < 10; j++) // The 10 here could be any number
{
sp.Children.Add(new Rectangle
{
Name = "myRectangle" + i + "-" + j,
Fill = new SolidColorBrush(Colors.Black),
Width = 20,
Height = 20,
Margin = new Thickness(1)
});
}
}
Then to be able to change the Fill color of any one of the Rectangles when I click the Start Button for instance. All in Code Behind.
As tgpdyk mentioned, we need to use VisualTreeHelper to find the specified rectangle shape.
Helper class:
public static class FrameworkElementExtensions
{
public static T TraverseCTFindShape<T>(DependencyObject root, String name) where T : Windows.UI.Xaml.Shapes.Shape
{
T control = null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
{
var child = VisualTreeHelper.GetChild(root, i);
string childName = child.GetValue(FrameworkElement.NameProperty) as string;
control = child as T;
if (childName == name)
{
return control;
}
else
{
control = TraverseCTFindShape<T>(child, name);
if (control != null)
{
return control;
}
}
}
return control;
}
}
How to use it:
private void StartButton_Click(object sender, RoutedEventArgs e)
{
// E.G. To change the Fill color of Rectangle4 in StackPanel2
var rec = FrameworkElementExtensions.TraverseCTFindShape<Shape>(myStackPanel, "myRectangle" + 2 + "-" + 4);
rec.Fill = new SolidColorBrush(Colors.Red);
}
I've uploaded my sample to Github repository
That is not how you approach this in WPF, at all.
You usually do not concern yourself with any UI components but only the data. In this case you data bind an ItemsControl to a list of rows, each row containing a list of cells. In the ItemsControl definition you then set an ItemTemplate that contains another ItemsControl binding to the cells. In the nested ItemsControl you then can set an ItemTemplate where you bind the Background to a (notifying) property of your cells which you then just need to change in code.
Check out these overviews:
Data Binding Overview
Data Templating Overview
You may also want to look into the Model-View-ViewModel pattern to ensure a suitable application architecture.

Create a bunch of buttons programmatically in C# Win Phone 8 app

I have a problem in my C# file. I have to create 6 buttons programmatically on specific location. but my for loop doesn't work..
just one button shows and not all the buttons.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
//using System.Array;
namespace AimPass
{
public partial class main : PhoneApplicationPage
{
public main()
{
InitializeComponent();
}
private void newbutton(object sender, RoutedEventArgs e)
{
// How many buttons do you want ?
int NumOfButtons = 6;
// X Location of each created button in the panel
int loc = 20;
for (int i = 1; i <= NumOfButtons; i++)
{
Button btn = new Button();
{
btn.Name = "Btn-" + i.ToString();
btn.Size= new Size(50, 20);
btn.Tag = i;
btn.Content = "Browse-" + i.ToString();
btn.location = new Point(5, loc);
}
//Add Click event Handler for each created button
btn.Click += Buttons_Click;
loc += 20;
// Add the created btn to grid
grid.Children.Add(btn);
}
}
}
}
there are 2,3 errors comes..
using System.Windows.Controls.Buttons does not contain a definition of location and size...???
btn.Click += Buttons_Click; does not exist in current context..
And loop is not working..Just one buttons comes except 6 buttons..
I wanna add button on a specific location..So these errors comes to my requirement..
Thanx in advance for solving this..:)
Some time before i have right this ..so take a look you will get what you have read..
it is little bit lengthy but i think it will help you to understand what are you looking for..You can add Row and add button to it in a loop simultaneously but little more is always good..
this is your solution..for your case..but i think you going on wrong way..
private void newbutton()
{
// How many buttons do you want ?
int NumOfButtons = 6;
// X Location of each created button in the panel
StackPanel stkpanel = new StackPanel();
stkpanel.Orientation = Orientation.Horizontal;
int loc = 20;
for (int i = 1; i <= NumOfButtons; i++)
{
Button btn = new Button();
{
btn.Name = "Btn-" + i.ToString();
btn.Height = 20;
btn.Width = 50;
btn.Foreground = new SolidColorBrush(Colors.White);
btn.Content = "btnnum" + i.ToString();
btn.Tag = i;
btn.Content = "Browse-" + i.ToString();
btn.Margin = new Thickness(5 + loc, 5, 5, 5);
btn.VerticalAlignment = Windows.UI.Xaml.VerticalAlignment.Top;
}
//Add Click event Handler for each created button
btn.Click += btn_Click;
loc += 20;
// Add the created btn to grid
stkpanel.Children.Add(btn);
}
grid.Children.Add(stkpanel);
}
void btn_Click(object sender, RoutedEventArgs e)
{
// throw new NotImplementedException();
}
so..it is better you tried something in some sample projects..what i want to canvey to you..
And as the previous answer says button does not contain properties like loc etc that you want to set..for that Margin is thr..and For Size Height and Width are there..and important thing is..first you write Xaml for what you want to achieve and try to set the properties that you set in xaml during in run time in new project..it will definitely tell you how things work..
Grid grdbooltype = new Grid();
grdbooltype.Name = "Grid_" + keybooltype;
grdbooltype.Margin = new Thickness(0, 20, 20, 0);
grdbooltype.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
grdbooltype.RowDefinitions.Add(new RowDefinition());
TextBlock objtextblock = new TextBlock();
objtextblock.Text = "Select Image";
objtextblock.FontSize = 15;
grdbooltype.Children.Add(objtextblock);
Grid.SetRow(objtextblock, 0);
Grid grdtoggleswitch = new Grid();
grdtoggleswitch.Name = headername;
grdtoggleswitch.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
grdtoggleswitch.ColumnDefinitions.Add(new ColumnDefinition());
TextBlock txtblktoggleswitchleft = new TextBlock();
txtblktoggleswitchleft.FontSize = 15;
txtblktoggleswitchleft.VerticalAlignment = VerticalAlignment.Center;
txtblktoggleswitchleft.Text = headername;
Grid.SetColumn(txtblktoggleswitchleft, 0);
ToggleSwitch toggleswitch = new ToggleSwitch();
toggleswitch.Name = key;
toggleswitch.HorizontalAlignment = HorizontalAlignment.Right;
toggleswitch.Padding = new Thickness(0);
toggleswitch.IsOn = defaultvalue;
toggleswitch.Margin = new Thickness(0, 0, 0, 0);
toggleswitch.OnContent = "On";
toggleswitch.OffContent = "Off";
Grid.SetColumn(toggleswitch, 1);
grdtoggleswitch.Children.Add(txtblktoggleswitchleft);
grdtoggleswitch.Children.Add(toggleswitch);
Grid.SetRow(grdtoggleswitch, 1);
grdbooltype.Children.Add(grdtoggleswitch);
Well, first of all, buttons in Windows Phone don't have size nor location. Why would you think that they do? Instead of Size, you have two properties: Width and Height.
As for location, XAML doesn't work that way. Grid is a special kind of control that creates a layout and you define how many columns and rows you want in your grid. Then you place controls inside individual cells or you can make controls span cells.
Maybe you should learn a bit about XAML first, here is a good starting point: Layout for Windows Phone.
--
EDIT: Adding sample code for placing a button in first row and first column. Note that you have to define grid and column definition either in XAML or code.
grid.Children.Add(btn);
Grid.SetRow(btn, 0);
Grid.SetColumn(btn, 0);

Efficiently drawing a two-dimensional grid in WPF

Here's a Windows Forms program which draws a two-dimensional grid of squares that are randomly colored black or red:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Forms_Panel_Random_Squares
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Width = 350;
Height = 350;
var panel = new Panel() { Dock = DockStyle.Fill };
Controls.Add(panel);
var random = new Random();
panel.Paint += (sender, e) =>
{
e.Graphics.Clear(Color.Black);
for (int i = 0; i < 30; i++)
for (int j = 0; j < 30; j++)
{
if (random.Next(2) == 1)
e.Graphics.FillRectangle(
new SolidBrush(Color.Red),
i * 10,
j * 10,
10,
10);
}
};
}
}
}
The resulting program looks something like this:
Here's a (naive) translation to WPF using Rectangle objects for each square:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WPF_Canvas_Random_Squares
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Width = 350;
Height = 350;
var canvas = new Canvas();
Content = canvas;
Random random = new Random();
Rectangle[,] rectangles = new Rectangle[30, 30];
for (int i = 0; i < rectangles.GetLength(0); i++)
for (int j = 0; j < rectangles.GetLength(1); j++)
{
rectangles[i, j] =
new Rectangle()
{
Width = 10,
Height = 10,
Fill = random.Next(2) == 0 ? Brushes.Black : Brushes.Red,
RenderTransform = new TranslateTransform(i * 10, j * 10)
};
canvas.Children.Add(rectangles[i, j]);
}
}
}
}
The WPF version seems to be way more memory inefficient due to the fact that each cell in the world has the overhead of a Rectangle object.
Is there a way to write this program in a style that's as efficient as the Forms version? Or is there no way around creating all those Rectangle objects?
Here's a pure WPF solution. FrameworkElement is subclassed. This new subclass (DrawingVisualElement) exposes a DrawingVisual object which can be used to draw.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace DrawingVisualSample
{
public class DrawingVisualElement : FrameworkElement
{
private VisualCollection _children;
public DrawingVisual drawingVisual;
public DrawingVisualElement()
{
_children = new VisualCollection(this);
drawingVisual = new DrawingVisual();
_children.Add(drawingVisual);
}
protected override int VisualChildrenCount
{
get { return _children.Count; }
}
protected override Visual GetVisualChild(int index)
{
if (index < 0 || index >= _children.Count)
throw new ArgumentOutOfRangeException();
return _children[index];
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Width = 350;
Height = 350;
var stackPanel = new StackPanel();
Content = stackPanel;
var drawingVisualElement = new DrawingVisualElement();
stackPanel.Children.Add(drawingVisualElement);
var drawingContext = drawingVisualElement.drawingVisual.RenderOpen();
var random = new Random();
for (int i = 0; i < 30; i++)
for (int j = 0; j < 30; j++)
drawingContext.DrawRectangle(
random.Next(2) == 0 ? Brushes.Black : Brushes.Red,
(Pen)null,
new Rect(i * 10, j * 10, 10, 10));
drawingContext.Close();
}
}
}
It is possible to mix WPF and Forms. So instead of going the pure Forms route, the Panel can be embedded into the WPF Window via WindowsFormsHost. Here's a WPF program which demonstrates this:
using System;
using System.Windows;
using System.Windows.Forms.Integration;
using System.Drawing;
namespace WindowsFormsHost_Random_Squares
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Width = 350;
Height = 350;
Random random = new Random();
var windowsFormsHost = new WindowsFormsHost();
Content = windowsFormsHost;
var panel = new System.Windows.Forms.Panel()
{ Dock = System.Windows.Forms.DockStyle.Fill };
windowsFormsHost.Child = panel;
panel.Paint += (sender, e) =>
{
e.Graphics.Clear(System.Drawing.Color.Black);
for (int i = 0; i < 30; i++)
for (int j = 0; j < 30; j++)
{
if (random.Next(2) == 1)
e.Graphics.FillRectangle(
new SolidBrush(System.Drawing.Color.Red),
i * 10,
j * 10,
10,
10);
}
};
}
}
}

WPF: Dynamical Label addition in Grid

I have to create a table to display the KEY VALUE kind of thing.
I tried the below code but messed up with overlapping output. I believe, I need to create the Grid RowDefinitions and ColumnDefinitions but not able to achieve it. Please help me.
XAML:
<Window x:Class="GrideLabel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Name="LabelGrid"></Grid>
</Window>
Code behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
AddLabelDynamically();
}
private void AddLabelDynamically()
{
for (int i = 0; i < 3; i++)
{
Label nameLabel = new Label(); nameLabel.Content = "KEY :"+i.ToString();
Label dataLabel = new Label(); dataLabel.Content = "VALUE :"+i.ToString();
//I want to creatre the Seperate coloum and row to display KEY
// VALUE Pair distinctly
this.LabelGrid.Children.Add(nameLabel);
this.LabelGrid.Children.Add(dataLabel);
}
}
}
You have to define Row and Column definitions and assign Rows and Columns to child Controls. Following code does that:
private void AddLabelDynamically()
{
this.LabelGrid.ColumnDefinitions.Clear();
this.LabelGrid.RowDefinitions.Clear();
this.LabelGrid.ColumnDefinitions.Add(new ColumnDefinition());
this.LabelGrid.ColumnDefinitions.Add(new ColumnDefinition());
for (int i = 0; i < 3; i++)
{
this.LabelGrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
Label nameLabel = new Label(); nameLabel.Content = "KEY :" + i.ToString();
Label dataLabel = new Label(); dataLabel.Content = "VALUE :" + i.ToString();
Grid.SetRow(nameLabel, i);
Grid.SetRow(dataLabel, i);
Grid.SetColumn(nameLabel, 0);
Grid.SetColumn(dataLabel, 1);
//I want to creatre the Seperate coloum and row to display KEY
// VALUE Pair distinctly
this.LabelGrid.Children.Add(nameLabel);
this.LabelGrid.Children.Add(dataLabel);
}
}

Categories