Can't specify a SolidBrushColor - wpf

I define a variable as follows:
x = Color.FromArgb(<some integer>)
and use it as follows when specifying a rectangle:
Dim Cell As New Shapes.Rectangle With
{
.Fill = New SolidColorBrush(x),
'......
}
However, this gives an error message:
Value of type 'Color' cannot be converted to 'Color'
What is wrong here?

There are two different Color types.
System.Drawing.Color (the one that you are using, GDI+)
System.Windows.Media.Color (the one WPF uses)
A SolidColorBrush or brushes in general in WPF expect the latter type.
Public Sub New (color As Color)
Unfortunately, this type does not have an overload for a single int, which means you have to convert it and use this FromArgb method instead:
Public Shared Function FromArgb (a As Byte, r As Byte, g As Byte, b As Byte) As Color
You can use one of the approaches from Convert integer to color in WPF, like this one:
Dim bytes = BitConverter.GetBytes(/* some integer */)
Dim color = Color.FromArgb(bytes(3), bytes(2), bytes(1), bytes(0))
Dim brush = New SolidColorBrush(color)
Dim Cell As New Shapes.Rectangle With
.Fill = brush
}

Related

WPF DataVisualization Chart Format Labels

I'm using the DataVisualization charting within WPF and creating a BarSeries in code, but I can't get the numbers formatted on the X axis.
I don't want to do this in XAML because the type of chart can vary according to user selection and it seemed more flexible to do all of this in code rather than having different chart types. The number of data series also fluctuates.
The XAML is just
xmlns:chttk="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
<chttk:Chart Name="DataChart1" Margin="0" Title="{Binding AxisXTitle}" DataContext="{Binding GraphData1}" Style="{StaticResource ChartStyle1}" BorderBrush="Transparent"/>
The code behind is
Dim dataChart As System.Windows.Controls.DataVisualization.Charting.Chart = DataChart1
Dim s As New System.Windows.Controls.DataVisualization.Charting.BarSeries
s.Title = "My Chart"
s.DependentValuePath = "Value"
s.IndependentValuePath = "Key"
s.DataContext = New Binding("[0]")
s.ItemsSource = CType(itm, IEnumerable)
dataChart.Series.Add(s)
The DataContext is a DataSeries.Collection with the data in KeyValuePairs. The values are all Double values.
The graph is displaying, but the values on the axis are un-formatted, e.g. 120000. I have found a few examples pointing at different Axis types and LabelFormat and LabelStyle.Format but I can't find anything that works in the WPF environment in the code behind.
Thanks for the input - I finally managed to get it working with the following code:
Dim n As Integer
dataChart.Series.Clear()
Dim x As New System.Windows.Controls.DataVisualization.Charting.LinearAxis
x.Orientation = DataVisualization.Charting.AxisOrientation.X
Dim y As New System.Windows.Controls.DataVisualization.Charting.CategoryAxis
y.Orientation = DataVisualization.Charting.AxisOrientation.Y
Dim stl As New Style(GetType(System.Windows.Controls.DataVisualization.Charting.AxisLabel))
stl.Setters.Add(New Setter(System.Windows.Controls.DataVisualization.Charting.AxisLabel.StringFormatProperty, "{0:#,0}"))
x.AxisLabelStyle = stl
For Each itm As Object In o
Dim srs As New System.Windows.Controls.DataVisualization.Charting.BarSeries
pi = itm.GetType.GetProperty("SeriesTitle")
srs.Title = pi.GetValue(itm, Nothing)
srs.DependentValuePath = "Value"
srs.IndependentValuePath = "Key"
srs.DataContext = New Binding("[" & n & "]")
srs.ItemsSource = CType(itm, IEnumerable)
srs.DependentRangeAxis = x
srs.IndependentAxis = y
dataChart.Series.Add(srs)
n += 1
Next
Some of the gotchas that tripped me up were adding the axis. You need to add the right type of axis to the DependentRangeAxis or IndependentAxis. With a BarSeries the DependentRangeAxis is the X axis and can be a LinearAxis and the IndependentAxis is the Y axis and for me was a CategoryAxis. Also if you have multiple series then you need to apply the same axis to all series.
Hope this helps someone else.

