Adding elements through code in a grid - WP - c#

I'm trying to do something which is as simple as adding elements to a 6x7 grid through code behind. The grid is defined in xaml as following
<Grid x:Name="CalendarGrid" Grid.Row="1" Visibility="Collapsed">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
</Grid>
I have a function called InitializeCalendar which would populate the grid with buttons. Somehow I cant figure out how to specify row and column to which I want to add the button. How to I reference the row and column of CalendarGrid?
void InitializeCalendar()
{
for (int i = 0; i < 6; i++)
{
for (int j = 0; i < 7; j++)
{
butArray[i + 1, j + 1] = new Button();
//CalendarGrid. I cant find function to specify the row and button
}
}
}
I found that there is a property called ColumnProperty.
butArray[i + 1, j + 1].SetValue(Grid.ColumnProperty, 0);
But then there are so many Grids in my page. How do I reference the CalendarGrid? Any solutions?
Thanks,

You can use Grid.SetRow (msdn) and Grid.SetColumn (msdn) methods:
void InitializeCalendar()
{
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 7; j++)
{
butArray[i, j] = new Button();
butArray[i, j].Content = (i).ToString() + (j).ToString();
CalendarGrid.Children.Add(butArray[i, j]);
Grid.SetRow(butArray[i, j], i);
Grid.SetColumn(butArray[i, j], j);
}
}
}

You have to add the button to the CalendarGrid. Try the following way:
CalendarGrid.Children.Add(butArray[i + 1, j + 1]);
butArray[i + 1, j + 1].SetValue(Grid.ColumnProperty, columnNumber);
butArray[i + 1, j + 1].SetValue(Grid.RowProperty, rowNumber);

Related

WPF. How to dynamically add new pages to grid?

