I am trying to create a WPF windows application where it has to show all the Racks or shelves of Warehouse like below
So far this is what I have tried
My Xaml looks like
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="950" Width="1225" BorderBrush="DodgerBlue" BorderThickness="3">
<Grid>
<Canvas Height="900" Width="1200" Name="front_canvas" Grid.Row="0" Grid.Column="0" Margin="1,24,10,790" >
<Canvas.RenderTransform>
<ScaleTransform ScaleX="1" ScaleY="1" />
</Canvas.RenderTransform>
</Canvas>
</Grid>
</Window>
In a Method I have following
For i As Integer = 1 To front_canvas.Width - 1 Step 100
Dim rect As New Rectangle()
rect.StrokeThickness = 1
rect.Stroke = System.Windows.Media.Brushes.Black
rect.Width = 50
rect.Height = 50
rect.Name = "box" + i.ToString()
'If Not i / 2 = 0 Then
Canvas.SetLeft(rect, i)
Canvas.SetFlowDirection(rect, Windows.FlowDirection.LeftToRight)
'Canvas.SetTop(rect, Top)
'_top += rect.Height
If front_canvas.Children.Count > 0 Then
Dim lastChildIndex = front_canvas.Children.Count - 1
Dim lastChild = TryCast(front_canvas.Children(lastChildIndex), FrameworkElement)
If lastChild IsNot Nothing Then
_top = Canvas.GetTop(lastChild) + lastChild.Height + 1
End If
End If
Canvas.SetTop(rect, _top)
front_canvas.Children.Add(rect)
' End If
_rectangles.Add(rect)
Next
And the result I get here is like below
I would appreciate if someone can help me
Here try this:
XAML
<Window x:Class="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:WpfApplication7"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Canvas Name="cvsWarehouse"></Canvas>
</ScrollViewer>
Code Behind:
Imports System.Text
Class MainWindow
Private Const dRACKSIZE As Double = 57
Private Const dRACKSPACING As Double = 2
Private Const dAISLESPACING As Double = 40
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
CreateAisles()
End Sub
Private Sub CreateAisles()
cvsWarehouse.Width = 10 + (11 * dRACKSIZE) + (6 * dRACKSPACING) + (4 * dAISLESPACING)
cvsWarehouse.Height = 10 + (19 * dRACKSIZE) + (18 * dRACKSPACING)
Dim dStartX As Double = 10
CreateAisle(dStartX, 10, 19, 2, 1)
dStartX += dAISLESPACING
CreateAisle(dStartX, 10, 19, 2, 2)
dStartX += dAISLESPACING
CreateAisle(dStartX, 10, 19, 2, 3)
dStartX += dAISLESPACING
CreateAisle(dStartX, 10, 19, 2, 4)
dStartX += dAISLESPACING
CreateAisle(dStartX, 10, 19, 3, 5)
End Sub
Private Sub CreateAisle(ByRef dStartX As Double, dStarty As Double, iRowCount As Integer, iColCount As Integer, iAisleNumber As Integer)
Dim iColUpper = iColCount - 1
Dim iRowUpper = iRowCount - 1
For iCol As Integer = 0 To iColUpper
Dim dYOffset As Double = dStarty
For iRow As Integer = 0 To iRowUpper
Dim bdr As Border = GetNewBorder()
bdr.Child = GetNewTextBlock(iAisleNumber, iCol + 1, iRow + 1)
Canvas.SetTop(bdr, dYOffset)
Canvas.SetLeft(bdr, dStartX)
cvsWarehouse.Children.Add(bdr)
dYOffset += dRACKSIZE + dRACKSPACING
Next
dStartX += dRACKSIZE + dRACKSPACING
Next
dStartX -= dRACKSPACING
End Sub
Private Function GetNewBorder() As Border
Dim bdr As New Border
bdr.Width = dRACKSIZE
bdr.Height = dRACKSIZE
bdr.BorderBrush = Brushes.Red
bdr.BorderThickness = New Thickness(1)
bdr.CornerRadius = New CornerRadius(2)
Return bdr
End Function
Private Function GetNewTextBlock(iAisle As Integer, iCol As Integer, iRow As Integer) As TextBlock
Dim txtBlock As New TextBlock()
txtBlock.HorizontalAlignment = HorizontalAlignment.Center
txtBlock.VerticalAlignment = VerticalAlignment.Center
Dim sb As New StringBuilder()
sb.Append("A").Append(iAisle.ToString()).Append(":C").Append(iCol.ToString()).Append(":R").Append(iRow.ToString())
txtBlock.Text = sb.ToString()
Return txtBlock
End Function
End Class
if you want to use buttons instead of borders that have event handlers attached:
Private Sub CreateAisle(ByRef dStartX As Double, dStarty As Double, iRowCount As Integer, iColCount As Integer, iAisleNumber As Integer)
Dim iColUpper = iColCount - 1
Dim iRowUpper = iRowCount - 1
For iCol As Integer = 0 To iColUpper
Dim dYOffset As Double = dStarty
For iRow As Integer = 0 To iRowUpper
Dim btn As Button = GetNewButton()
btn.Content = GetNewTextBlock(iAisleNumber, iCol + 1, iRow + 1)
Canvas.SetTop(btn, dYOffset)
Canvas.SetLeft(btn, dStartX)
cvsWarehouse.Children.Add(btn)
dYOffset += dRACKSIZE + dRACKSPACING
Next
dStartX += dRACKSIZE + dRACKSPACING
Next
dStartX -= dRACKSPACING
End Sub
Private Function GetNewButton() As Button
Dim btn As New Button
btn.Width = dRACKSIZE
btn.Height = dRACKSIZE
btn.BorderBrush = Brushes.Red
btn.BorderThickness = New Thickness(1)
btn.AddHandler(Button.ClickEvent, New RoutedEventHandler(AddressOf Button_Click))
Return btn
End Function
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim buttonClicked As Button = DirectCast(sender, Button)
Dim text As String = DirectCast(buttonClicked.Content, TextBlock).Text
MessageBox.Show("Button " & text & " Clicked")
End Sub
To the questions below in answer 1, Here is what I did. Most of the code is from SO but it is not actually doing the styles like width and height. Print Preview is done in the following way. I had a Print preview button in tool bar of XAML mainwindow and in code behind I had below code `
Friend Sub DoPreview(title As String)
Dim fileName As String = System.IO.Path.GetRandomFileName()
' Dim visual As FlowDocumentScrollViewer = DirectCast(Me.FindName("cvsWarehouse"), FlowDocumentScrollViewer)
Dim visual As Canvas = DirectCast(cvsWarehouse, Canvas)
visual.Width = 1500
visual.Height = 900
Try
' write the XPS document
Using doc As New XpsDocument(fileName, FileAccess.ReadWrite)
Dim writer As XpsDocumentWriter = XpsDocument.CreateXpsDocumentWriter(doc)
writer.Write(visual)
End Using
' Read the XPS document into a dynamically generated
' preview Window
Using doc As New XpsDocument(fileName, FileAccess.Read)
Dim fds As FixedDocumentSequence = doc.GetFixedDocumentSequence()
Dim s As String = _previewWindowXaml
s = s.Replace("##TITLE", title.Replace("'", "'"))
Using reader = New System.Xml.XmlTextReader(New StringReader(s))
Dim preview As New Window
preview.Width = 1500
preview.Height = 900
preview.HorizontalAlignment = Windows.HorizontalAlignment.Stretch
preview.VerticalAlignment = Windows.VerticalAlignment.Stretch
preview = TryCast(System.Windows.Markup.XamlReader.Load(reader), Window)
Dim dv1 As DocumentViewer = TryCast(LogicalTreeHelper.FindLogicalNode(preview, "dv1"), DocumentViewer)
dv1.Width = 1500
dv1.Height = 900
dv1.IsHitTestVisible = True
dv1.VerticalAlignment = Windows.VerticalAlignment.Stretch
dv1.HorizontalAlignment = Windows.HorizontalAlignment.Stretch
dv1.ApplyTemplate()
dv1.Document = TryCast(fds, IDocumentPaginatorSource)
preview.ShowDialog()
End Using
End Using
Finally
If File.Exists(fileName) Then
Try
File.Delete(fileName)
Catch
End Try
End If
End Try
End Sub`
And the my preview is like below
Print Preview Image
Neither I can do scroll bar nor the entire canvas which is wider is fit to the preview window.
My actual Window with canvas is way wider like below
Actual canvas window
Could someone please correct the bug here?
Related
This is my first question ever, so please spare me if I did something wrong.
I have a small survey form that automatically draw questions and answers from a SQL server table, and create a question label (Label_Questionnaire(i)), a panel to nest all radiobuttons for the answer of each question (Panel_Response(i)), and 3 radiobuttons(yes, no, n/a), named RadioButton_Answers(i)_1 . All questions and answers are inside a big panel (Panel_Survey) to allow user to scroll up and down (around 50 questions).
When I run the program, I can only see questions but none of the radiobuttons are showing. What I did try are:
Use .BringToFront to bring the Panel_Response and all radiobuttons to front.
Change .Parent to Controls.Add . Instead of using .Parent, I use Panel_Survey.Controls.Add(Panel_Response) and Panel_Response.Controls.Add(RadioButton_Answers_1)
Force Panel_Response.Visible = True and all radiobuttons visible = true
(I know it might sound stupid, but I'm out of trick)
How do I make those radiobuttons show up? If not, are there any better designs for this kind of survey form? Thank you for any advice, in advance!
Below is my code:
Protected Overrides Sub OnLoad(e As EventArgs)
Dim PanelCount As Integer
Dim QuestionName As String
Dim Response1 As String
Dim Response2 As String
Dim Response3 As String
Dim InitialX As Integer = Panel_Survey.Left
Dim InitialY As Integer = Panel_Survey.Top
Dim SizeX As Integer = 1000
Dim SizeY As Integer = 25
'Load the survey
Try
'Get a list of questions and answers into array of list
Dim ListofQuestionandAnswers As New List(Of List(Of String))
Dim conn As New SqlClient.SqlConnection
conn.ConnectionString = ConnectionString
Dim CommandString As String = "SELECT [QuestionID], [QuestionName] ,[Response1],[Response2],[Response3] FROM [Question_List] ORDER BY [QuestionID]"
Dim Command As New SqlClient.SqlCommand
Command.CommandText = CommandString
Command.Connection = conn
Dim dr As SqlClient.SqlDataReader
conn.Open()
dr = Command.ExecuteReader
While dr.Read
Dim ls As New List(Of String)
ls.Add(dr.GetValue(0).ToString)
ls.Add(dr.GetValue(1).ToString)
ls.Add(dr.GetValue(2).ToString)
ls.Add(dr.GetValue(3).ToString)
ls.Add(dr.GetValue(4).ToString)
ListofQuestionandAnswers.Add(ls)
End While
conn.Close()
PanelCount = ListofQuestionandAnswers.Count
For i = 0 To ListofQuestionandAnswers.Count - 1
QuestionName = ListofQuestionandAnswers(i)(1)
Response1 = ListofQuestionandAnswers(i)(2)
Response2 = ListofQuestionandAnswers(i)(3)
Response3 = ListofQuestionandAnswers(i)(4)
Dim Label_Questionnaire As New Label
Dim Panel_Response As New Panel
Dim RadioButton_Answers_1 As New RadioButton
Dim RadioButton_Answers_2 As New RadioButton
Dim RadioButton_Answers_3 As New RadioButton
'Condition the label
With Label_Questionnaire
.Parent = Panel_Survey
.Name = "Label_Questionnaire" + i.ToString
.Font = New Font("Calibri", 11, FontStyle.Regular)
.Text = QuestionName
.ForeColor = Color.Black
.Location = New Point(InitialX, InitialY)
.AutoSize = True
End With
'Condition the panel
With Panel_Response
'Panel_Survey.Controls.Add(Panel_Response)
.Parent = Panel_Survey
.Name = "Panel_Questionnaire" + i.ToString
.Location = New Point(InitialX + 880, InitialY)
.Width = 250
.Height = 25
.BringToFront()
End With
Dim j As Integer
Dim h As Integer
j = Panel_Response.Left
h = Panel_Response.Top
'Condition the radiobuttons for answers
With RadioButton_Answers_1
.Parent = Panel_Response
.Name = "RadioButton_Answers" + i.ToString + "_1"
.Font = New Font("Calibri", 11, FontStyle.Regular)
.Text = Response1
.ForeColor = Color.Black
.Location = New Point(j, h)
.AutoSize = True
h += RadioButton_Answers_1.Height
End With
With RadioButton_Answers_2
.Parent = Panel_Response
.Name = "RadioButton_Answers" + i.ToString + "_2"
.Font = New Font("Calibri", 11, FontStyle.Regular)
.Text = Response2
.ForeColor = Color.Black
.Location = New Point(RadioButton_Answers_1.Right, h)
.AutoSize = True
End With
With RadioButton_Answers_3
.Parent = Panel_Response
.Name = "RadioButton_Answers" + i.ToString + "_3"
.Font = New Font("Calibri", 11, FontStyle.Regular)
.Text = Response3
.ForeColor = Color.Black
.Location = New Point(RadioButton_Answers_2.Right, h)
.AutoSize = True
End With
InitialY = InitialY + SizeY + 10
Next
Catch ex As Exception
MessageBox.Show(String.Format("Error: {0}", ex.Message), "Error while creating questions and answers", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Few basic problems here:
You seem to assume that when a control is placed inside a panel, it must be placed at a location relative to the form. It doesn't; it places relative to the Panel which has its own coordinate system starting at 0,0 in the top left of the panel - you initialize j and h (for locations of the radio buttons) to the Left and Top of the panel they're in, but they should be inited to 0,0 if you want the radiobuttons to start at the top left of the panel. If the Panel is placed at 300,300 on a form, and you place a radiobutton inside the panel also at 300,300 (because you copied its left and top) then the radio button will look like it's at 600,600 on the form because its at 300,300 inside a panel that is at 300,300
You only make your panel 250 wide - it's barely wide enough to show a single radio button
You increment h once, by an amount that means the next radiobutton disappears off the bottom of the panel (which is 25 pixels high)
Here:
With Panel_Response
'Panel_Survey.Controls.Add(Panel_Response)
.Parent = Panel_Survey
.Name = "Panel_Questionnaire" + i.ToString
.Location = New Point(InitialX + 880, InitialY)
.Width = 2500
.Height = 25
.BringToFront()
.BackColor = Color.Red
End With
Dim j As Integer
Dim h As Integer
j = 0
h = 0
Paste that over your app code and run it again. I made the panel BackColor red so you can more easily see where the panel is
I guess you need to decide how you want your UI to look. If the radiobuttons are laid out vertically, don't increment X when you add them to the panel (by setting the parent property). Make the panel tall enough to accommodate them (25 px not enough)
Use a FlowLayoutPaanel or TableLayoutPanel instead
In an application I'm developing, the user can select a number of items (max. 6) in a datagrid. These items should then be printed in a matrix style on pre-printed forms (see it like CD labels, 6 on a page).
I'm generating these images dynamically containing the selected content from a database. I then put these in a grid so they can be printed on the pre-printed forms.
I have the following code that creates the grid, generates the images from a user control and adds them to the grid and then prints these images.
I'm not following the MVVM pattern for the printing action. I created a reference to my view model in my code-behind.
Private Sub PrintButton_Click(sender As Object, e As RoutedEventArgs) Handles ButtonPrint.Click
Dim dlg As New PrintDialog
dlg.PrintTicket.PageMediaSize = New PageMediaSize(PageMediaSizeName.ISOA4)
Dim pageWidth As Double = GetPageWidth(dlg)
'Since the label is a perfect square: labelWidth = labelHeight
Dim labelWidthInPx As Integer = Utilities.ConvertMmToPixels(My.Settings.LabelWidthInMm)
'Set spacing distances in pixels
Dim horizontalLabelSpacing As Integer = Utilities.ConvertMmToPixels(My.Settings.HorizontalLabelSpacinginMm)
Dim verticalLabelSpacing As Integer = Utilities.ConvertMmToPixels(My.Settings.VerticalLabelSpacingInMm)
Dim topMargin As Integer = Utilities.ConvertMmToPixels(My.Settings.TopMarginInMm)
Dim leftMargin As Integer = Utilities.ConvertMmToPixels(My.Settings.LeftMarginInMm)
Dim bottomMargin As Integer = Utilities.ConvertMmToPixels(My.Settings.BottomMarginInMm)
'Create the table/grid
Dim tbl As New Grid
If CheckBoxPrintGridLines.IsChecked Then
tbl.ShowGridLines = True
Else
tbl.ShowGridLines = False
End If
'Add 3 columns (2 for the labels, 1 for spacing)
Dim col1 As New ColumnDefinition With {
.Width = New GridLength(labelWidthInPx, GridUnitType.Pixel)
}
Dim col2 As New ColumnDefinition With {
.Width = New GridLength(horizontalLabelSpacing, GridUnitType.Pixel)
}
Dim col3 As New ColumnDefinition With {
.Width = New GridLength(labelWidthInPx, GridUnitType.Pixel)
}
tbl.ColumnDefinitions.Add(col1)
tbl.ColumnDefinitions.Add(col2)
tbl.ColumnDefinitions.Add(col3)
'Add 5 Rows (3 for labels, 2 for spacing)
Dim row1 As New RowDefinition With {
.Height = New GridLength(labelWidthInPx, GridUnitType.Pixel)
}
Dim row2 As New RowDefinition With {
.Height = New GridLength(verticalLabelSpacing, GridUnitType.Pixel)
}
Dim row3 As New RowDefinition With {
.Height = New GridLength(labelWidthInPx, GridUnitType.Pixel)
}
Dim row4 As New RowDefinition With {
.Height = New GridLength(verticalLabelSpacing, GridUnitType.Pixel)
}
Dim row5 As New RowDefinition With {
.Height = New GridLength(labelWidthInPx, GridUnitType.Pixel)
}
tbl.RowDefinitions.Add(row1)
tbl.RowDefinitions.Add(row2)
tbl.RowDefinitions.Add(row3)
tbl.RowDefinitions.Add(row4)
tbl.RowDefinitions.Add(row5)
'Add label images
Dim reelData = CType(DataGridReels.ItemsSource, List(Of ReelInfo))
Dim rowIndex As Integer = 0
Dim colIndex As Integer = 0
For Each reel In reelData.Where(Function(r) r.IsSelected = True)
Dim partNumberData = ViewModel.DataService.GetPartNumberDataAsync(reel.PartNumber)
Dim batchData = ViewModel.DataService.GetBatchDataAsync(reel.PartNumber, reel.HENBatchNumber)
LabelImageControl.IsPrinting = True
LabelImageControl.PartNumberData = partNumberData.Result
LabelImageControl.BatchData = batchData.Result
LabelImageControl.ReelData = reel
LabelImageControl.Refresh
UpdateUI()
Dim labelImage As New Image
labelImage = GetImageFromLabel(LabelImageControl)
labelImage.Width = labelWidthInPx
labelImage.Height = labelWidthInPx
Grid.SetRow(labelImage, rowIndex)
Grid.SetColumn(labelImage, colIndex)
tbl.Children.Add(labelImage)
tbl.Refresh
colIndex += 1
If colIndex > 1 Then
colIndex = 0
rowIndex += 1
End If
Next
Dim iuc As New InlineUIContainer(tbl)
Dim p As New Paragraph(iuc)
'Create print dialog
If dlg.ShowDialog.GetValueOrDefault Then
'Create a flow document
Dim doc As New FlowDocument With {
.Name = "LabelPage",
.ColumnWidth = pageWidth,
.PagePadding = New Thickness(leftMargin, topMargin, 0, bottomMargin)
}
doc.Blocks.Add(p)
'Create IDocumentPagniatorSource from FlowDocument
Dim idpSource As IDocumentPaginatorSource = doc
Try
Me.Cursor = Cursors.Wait
dlg.PrintDocument(idpSource.DocumentPaginator, "Label Page")
Catch ex As Exception
Me.Cursor = Cursors.Arrow
MessageBox.Show("An error occurred during printing: " & ex.Message, "Print error")
Finally
Me.Cursor = Cursors.Arrow
End Try
End If
End Sub
When I send the output to the PDF printer I only get one image in the top left corner of the page/grid.
Since the user control (LabelImageControl) is in the XAML, I can see it changing while debugging. So the data is coming into the user control correctly.
When I check the grid with the XML Visualiser I see it has the same number of children as the items I selected in the datagrid.
Can anyone point me in the right direction on how to get the grid printing correctly?
I am doing my homework but stuck on a part. Problem is, How can i populate seat number in array of controls(labels) using database. I already created labels and a class to retrieve all rows from database but how can i apply it in main form and populate labels.
--------------------------Class---------------------------------------
Public Shared Function getOneRow(PK As Integer) As datMovieTimes
Dim returnRow As New datMovieTimes(0)
Dim connDB As New SqlConnection
connDB.ConnectionString = Conn.getConnectionString
Dim command As New SqlCommand
command.Connection = connDB
command.CommandType = CommandType.Text
command.CommandText = SQLStatements.SELECT_1_BY_ID
command.Parameters.AddWithValue("#Key", PK)
Try
connDB.Open()
Dim dR As IDataReader = command.ExecuteReader
If dR.Read() Then
returnRow.showingID = PK
If Not IsDBNull(dR(Fields.movieID)) Then returnRow.movieID = dR(Fields.movieID)
If Not IsDBNull(dR(Fields.dateTime)) Then returnRow.dateTime = dR(Fields.dateTime)
If Not IsDBNull(dR(Fields.isActive)) Then returnRow.isActive = dR(Fields.isActive)
End If
Catch ex As Exception
Console.WriteLine(Err.Description)
End Try
Return returnRow
End Function
Public Shared Function getAllRows() As Generic.List(Of datMovieTimes)
Dim returnRows As New Generic.List(Of datMovieTimes)
Dim connDB As New SqlConnection
connDB.ConnectionString = Conn.getConnectionString
Dim command As New SqlCommand
command.Connection = connDB
command.CommandType = CommandType.Text
command.CommandText = SQLStatements.SELECT_ALL
Try
connDB.Open()
Dim dR As IDataReader = command.ExecuteReader
Do While dR.Read()
Dim Row As New datMovieTimes(0)
If Not IsDBNull(dR(Fields.showingID)) Then Row.showingID = dR(Fields.showingID)
If Not IsDBNull(dR(Fields.movieID)) Then Row.movieID = dR(Fields.movieID)
If Not IsDBNull(dR(Fields.dateTime)) Then Row.dateTime = dR(Fields.dateTime)
If Not IsDBNull(dR(Fields.isActive)) Then Row.isActive = dR(Fields.isActive)
returnRows.Add(Row)
Loop
Catch ex As Exception
Console.WriteLine(Err.Description)
End Try
Return returnRows
End Function
-----------------------------main form-----------------------------------------
Public Sub createSeat()
Dim S1 As Label
For X As Integer = 1 To _MAX_X
For Y As Integer = 1 To _MAX_Y
S1 = New Label
S1.Height = 25
S1.Width = 25
S1.BackColor = Color.LightGreen
S1.Top = 100 + (X - 1) * (S1.Height + 5)
S1.Left = 200 + (Y - 1) * (S1.Width + 5)
S1.TextAlign = ContentAlignment.MiddleCenter
S1.Text = Y.ToString
AddHandler S1.Click, AddressOf GenericLabel_Click
Me.Controls.Add(S1)
_SeatArray(X, Y) = S1
Next
Next
For X As Integer = 0 To 9
_AlphaLabel(X) = New Label
_AlphaLabel(X).Height = 25
_AlphaLabel(X).Width = 25
_AlphaLabel(X).BackColor = Color.Transparent
_AlphaLabel(X).Top = 130 + (X - 1) * (_AlphaLabel(X).Height + 6)
_AlphaLabel(X).Left = 170
_AlphaLabel(X).Text = _AlphaName(X)
Me.Controls.Add(_AlphaLabel(X))
Next
End Sub
Private Sub GenericLabel_Click(sender As Object, e As EventArgs)
Dim L As New Label
L = DirectCast(sender, Label)
If L.BackColor = Color.LightGreen Then
L.BackColor = Color.Orange
clickLess -= 1
ElseIf L.BackColor = Color.Orange Then
L.BackColor = Color.LightGreen
clickLess += 1
End If
clickCount += 1
Me.lblRemainingCount.Text = clickLess.ToString
Me.nudTicketsCount.Value = clickCount
If clickLess <= 0 Then
MsgBox("No more seats left.", MsgBoxStyle.OkOnly, "House Full")
End If
End Sub
Database pic
When creating labels, insert one more line:
S1.Name = "MyLabel" & X & Y
When accessing the label:
Dim MyCurrentLabel as Label
MyCurrentLabel = CType("MyLabel" & X & Y, Label)
Then you can do things with the current label:
MyCurrentLabel.Text = "Hello World"
current image
Now it is something like this, so it want to change the colour to red if it is paid according to database.
Thanks
I found the answer, sorry i forgot to mention it because i was busy in completing the project
----------------------Seat creation----------------------------------------
Public Sub createSeat()
Dim S1 As Label
Dim numValue As Integer = 1
For X As Integer = 1 To _MAX_X
For Y As Integer = 1 To _MAX_Y
S1 = New Label
S1.Height = 25
S1.Width = 25
S1.BackColor = Color.LightGreen
S1.Top = 180 + (X - 1) * (S1.Height + 5)
S1.Left = 200 + (Y - 1) * (S1.Width + 5)
S1.TextAlign = ContentAlignment.MiddleCenter
S1.Text = Y.ToString
' S1.Text = numValue
S1.Name = "Label" & numValue
AddHandler S1.Click, AddressOf GenericLabel_Click
Me.Controls.Add(S1)
_SeatArray(X, Y) = S1
numValue += 1
Next
Next
For X As Integer = 0 To 9
_AlphaLabel(X) = New Label
_AlphaLabel(X).Height = 25
_AlphaLabel(X).Width = 25
_AlphaLabel(X).BackColor = Color.Transparent
_AlphaLabel(X).Top = 210 + (X - 1) * (_AlphaLabel(X).Height + 6)
_AlphaLabel(X).Left = 170
_AlphaLabel(X).Text = _AlphaName(X)
Me.Controls.Add(_AlphaLabel(X))
Next
End Sub
-------------------------------populate seat number----------------------------------
Public Sub populateSeatNumber()
Dim connectionString As String = DBL.Conn.getConnectionString
Dim connection As New SqlConnection(connectionString)
connection.Open()
Dim selectStatement As String = "SELECT * FROM datTicketsSold"
Dim selectCommand As New SqlCommand(selectStatement, connection)
Dim daSoldTickets As New SqlDataAdapter(selectCommand)
Dim dsSoldTickets As DataSet = New DataSet
daSoldTickets.Fill(dsSoldTickets, "datTicketsSold")
connection.Close()
Dim dtTickets As DataTable = dsSoldTickets.Tables("datTicketsSold")
Dim row As DataRow
For Each row In dtTickets.Rows
If row(3) = True Then
CType(Controls("Label" & row(2)), Label).BackColor = Color.Red
redCounter += 1
Else
CType(Controls("Label" & row(2)), Label).BackColor = Color.Yellow
yellowCounter += 1
End If
Next
Me.lblReservedCount.Text = yellowCounter.ToString
Me.lblSoldCount.Text = redCounter.ToString
End Sub
Thanks everyone
I have a canvas that shows an audio waveform, which is made using a lot of Lines. Each line is Tagged with it's time code so I can identify where in the audio it is.
I want to put a rectangle on the canvas based on data stored in an observable collection.
Basically, Timespan start and end points so I can show a block of audio.
The problem I'm having is that to show the rectangle, I have to know the Canvas left value and width.
I can get these by scanning through the canvas children until I find the correct line and getting its X1 value, but I don't know how to do it in a binding.
I want to bind the observable collection ItemsControl so I can show the rectangles on the canvas.
Is it possible to bind to a function or something that would do the calculations based on the data in the observable collection?
XAML:
<ScrollViewer Grid.Row="2" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden">
<Canvas Name="waveform" >
<ItemsControl Name="RectArea"> <!-- Where I hope to have the rectangles appear on top of the waveform canvas -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Stroke="Yellow" Fill="Yellow" Opacity="0.2" Height="200" Width="{Binding Width}" Canvas.Left="{Binding Left}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
</ScrollViewer>
Creating the waveform:
Dim seconds As Integer = 0
lines = New Dictionary(Of String, Line)
Using Reader As New AudioFileReader(openfile.FileName)
Dim samples = Reader.Length / (Reader.WaveFormat.Channels * Reader.WaveFormat.BitsPerSample / 8)
Dim f = 0.0F
Dim max = 0.0F
Dim batch As Integer = Math.Max(10, samples / samplecount)
Dim mid = 100
Dim yScale = 100
Dim buffer(batch) As Single
Dim read As Integer
Dim xPos = 0
read = Reader.Read(buffer, 0, batch)
While read = batch
For n As Integer = 0 To read
max = Math.Max(Math.Abs(buffer(n)), max)
Next
Dim line As New Line
line.X1 = xPos
line.X2 = xPos
line.Y1 = mid + (max * yScale)
line.Y2 = mid - (max * yScale)
line.Tag = Reader.CurrentTime
line.StrokeThickness = 1
line.Stroke = Brushes.DarkGray
AddHandler line.MouseDown, AddressOf Line_MouseDown
waveform.Children.Add(line)
' lines is a dictionary that holds all of the line information. nothing is bound to it, it just allows me to search against time code so I can highlight the line as the audio is playing'
If Not lines.ContainsKey(Reader.CurrentTime.Hours.ToString().PadLeft(2, "0") & Reader.CurrentTime.Minutes.ToString().PadLeft(2, "0") & Reader.CurrentTime.Seconds.ToString().PadLeft(2, "0") & Reader.CurrentTime.Milliseconds.ToString().PadLeft(3, "0").Substring(0, 1)) Then
lines.Add(Reader.CurrentTime.Hours.ToString().PadLeft(2, "0") & Reader.CurrentTime.Minutes.ToString().PadLeft(2, "0") & Reader.CurrentTime.Seconds.ToString().PadLeft(2, "0") & Reader.CurrentTime.Milliseconds.ToString().PadLeft(3, "0").Substring(0, 1), line)
End If
' Draw a tall black line and show timecode every 10 seconds to make it easier to see where you are on the code '
If Reader.CurrentTime.TotalSeconds > (seconds + 10) Then
seconds = Reader.CurrentTime.TotalSeconds
line = New Line
line.X1 = xPos
line.X2 = xPos
line.Y1 = mid + yScale
line.Y2 = mid - yScale
line.StrokeThickness = 1
line.Stroke = Brushes.Black
waveform.Children.Add(line)
Dim textblock As New TextBlock
textblock.Text = Reader.CurrentTime.Hours.ToString().PadLeft(2, "0") & ":" & Reader.CurrentTime.Minutes.ToString().PadLeft(2, "0") & ":" & Reader.CurrentTime.Seconds.ToString().PadLeft(2, "0") & "," & Reader.CurrentTime.Milliseconds.ToString().PadLeft(3, "0")
textblock.Foreground = Brushes.Black
Canvas.SetLeft(textblock, xPos)
Canvas.SetTop(textblock, yScale)
waveform.Children.Add(textblock)
End If
max = 0
xPos += 1
read = Reader.Read(buffer, 0, batch)
End While
waveform.Width = xPos
End Using
ObservableCollection:
Imports System.ComponentModel
Imports System.Collections.ObjectModel
Public Class ocAudioSelection
Implements INotifyPropertyChanged
Private _Changed As Boolean
Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Protected Overridable Sub OnPropertyChanged(ByVal Propertyname As String)
On Error GoTo sError
If Not Propertyname.Contains("Changed") Then
Changed = True
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(Propertyname))
Exit Sub
sError:
MsgBox(ErrorToString)
End Sub
Public Property Changed() As Boolean
Get
Return _Changed
End Get
Set(ByVal value As Boolean)
If _Changed <> value Then
_Changed = value
OnPropertyChanged("Changed")
End If
End Set
End Property
Private _startTime As String
Private _endTime As String
Public Sub New()
End Sub
Public Sub New(startTime As String)
_startTime = startTime
End Sub
Public Sub New(startTime As String, endTime As String)
_startTime = startTime
_endTime = endTime
End Sub
Public Property StartTime As String
Get
Return _startTime
End Get
Set(value As String)
If value <> _startTime Then
_startTime = value
OnPropertyChanged("StartTime")
End If
End Set
End Property
Public Property EndTime As String
Get
Return _endTime
End Get
Set(value As String)
If value <> _endTime Then
_endTime = value 'TimeSpan.Parse()
OnPropertyChanged("EndTime")
End If
End Set
End Property
End Class
I am trying to get all chars of Segoe UI Symbol Font.
I got them, converted to char, converted to Hex value and added to listview as items.
So, somebody else can use their hex values for XAML projects as icon.
But the problem is this in the code:
i am always getting OverFlowException at the function Convert.ToChar.
Code is running correct, but when the index variable is bigger than 65535 which is max char value, i got overflowexception.
But if you run the code, as you will see, in the Segoe UI Symbol fontfamily there are more chars which is bigger than 65535.
Maybe my method is wrong, you can advice me another method.
MainWindow.xaml file:
<Grid Loaded="Grid_Loaded">
<ListView x:Name="listview">
<ListView.View>
<GridView>
<GridViewColumn Header="HexValue" />
</GridView>
</ListView.View>
</ListView>
</Grid>
MainWindow.xaml.vb file
Class MainWindow
Public glyph As GlyphTypeface
Dim characterMap As IDictionary(Of Integer, UShort)
Private Sub Grid_Loaded(sender As Object, e As RoutedEventArgs)
SymbolleriGetir()
End Sub
Public Sub SymbolleriGetir()
Dim segoeUiSymbol As FontFamily
For Each font As FontFamily In Fonts.SystemFontFamilies
Dim fontName As String
fontName = font.Source
If fontName = "Segoe UI Symbol" Then
segoeUiSymbol = font
End If
Next
For Each typeFace As Typeface In segoeUiSymbol.GetTypefaces
typeFace.TryGetGlyphTypeface(glyph)
If glyph IsNot Nothing Then
characterMap = glyph.CharacterToGlyphMap
Else
Continue For
End If
Next
For i As Integer = 0 To characterMap.Keys.Count
Dim index As Integer = characterMap.Keys.ElementAt(i)
Dim c As Char = Nothing
c = Convert.ToChar(index)
Dim charText As String = c.ToString()
listview.Items.Add(String.Format("&#x{0:x2};", System.Convert.ToUInt32(c)))
Next
End Sub
End Class
CharacterToGlyphMap is a lookup map
(IDictionary(Of Integer, UShort))
with the UShort being the unicode char
so it is not necessary to convert.
I am no VB developer, but I just just coded this up and tested which enumerates the chars, and creates an image glyph next to each hex value:
Wingdings:
Your loaded event handler:
(I exited after 100 due to load time)
Private Sub Grid_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim glyph As GlyphTypeface
Dim glyphIndex As UShort
Dim typeface As System.Windows.Media.Typeface = New System.Windows.Media.Typeface("Segoe UI Symbol")
If (typeface.TryGetGlyphTypeface(glyph)) Then
Dim glyphLookupMap As IDictionary(Of Integer, UShort) = glyph.CharacterToGlyphMap
Dim x As Integer = 0
For Each kvp As KeyValuePair(Of Integer, UShort) In glyphLookupMap
Dim c As Char = Convert.ToChar(kvp.Value)
Dim glyphImage As ImageSource = Nothing
If (glyphLookupMap.TryGetValue(kvp.Key, glyphIndex)) Then
glyphImage = Me.CreateGlyph(glyph, glyphIndex, kvp.Value, Brushes.Blue)
End If
Me._listview.Items.Add(Me.CreateGlyphListboxEntry(kvp.Key, glyphImage))
Dim num As Integer = x + 1
x = num
If (num > 100) Then
Exit For
End If
Next
End If
End Sub
And here would be the Glyph image creator
Private Function CreateGlyph(ByVal glyphTypeface As System.Windows.Media.GlyphTypeface, ByVal glyphIndex As UShort, ByVal charUShortVal As UShort, ByVal foreground As Brush) As System.Windows.Media.ImageSource
Dim imageSource As System.Windows.Media.ImageSource
Dim flag As Boolean = False
Dim drawingImage As System.Windows.Media.DrawingImage = Nothing
Try
Dim glyphIndexes As IList(Of UShort) = New List(Of UShort)() From
{
charUShortVal
}
Dim advanceWidths As IList(Of Double) = New List(Of Double)() From
{
glyphTypeface.AdvanceWidths(glyphIndex)
}
Dim glyphRun As System.Windows.Media.GlyphRun = New System.Windows.Media.GlyphRun(glyphTypeface, 0, False, 1, glyphIndexes, New Point(0, 0), advanceWidths, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing)
drawingImage = New System.Windows.Media.DrawingImage(New System.Windows.Media.GlyphRunDrawing(foreground, glyphRun))
Catch exception As System.Exception
imageSource = Nothing
flag = True
End Try
If (Not flag) Then
imageSource = drawingImage
End If
flag = False
Return imageSource
End Function
And finally the Listbox Entry creator:
Private Function CreateGlyphListboxEntry(ByVal charIntValue As Integer, ByVal glyphImage As ImageSource) As FrameworkElement
Dim result As StackPanel = New StackPanel() With
{
.Orientation = Orientation.Horizontal
}
Dim text As TextBlock = New TextBlock() With
{
.Text = String.Format("{0:X}", charIntValue),
.Foreground = Brushes.Black,
.FontSize = 17,
.Margin = New Thickness(10, 0, 10, 0)
}
result.Children.Add(text)
If (glyphImage IsNot Nothing) Then
Dim image As System.Windows.Controls.Image = New System.Windows.Controls.Image()
Dim num As Double = 32
Dim num1 As Double = num
image.Height = num
image.Width = num1
image.Stretch = Stretch.Uniform
image.Source = glyphImage
result.Children.Add(image)
End If
Return result
End Function
Hope this helps!