send data from form 1 to form 2

I have made 2 variables:
Public a as Integer
Public b as Integer
and I have a text field where 2 values can be inserted like this: "1 - 10"
so I split the value and saved them in those 2 variables a and b.
but I need those 2 values in different forms but all I'm getting is 0.
I also created Dim c as form1 = new form1 in the form2.
What's the problem?
Depending on a relation between Form1 and Form2, you can use this kind of communication (this is for a parent-child relation):
Form 2:
Public ParentFrm as Form1
Public a as Int16
Form 1 - in it's running instance:
Public b as Int16
Dim NewInstanceOfForm2 as New Form2
NewInstanceOfForm2.ParentFrm = Me ' this is to ensure you can talk back to correct instance of parent form
NewInstanceOfForm2.a = 12345
NewInstanceOfForm2.BackColor = colors.Pink
NewInstanceOfForm2.TextBox1.Text = "Hello World!!!"
Since we set the ParentFrm in the Form2, you can communicate the same way back and set things in Form1:
ParentFrm.b = 789
ParentFrm.TextBox3 = "Hi there!!!"
ParentFrm.UpdateForm1FromDatabasePublicFunction()
Siblings can communicate through a common parent. But in all the cases, you need to get to understand instances of the forms. Remember, that you can communicate only with objects (TextBox, Button, DataGridView,...) and Public variables of the form.
You could create a module and define the variable as puclic there, that way they'll always be accessible from anywhere on the application.
Right click the solution, Add New, Module
And inside that module add
Public a, b as Integer
To split the textbox input and store them in these vars use
Dim s as String
Dim sp() as String
s = TextBox1.Text
sp = s.Split("-")
This stores the values in the textbox separated by '-' on sp(0) and sp(1) respectively.
You can then stote them into you public variables.
a = sp(0)
b = sp(1)
And call then from any form you need.
Well, i am not sure what it exactly is you want but here are some suggestions:
if your form1 contains two variables like so:
Public a As Integer = 0
Public b As Integer = 0
and you want to retrieve the value of one of those variables from another form, lets say from Form2, then all you need to do is that:
(Put this code in either a function, or an event of your second Form (for example Form2)):
dim current_a As Integer = 0
current_a = Form1.a
dim current_b As Integer = 0
current_b = Form1.b
If you enter the text (for example: "1 - 10“), into a textbox, but want to get both values (in this case 1, and 10), you only need to grab them by for example creating a loop, to search for these values, like so:
dim textbox_str As String = ""
textbox_str = TextBox1.Text
( in this example, the TextBox1.Text would contain "1 - 10")
dim final_str1 As String = ""
dim final_str2 As String = ""
for each s_ As String In textbox_str
If Not s_ = " " Then
final_str1 = final_str1 & s_
Else
Exit For
End If
Next
(after this, final_str1 would contain "1")
(now extract the second number, by doing the following:)
final_str2 = textbox_str.Replace(final_str1 & " - ", "")
(and now, final_str2 would contain "10")
(so you would have both numbers extracted from that text)
As i said, i do not exactly know what you want, but hopefully this helped you, let me know if it is what you were looking for!

Extract color name from a System.Windows.Media.Color

How do I extract the name of a color (e.g. "green") from a System.windows.Media.Color object? The .tostring() method gives me the hex format #ff008000.
You could use reflection to get the color names:
static string GetColorName(Color col)
{
PropertyInfo colorProperty = typeof(Colors).GetProperties()
.FirstOrDefault(p => Color.AreClose((Color)p.GetValue(null), col));
return colorProperty != null ? colorProperty.Name : "unnamed color";
}
The following code shows how to use GetColorName():
Color col = new Color { R = 255, G = 255, B = 0, A = 255 };
MessageBox.Show(GetColorName(col)); // displays "Yellow"
Please note that the above GetColorName() method is not very fast, since it uses reflection. If you plan to make many calls to GetColorName(), you probably should cache the color table in a dictionary.
In the WPF, the hex code stands just as it were rgba.
#ff008000
Would be
rgba(255, 0, 80, 0); // last 2 00s are for alpha filter.
If that's the result. You should use switch statement to convert it to some String value. Also, .ToString() method doesn't generate a Human readable String result like Green. It just converts the result to a String while passing the value to methods and function that would require a String argument.
The following code would do the trick for you:
var converter = new System.Windows.Media.BrushConverter();
var brush = (Brush) converter.ConvertFromString("#ff008000");
Use the brush now.
My Visual Basic translation is like this:
Function GetColorName(ByVal col As System.Windows.Media.Color) As String
Dim coltype As System.Type = GetType(System.Windows.Media.Colors)
Dim colproplist() As PropertyInfo = coltype.GetProperties
Try
Dim colorproperty As PropertyInfo = colproplist.FirstOrDefault(Function(p As PropertyInfo) Color.AreClose(p.GetValue(col, Nothing), col))
Return colorproperty.Name
Catch ex As Exception
Return ("unnamed color")
End Try
End Function
I had to catch a nullreference exception, when executing this function with an unnamed color. Why, I do not know.
This will return the English color name if it is defined:
Function GetName(color As Media.Color) As String
Dim c = System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B)
Return System.Drawing.ColorTranslator.ToHtml(c)
End Function