I am creating app in wpf that display some places in the world (descriptions, photos) and there are also opinions, that user can write. To display them I created new Grid, where user can add up to 5 opinions (if more the texts overlap). Because of this problem I wanted to dynamically add new pages to Grid, e.g. if user added 6th opinion, new grid page created and new button appers on the bottom of Grid with page number (navigation). But I have no clue how to write it.
Grid used to display opinions:
<Grid Grid.Column="2" Grid.ColumnSpan="3"
Grid.Row="0" Grid.RowSpan="3" x:Name="newGrid" Margin="0,50,0,0"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
</Grid>
Function used to add new opinions:
private void btnConfirm_Click(object sender, RoutedEventArgs e)
{
txtName.Visibility = Visibility.Hidden;
tbName.Visibility = Visibility.Hidden;
txtOpinion.Visibility = Visibility.Hidden;
tbOpinion.Visibility = Visibility.Hidden;
btnConfirm.Visibility = Visibility.Hidden;
var name = tbName.Text;
var opinion = tbOpinion.Text;
if(name != "" && opinion != "" && name != " " && opinion != " ")
{
TextBlock tb = new TextBlock();
tb.Text = name + ": " + opinion;
tb.HorizontalAlignment = HorizontalAlignment.Left;
tb.VerticalAlignment = VerticalAlignment.Bottom;
tb.FontSize = 30;
tb.Foreground = Brushes.White;
tb.Margin = new Thickness(50, 0, 0, 0);
tb.TextWrapping = TextWrapping.Wrap;
tb.TextAlignment = TextAlignment.Justify;
newGrid.Children.Add(tb);
Grid.SetRow(tb, klik);
Grid.SetColumnSpan(tb, 3);
klik++; //opinion counter and also number of row
}
else
{
MessageBox.Show("Fields cannot by empty!","Error",MessageBoxButton.OK,MessageBoxImage.Error);
}
I suppose variable klik must be used, because that variable is responsible for counting opinions. So it would be:
if(klik>5)
{
//add new grid page - but I have no clue how to do this
}
First off I want to preface this by saying there are many better ways to design your application (using MVVM design patterns, Styles, DataTemplates, etc.). Learning those skills will benefit you as a developer in the long run. Having said that, I'll answer this based on your request.
Because you are adding new rows that do not have a home yet on your Grid, you'll first need to add a new placeholder for the row by adding a new RowDefinition.
newGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
Then perform your code the same as you did before. So it should look something like this:
if(klik>5)
{
newGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
}
if(name != "" && opinion != "" && name != " " && opinion != " ")
{
TextBlock tb = new TextBlock();
tb.Text = name + ": " + opinion;
tb.HorizontalAlignment = HorizontalAlignment.Left;
// ... etc etc etc
}

WPF Drag Control during runtime

I been working with winforms, so my knowledge of WFP is non existent, this is something i am trying to test.
In code I am generating few buttons and placing them on Canvas. Than after clik on any button, i am moving that button around, and after second click button should stay at the position where mouse cursor was when clicked.
If mouse cursor go outside canvas then button will stop follow it.
My problem is, that button is moving, but only when mouse cursor is over that button or any other control, but it is not moving while mouse cursor is traveling over Canvas.
XAML
<Window x:Class="WpfTestDrag.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"
xmlns:local="clr-namespace:WpfTestDrag"
mc:Ignorable="d"
Title="MainWindow" Height="522" Width="909">
<Grid>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="130*"/>
<ColumnDefinition Width="33*"/>
<ColumnDefinition Width="120"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions >
<RowDefinition Height="40" />
<RowDefinition Height="*" />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Canvas Grid.Column="1" Grid.Row="1" x:Name="cnvTest" Width="auto" Height="auto" PreviewMouseMove="CnvTest_PreviewMouseMove"/>
<TextBlock x:Name="txbStatus" Grid.Column="1" Grid.Row="2" Grid.ColumnSpan="2"/>
</Grid>
</Window>
C#
public partial class MainWindow : Window
{
Button bts;
Boolean isUsed = false;
public MainWindow()
{
InitializeComponent();
CreateButtons();
}
private void CreateButtons()
{
var xPos = 10.0;
var yPos = 15.0;
var Rnd = new Random();
for (int i = 0; i < 3; i++)
{
var btn = new Button();
btn.Name = "btn" + i;
btn.Content = "Button - " + i;
btn.Tag = "Tag" + i;
btn.Width = 150;
btn.Height = 150;
btn.Click += Btn_Click;
Canvas.SetLeft(btn, xPos);
Canvas.SetTop(btn, yPos);
cnvTest.Children.Add(btn);
xPos = xPos + btn.Width + Rnd.Next(-15,40);
yPos = yPos + btn.Height + Rnd.Next(-15, 40);
}
}
private void Btn_Click(object sender, RoutedEventArgs e)
{
bts = sender as Button;
if (isUsed == false)
{
isUsed = true;
}
else
{
isUsed = false;
}
}
private void CnvTest_PreviewMouseMove(object sender, MouseEventArgs e)
{
Point p = Mouse.GetPosition(cnvTest);
if (isUsed == true)
{
Canvas.SetLeft(bts, p.X);
Canvas.SetTop(bts, p.Y);
txbStatus.Text = bts.Name.ToString() + " isUsed:" + isUsed.ToString() + " -> xPos:" + p.X.ToString() + " yPos:" + p.Y.ToString();
}
}
}
Should I use something else than Canvas for this?
You should set the Background property of the Canvas to Transparent (or any other Brush) for it to respond to the mouse events:
<Canvas Grid.Column="1" Grid.Row="1" x:Name="cnvTest" Width="auto" Height="auto" PreviewMouseMove="CnvTest_PreviewMouseMove"
Background="Transparent"/>

Exception in Main Window while SizeChanged event used

I have wpf solution, where I have created UserControl for trending. This UserControl is used in MainWindow.
The path of trend is painted on method showData() of current class ChartControl. But because I want to have actual picture of path related to main window size, I have add SizeChanged event where this showData() method is called.
My code for event here:
private void OnResize(object sender, SizeChangedEventArgs e)
{
this.showData();
}
Edit:
private List<ChartData> data = new List<ChartData>();
public void showData()
{
double maxVal = this.maxVal();
double minVal = this.minVal();
TimeSpan timeSpan = new TimeSpan();
timeSpan = this.maxTime() - this.minTime();
double stepSize = Area.ActualWidth / timeSpan.TotalSeconds;
setLabels();
Area.Children.Clear();
for (int i = 1; i < this.data.Count; i++)
{
Line lineHorizont = new Line();
lineHorizont.StrokeThickness = 2;
lineHorizont.Stroke = Brushes.Red;
lineHorizont.X1 = (this.data[i].X - this.minTime()).TotalSeconds * stepSize;
lineHorizont.Y1 = Math.Abs(((this.data[i - 1].Y - minVal) / (maxVal - minVal) * Area.ActualHeight) - Area.ActualHeight);
lineHorizont.X2 = lineHorizont.X1;
lineHorizont.Y2 = Math.Abs(((this.data[i].Y - minVal) / (maxVal - minVal) * Area.ActualHeight) - Area.ActualHeight);
Area.Children.Add(lineHorizont);
Line lineVertical = new Line();
lineVertical.StrokeThickness = 2;
lineVertical.Stroke = Brushes.Red;
lineVertical.X1 = (this.data[i - 1].X - this.minTime()).TotalSeconds * stepSize;
lineVertical.Y1 = Math.Abs(((this.data[i - 1].Y - minVal) / (maxVal - minVal) * Area.ActualHeight) - Area.ActualHeight);
lineVertical.X2 = (this.data[i].X - this.minTime()).TotalSeconds * stepSize;
lineVertical.Y2 = lineVertical.Y1;
Area.Children.Add(lineVertical);
}
//Draw cross coordinator
coordX1.StrokeThickness = 1;
coordX1.Stroke = Brushes.Black;
coordX1.X1 = 0;
coordX1.Y1 = Mouse.GetPosition(Area).Y;
coordX1.X2 = Area.ActualWidth;
coordX1.Y2 = coordX1.Y1;
Area.Children.Add(coordX1);
coordX2.StrokeThickness = 1;
coordX2.Stroke = Brushes.Black;
coordX2.X1 = Mouse.GetPosition(Area).X;
coordX2.Y1 = 0;
coordX2.X2 = coordX2.X1;
coordX2.Y2 = Area.ActualHeight;
Area.Children.Add(coordX2);
}
public double maxVal()
{
List<double> data = new List<double>();
for (int i = 0; i < this.data.Count; i++)
{
data.Add(this.data[i].Y);
}
return data.Max<double>();
}
edit2:
xaml content of Main Window
<Grid Margin="0">
<lib:ChartControl x:Name="Trend" Margin="0" Width="Auto" Height="Auto"/>
</Grid>
xaml content of ChartControl
<Grid Grid.Column="1" Margin="0" Grid.Row="1" Background="Black" Cursor="Cross" PreviewMouseMove="OnMouseMove">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Rectangle Fill="#FFF1F1F1" Grid.RowSpan="10"/>
<Rectangle Fill="#FFD4D4D4"/>
<Rectangle Fill="#FFD4D4D4" Grid.Row="2"/>
<Rectangle Fill="#FFD4D4D4" Grid.Row="4"/>
<Rectangle Fill="#FFD4D4D4" Grid.Row="6"/>
<Rectangle Fill="#FFD4D4D4" Grid.Row="8"/>
<Canvas x:Name="Area" Grid.RowSpan="10"/>
</Grid>
After start of program everything is working fine and according expectations, but I am getting Exception in View Designer in Visual studio, which is eliminating any design changes.
In the OnResize event handler you must test that the current instance is not in design mode.
System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)
if you have no data then return...then no more design exception !!
private void OnResize(object sender, SizeChangedEventArgs e) {
if(!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
this.showData();
}
List<double> data = new List<double>();
for (int i = 0; i < this.data.Count; i++)
{
data.Add(this.data[i].Y);
}
return data.Max<double>();
Please, please, please don't name your local variables the same as your outer-scope variables.
As for why this is failing, it's obvious:
this.data is empty when this is called, as such, when you try to perform data.Max<double>() you get an exception.
You're calling MaxVal() at the very beginning of ShowData() and as far as I can see, there's no real discernible place you're adding any ChartData to the data list.

Command is not working inside control of border in wpf

I am binding window DragMove event to the border control for moving the window. Propert is local:EnableDragHelper.EnableDrag="True" you can check design below.
<Border Grid.Row="0" BorderThickness="1" BorderBrush="Black" Background="#467EAF" Name="borderHeader" local:EnableDragHelper.EnableDrag="True">
<StackPanel Grid.Row="0" VerticalAlignment="Center">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" Content="{Binding InspectionHistoryModel.CurrentDateTime,Mode=TwoWay}" FontWeight="Bold" Foreground="White" FontSize="18" Margin="5,0,0,0"></Label>
<TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" Name="popupTaregetextblock" Margin="10,0,0,0" VerticalAlignment="Center">
<Hyperlink FontSize="20" Foreground="White" Command="{Binding ShowHideHeaderPopupCommand}" CommandParameter="onDuty"><TextBlock Text="{Binding InspectionHistoryModel.HeaderDutyText, Mode=TwoWay}" VerticalAlignment="Center" FontWeight="Bold" FontSize="18" Foreground="White"> </TextBlock></Hyperlink>
</TextBlock>
</Grid>
</StackPanel>
</Border>
Comamnd of Hyperlink (which put in inside of the border) is not working. How to possible this? Drag Code is
private static void UIElementOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
{
var uiElement = sender as UIElement;
if (uiElement != null)
{
if (mouseEventArgs.LeftButton == MouseButtonState.Pressed)
{
DependencyObject parent = uiElement;
int avoidInfiniteLoop = 0;
// Search up the visual tree to find the first parent window.
while ((parent is Window) == false)
{
parent = VisualTreeHelper.GetParent(parent);
avoidInfiniteLoop++;
if (avoidInfiniteLoop == 1000)
{
// Something is wrong - we could not find the parent window.
return;
}
}
var window = parent as Window;
if (window.WindowState == WindowState.Maximized)
{
var mouseX = mouseEventArgs.GetPosition(window).X;
var width = window.RestoreBounds.Width;
var x = mouseX - width / 2;
if (x < 0)
{
x = 0;
}
else
if (x + width > SystemParameters.PrimaryScreenWidth)
{
x = SystemParameters.PrimaryScreenWidth - width;
}
window.WindowState = WindowState.Normal;
window.Left = x;
window.Top = 0;
// window.Width = window.ActualWidth;
// window.Height = window.ActualHeight;
// window.Left = 0;
// window.Top = 0;
// window.WindowStartupLocation = WindowStartupLocation.Manual;
// window.WindowState = WindowState.Normal;
}
window.DragMove();
}
}
}

how to create listview to a grid programmatically

I have a grid with columns and rows define. By knowing x amount of items, I can add it to my xaml no problem. Unfortuantely I want to create the listview programatically because I want to populate them based on x amount of item I get when executing my SP. Here is my xaml. The label is there to assign a given content from the SP result too. Can someone show me how create this programatically?
<Grid Name="grdItems" Width="939" Grid.Row="1" HorizontalAlignment="Left" DataContext="{Binding}" Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="5"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="5"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="231"></ColumnDefinition>
<ColumnDefinition Width="5"></ColumnDefinition>
<ColumnDefinition Width="231"></ColumnDefinition>
<ColumnDefinition Width="5"></ColumnDefinition>
<ColumnDefinition Width="231"></ColumnDefinition>
<ColumnDefinition Width="5"></ColumnDefinition>
<ColumnDefinition Width="231"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Name="lblItem" Grid.Row="0" Grid.Column="0" Content="item label" />
<ListView Name="lstFirstItem" HorizontalAlignment="Left" VerticalAlignment="Top"
Height="auto" Margin="0,0,0,0" ItemsSource="" FontWeight="Regular"
Grid.Column="0" Grid.Row="1">
<ListView.View>
<GridView>
<GridView.ColumnHeaderContainerStyle>
<Style>
<Setter Property="FrameworkElement.Visibility" Value="Collapsed"/>
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridViewColumn Width="58" DisplayMemberBinding="{Binding ItemName}"></GridViewColumn>
<GridViewColumn Width="174.25" DisplayMemberBinding="{Binding ItemDescription}"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
we can add rows or columns dynamically from code behind.
Inorder to add rows:
GridLength rowheight = new GridLength(100); //your own value we can give *,Auto as well
RowDefinition rowDef = new RowDefinition {Height = rowheight };
mainGrid.RowDefinitions.Add(rowDef);
Inorder to add colomns:
GridLength columnwidth = new GridLength(100);
ColumnDefinition colDef = new ColumnDefinition { Width = columnwidth};
mainGrid.ColumnDefinitions.Add(colDef );
Inorder to add textblock at particular row,column
TextBlock textBlock = new TextBlock();
textBlock.Text = "Some Value";
Grid.SetRow(textBlock, rowNum);
Grid.SetColumn(textBlock, colNum);
mainGrid.Children.Add(textBlock);
Hope this answers your question
This work perfectly for me:
ListView Lv_Report = new ListView();
Lv_Report.Name = "Lv_Report";
Lv_Report.FontSize = 14;
Lv_Report.Height = 300;
Lv_Report.Width = 800;
Canvas.SetTop(Lv_Report, 10);
Canvas.SetLeft(Lv_Report, 30);
Cv_Scheduler.Children.Add(Lv_Report);
Lv_Report.Background = null;
LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush();
myLinearGradientBrush.StartPoint = new System.Windows.Point(0, 0);
myLinearGradientBrush.EndPoint = new System.Windows.Point(0, 1);
Color color = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#7FFFFFFF");
myLinearGradientBrush.GradientStops.Add(new GradientStop(color, 0.02));
color = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#BFBADF69");
myLinearGradientBrush.GradientStops.Add(new GradientStop(color, 0.19));
color = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#7FF9FCF2");
myLinearGradientBrush.GradientStops.Add(new GradientStop(color, 1));
color = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#BEB9DE67");
myLinearGradientBrush.GradientStops.Add(new GradientStop(color, 0.83));
Style style = new Style(typeof(GridViewColumnHeader));
style.Setters.Add(new Setter()
{
Property = GridViewColumnHeader.BackgroundProperty,
Value = myLinearGradientBrush
});
var Lvitems = new List<string>();
Lvitems.Add("WorkOrder");
Lvitems.Add("Module1");
GridView Gv = new GridView();
foreach (String item in Lvitems)
{
DataTemplate Dtemplate = new DataTemplate();
var markup =
"<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" xmlns:local=\"clr-namespace:SubMeteringElectric;assembly=SubMeteringElectric\">"
+ "<StackPanel>"
+ "<Label Content =\"{Binding Lv_RSH_" + item + "}\" Width = \"100\" Height = \"30\" HorizontalContentAlignment = \"Center\" FontSize = \"14\" />"
+ "</StackPanel>"
+ "</DataTemplate>";
byte[] byteArray = Encoding.UTF8.GetBytes(markup);
MemoryStream stream = new MemoryStream(byteArray);
Dtemplate = (DataTemplate)XamlReader.Load(stream);
GridViewColumn Gvc_item = new GridViewColumn();
Gvc_item.Header = item;
Gvc_item.Width = 150;
Gvc_item.CellTemplate = Dtemplate;
Gv.Columns.Add(Gvc_item);
}
Gv.ColumnHeaderContainerStyle = style;
Lv_Report.View = Gv;
}

Categories