How to make an array of PictureBoxes in Visual Basic

How do I make an array of PictureBoxes in Visual Basic?
I'm trying to make a row of PictureBoxes -that's all the same size, and same picture- to display across the form. How could I do this?
I made the array using this:
Dim blk(10) As PictureBox
and the code to place the PictureBoxes is this:
'Create PictureBoxes
blk(0) = blk_Green()
blk(0).Image = imgl_blk.Images(0)
blk(0).Visible = True
blk(0).SetBounds(10, 10, blk_Green.Width, blk_Green.Height)
For i = 1 To 10 Step 1
blk(i) = blk_Green()
blk(i).Image = imgl_blk.Images(0)
blk(i).Visible = True
blk(i).SetBounds(i * 10, 10, blk_Green.Width, blk_Green.Height)'I will change this according to what it needs to be
Next
imgl_blk is an ImageList, and blk_Green is a ImageBox I've already made on the form.
When I run it, only one of the PictureBoxes will show up, instead of all 10 from the array.
This is what i'm trying to get (Or something like this):
This is what happens instead:
How could I make this work? Thanks in advance!
If you want to create a control array:
Dim blk() As PictureBox
blk = New PictureBox() {PictureBox1, PictureBox2, PictureBox3, PictureBox4}
Then you can reference PictureBox1 with blk(0), PictureBox2 with blk(1), PictureBox3 with blk(2) and PictureBox4 with blk(3).
You're assigning the same Object's reference to all 10 PictureBoxes. You need to instantiate each one of your PictureBoxes separately and then assign each one's Image property.
BTW, you should really look into GDI+'s drawing methods such as Graphics.DrawImage() to do this kind of stuff. It would be a lot faster and less of a memory-hog.
You may try this :
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim Shapes(10) As PictureBox
For i = 1 To 10
Shapes(i) = New PictureBox
Shapes(i).Name = "rect" + Str(i)
Shapes(i).BackColor = Color.Green
Shapes(i).Location = New Point(10 + 50 * i, 20)
Shapes(i).Size = New Size(40, 20)
Shapes(i).Visible = True
Me.Controls.Add(Shapes(i))
Next
End Sub
End Class

Label with different font sizes

Basically I want to achieve something like this:
but I have no idea how to do it, I tried with 2 labels to combine them but the result isn't that great..
You need to draw the text from a different point of view, namely, the baseline:
Public Class MyLabel
Inherits Label
<Browsable(False)> _
Public Overrides Property AutoSize As Boolean
Get
Return False
End Get
Set(value As Boolean)
'MyBase.AutoSize = value
End Set
End Property
Protected Overrides Sub OnPaint(e As PaintEventArgs)
'MyBase.OnPaint(e)
Dim fromLine As Integer = Me.ClientSize.Height * 0.75
Dim g As Graphics = e.Graphics
Dim fontParts() As String = Me.Text.Split(".")
Using bigFont As New Font(Me.Font.FontFamily, 20)
TextRenderer.DrawText(g, fontParts(0), bigFont, _
New Point(0, fromLine - GetBaseLine(bigFont, g)), _
Me.ForeColor, Color.Empty)
If fontParts.Length > 1 Then
Dim bigWidth As Integer = TextRenderer.MeasureText(g, fontParts(0), bigFont, _
Point.Empty, TextFormatFlags.NoPadding).Width
Using smallFont As New Font(Me.Font.FontFamily, 8)
TextRenderer.DrawText(g, "." & fontParts(1), smallFont, _
New Point(bigWidth + 3, fromLine - GetBaseLine(smallFont, g)), _
Me.ForeColor, Color.Empty)
End Using
End If
End Using
End Sub
Private Function GetBaseLine(fromFont As Font, g As Graphics) As Single
Dim fontHeight As Single = fromFont.GetHeight(g)
Dim lineSpacing As Single = fromFont.FontFamily.GetLineSpacing(fromFont.Style)
Dim cellAscent As Single = fromFont.FontFamily.GetCellAscent(fromFont.Style)
Return fontHeight * cellAscent / lineSpacing
End Function
End Class
The code basically measures the height of the font from a line. In my example, I used the bottom 25% of the Label's client space to say, start drawing from this line: Me.ClientSize.Height * 0.75.
For each font you use, you would have to measure that font's baseline and subtract that from your drawing line in order to offset your drawing position of the text.
Measuring an individual character's dimensions is not easy due to aliasing and glyph overhangs. I added a small padding between the big text and the small text: bigWidth + 3 to try to make it look good. If the big number ends in a 7, the distance looks a little off because the stem of the 7 is angled.
Result:
Create a new class inherited from Label, and override the void OnPaint(PaintEventArgs e) method to change the default rendering behavior:
public class MyLabel : Label
{
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawString("A", Font, new SolidBrush(ForeColor), 10, 10);
e.Graphics.DrawString("B", new Font(Font.FontFamily, 20), new SolidBrush(ForeColor), 50, 10);
}
}
As a result, "B" will be two times larger the "A". You can achieve your goal in the same way, but you have to calculate the position of your sub-strings ("145", ".", "54") and draw them.
Use devexpress LabelControl.AllowHtmlString property to true and use the supported <size> tag within the LabelControl's Text property as detailed in the HTML Text Formatting documentation.
you can use user control WPF in windows form. to do that do this step.
1. add user control to the windows form
2.from xml of usercontrol name grid like t1
3. add this function to the usercontrol.wpf.cs
public void Actor(string text)
{
StringBuilder sb = new StringBuilder();
sb.Append(#"<TextBlock xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'> ");
sb.Append(text);
sb.Append(#"</TextBlock>");
TextBlock myButton = (TextBlock)XamlReader.Parse(sb.ToString());
this.t1.Children.Clear();
t1.Children.Add(myButton);
}
4. after that from form1.css add this function in every where you want.
userControl11.Actor("<Run Text='Hi ' FontWeight='Bold'/><Run Text='Hitler ' FontWeight='Bold'/>");
userControl11.Actor(" < Run FontWeight = 'Bold' FontSize = '14' Text = 'This is WPF TextBlock Example. ' />");
you can mange the write code "" of Actor function by using xml wpf.

Resources