WPF in VB Text Box 'System.NullReferenceException' - wpf

so here is simple WPF application I made to practice OO concepts. It has the user input a number in feet and converts to meters by outputting a message box.
Class MainWindow
Dim lengthInMeters = txtBox1.Text '***An exception of type "System.NullReferenceException" occurred***
Private Sub button_Click(sender As Object, e As RoutedEventArgs) Handles button.Click
MessageBox.Show(COptions.GetLength(lengthInMeters), "Conversion Successful!", MessageBoxButton.OK)
End Sub
End Class
And my other Class file:
Public Class COptions
Public Shared Function GetLength(lengthInMeters) As Double
Return lengthInMeters / 3.28
End Function
End Class
Also, here is the XAML for the textbox:
<TextBox
x:Name="txtBox1"
x:FieldModifier="public"
HorizontalAlignment="Left"
Height="23"
Margin="200,140,0,0"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="120"
enderTransformOrigin="1.29,-3.252"
Grid.Column="1"
/>
I am getting a NullReference at "Dim lengthInMeters = txtBox1.Text" and I believe I need to instantiate my object reference? But how?
Thank you for your help!

Fields are initialized before the constructor runs, and GUI components initialized in the constructor, so txtBox1 has not been initialized at the point you are using it, as you have found out. Even if it did work, it would capture the value of the text box at that point, which is before the user has had a chance to enter anything.
Instead, move the Dim lengthInMeters = txtBox1.Text line into your button click handler, so that you get the current value of the text box just before you use it. Your current code is also relying on some implicit type conversions - I would recommend turning Option Strict On to catch these, and use explicit conversions.
Private Sub button_Click(sender As Object, e As RoutedEventArgs) Handles button.Click
Dim lengthInMeters = CDbl(txtBox1.Text)
MessageBox.Show(COptions.GetLength(lengthInMeters), "Conversion Successful!", MessageBoxButton.OK)
End Sub
Public Class COptions
Public Shared Function GetLength(lengthInMeters As Double) As Double
Return lengthInMeters / 3.28
End Function
End Class

Related

WPF Combobox Item Update

I am rather new to the WPF setup and I am running into an issue where as far as I can see I have set it up correctly to have my combobox bound to a observable collection of object.
The Combobox will update when I add or delete items. If I make a change the items in the drop down will not show any differently but if I select one that was edited it will now show the new information but only when selected.
I have set up the object class to use INotifyPropertyChanged correctly I think but it does not seem to be functioning. Going to attach the code below so that you can easily see exactly what I am trying to describe.
What I am trying to do it allow a user to push a button and have the text inside a combobox update to show the new text.
Imports System.ComponentModel
Public Class Window2
Public _names As New System.Collections.ObjectModel.ObservableCollection(Of TestClass)
Public Sub BaseLoading() Handles MyBase.Loaded
Dim AddNewItem As New TestClass
AddNewItem.groupName = "Item " + (_names.Count + 1).ToString
_names.Add(AddNewItem)
cbo_Names.SetBinding(ItemsControl.ItemsSourceProperty, New Binding With {.Source = _names})
End Sub
Private Sub button_PreviewMouseDown(sender As Object, e As MouseButtonEventArgs)
Dim AddNewItem As New TestClass
AddNewItem.groupName = "Item " + (_names.Count + 1).ToString
_names.Add(AddNewItem)
_names(0).groupName = ("Value Changed")
End Sub
End Class
Public Class TestClasss
Implements INotifyPropertyChanged
Public _groupName As String = ""
Public Property groupName As String
Get
Return _groupName.ToString
End Get
Set(value As String)
_groupName = value
onPropertyChanged(New PropertyChangedEventArgs(_groupName))
End Set
End Property
Public Event PropertyChagned(ByVal sender As Object, ByVal e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
Public Sub onPropertyChanged(ByVal e As PropertyChangedEventArgs)
RaiseEvent PropertyChagned(Me, e)
End Sub
End Class
XAML
<Window x:Class="Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Button x:Name="button" Content="Button" PreviewMouseDown="button_PreviewMouseDown"/>
<ComboBox x:Name="cbo_Names" Margin="30,5,30,5" IsEditable="False" ItemsSource="{Binding _names, NotifyOnSourceUpdated=True,Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="groupName" SelectedItem="{Binding _names, NotifyOnSourceUpdated=True,Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</Window>
I would appreciate any help locating what I am missing.
You should pass the name of the data-bound property (instead of the value of the property) to the constructor of the PropertyChangedEventArgs:
onPropertyChanged(New PropertyChangedEventArgs("groupName"))
If you are using at least Visual Studio 2015, you could consider making the following change to your onPropertyChanged routine:
Public Sub onPropertyChanged(<System.Runtime.CompilerServices.CallerMemberName> Optional ByVal propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Then, in the setter for groupName you can call onPropertyChanged without specifying the property name, and it will be taken from the name of the caller (that is, it will end up being "groupName").
Effectively, this is doing the same thing as the previous answer, but in a way that is easier for you to code and maintain. (Along with the <CallerMemberName> attribute, this works well with NameOf, both making your code more robust against any changes in names of properties.)

Visual basic: '<name>' is not a member of '<classname>'

Before you read, here are a couple pages I have looked at before posting this question:
'Button_Click' : is not a member of 'ButtonTest::MainPage'. This question regards C++ and is not useful as far as I am aware. According to the only answer, you need to "define the prototype of MainPage::Button_Click in the MainPage.xaml.h file as a member of the class."
visual basic error BC30456 'Form1' is not a member of 'WindowsApplication1'. This question also experiences the same error, however it is caused by something else. The OP replied to this answer, saying that it fixed the problem:
If you have renamed the startup form1 it is likely you also have to change the Startup form setting. You can find this setting to open 'My Project' in the 'Solution Explorer'. Select the Application section, change the 'startup form' as appropriate.
In my case, I have not renamed anything since making the project, and the code which the error points to is a line which adds a handler in 'popup.g.i.vb'
I also looked on MSDN: Creating Event Handlers for WPF Controls. The page uses the following syntax to react to a button being clicked:
<Button Click="Button2_Click" />
and
Sub Button2_Click(ByVal Sender As Object, ByVal e As RoutedEventArgs)
'Code here
End Sub
This is exactly the same syntax as I have used.
My code
I am currently making a program using WPF and Visual Basic, and I wanted to make a small window pop up if the user causes an error.
I have a WPF window named popup.xaml and I have a class called 'popup' which inherits from 'window'. I want to create a window and then close it when the user clicks the 'ok' button. The equivalent of this in C# would be the following:
popup errorWindow = new popup("Error message here");
errorWindow.ShowDialog();
When this method is called, an override of popup() is called which initialises and also takes the error message as a parameter.
public partial class popup : Window
{
public popup()
{
InitializeComponent();
}
public popup(string errorMessage)
{
InitializeComponent();
this.errorMessage.Text = errorMessage;
}
private void okButton_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
When the 'ok' button is clicked, the okButton_Click() method is called and the window closes.
In my visual basic application, I have the same WPF code for the error window:
<Window x:Class="FacialRecognitionVB.popup"
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:FacialRecognitionVB"
mc:Ignorable="d"
Title="Error." MinHeight="150" MaxHeight="150" Height="150" MinWidth="300" MaxWidth="300" Width="300" >
<Grid>
<Border VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Gray" />
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5,5,5,5" >
<TextBlock x:Name="errorMessage" FontSize="18" FontWeight="Medium" Text="An error has occured." TextWrapping="Wrap" />
</StackPanel>
<Button x:Name="okButton" Template="{StaticResource ButtonTemplate}" Content="OK" Width="40" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="5,5,5,5" Click="okButton_Click" />
</Grid>
Despite this, the event handler for clicking the button is playing up. The VB code for my popup class is almost exactly the same:
Partial Public Class popup
Inherits Window
Public Sub Popup()
End Sub
Public Sub Popup(ByVal message As String)
Dim errorMessage As TextBlock
errorMessage.Text = message
End Sub
Private Sub okButton_Click(sender As Object, e As RoutedEventArgs)
Me.Close()
End Sub
End Class
I create an instance of the class using this code in MainWindow.vb:
Dim errorWindow As New popup()
errorWindow.Popup("An error has occured.")
When I try to build this, I get the error 'okButton_Click' is not a member of 'popup'. On double-clicking the error in the error list it takes me to popup.g.i.vb and highlights the following:
#ExternalSource ("..\..\popup.xaml", 14)
AddHandler okButton.Click, New RoutedEventHandler(AddressOf Me.okButton_Click)
#End ExternalSource
It will not give me any further information other than 'okButton_Click' is not a member of 'popup'
How can I fix this? I actually have several buttons on my main page which work perfectly using visual basic! This one button, for some reason, does not. Is there something different I need to do because it is on a separate window as part of a popup?
Update
I had another look round today and I found '{name}' is not a member of '{classname}' on MSDN which gives the following two solution:
1: Check the name of the member to ensure it is accurate.
2: Use an actual member of the class.
My button is named okButton and the method is okButton_Click(). The error is highlighted in the popup.g.i.vb file, saying that Me.okButton_Click is not a member of my popup class. I do not see how either of the fixes above apply, since I am using the correct name and the member does exist.
Your constructors are not defined correctly - constructors are always named New in VB.NET - and you need to call InitializeComponent from your constructor. You are also doing Dim errorMessage As TextBlock, which should not be required since it is defined in XAML.
It seems like something has broken the link between the XAML and the code behind file, and it's probably easier to delete all files related to the window and start from scratch, but your code behind should look something like this:
Partial Public Class popup
Inherits Window
Public Sub New()
' This call is required by the designer.
InitializeComponent()
End Sub
Public Sub New(ByVal message As String)
' This call is required by the designer.
InitializeComponent()
errorMessage.Text = message
End Sub
Private Sub okButton_Click(sender As Object, e As RoutedEventArgs)
Me.Close()
End Sub
End Class
In VS2015, the code behind does not have the Partial or Inherits Window parts, so those may not be required, but probably don't hurt anything.
Displaying the window should also look like the C# version:
Dim errorWindow As New popup("An error has occured.")
errorWindow.ShowDialog()

wpf lable text binding not working, where i am going wrong

I am new to WPF and trying something like this to update a label text in the WPF form from the class.
The onchange event is getting triggered, but not getting displayed on the form
Here is my class
Public Class ExtractDetails
Inherits UserControl
Implements INotifyPropertyChanged
Private _prdFrstName as string
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public Property PrdFrstName() As String
Get
Return _prdFrstName
End Get
Set(ByVal value As String)
If _prdFrstName <> value Then
_prdFrstName = value
Me.OnPropertyChanged("PrdFrstName")
End If
End Set
End Property
Public Sub suMainStrt()
PrdFrstName = strComurl ''contyains teh URL to nagigate to
webBrwFrst = New WebBrowser
webBrwFrst.Navigate(New Uri(strComurl))
Call extract(webBrwFrst, strComurl)
end sub
end class
the url keeps on changing as i ma getting the values from an excel file and looping for each URL.
i wanted to display the URL currently working now
this is my XAML
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Avenet Prduct Description Extractor" Height="396.627" Width="588.123" Background="AliceBlue" Icon="LGIcon.ico">
<Grid Height="341.077" Width="567.721" Background="AliceBlue">
<StackPanel Margin="170.225,226.418,3.143,0" Name="StackPanel1" Height="97.994" VerticalAlignment="Top">
<Label Height="30.906" Name="lblCrntSt1" Content="{Binding Path=PrdFrstName, UpdateSourceTrigger=PropertyChanged}" Width="161" BorderThickness="2" BorderBrush="AliceBlue" Background="Red" Foreground="White" FontSize="13"></Label>
</StackPanel>
</Grid>
and this is my windows class.
Class Window1
Dim clsIniti As New ExtractDetails
Public Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
'clsIniti = New ExtractDetails
Me.DataContext = clsIniti
End Sub
end class
without updating the text labels the entire function is working good. but i wish to display few things. where i am going wrong
I tried data binding by removing few parts to new created project. it works there. so some thing wrong in this code??? :`(
I see two possible causes that this doesn't work for you.
A. How does your OnPropertyChanged method look like?
' Correct implementation:
Private Sub OnPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
B. Make sure the ExtractDetails instance you call suMainStrt on, is the same as your DataContext instance. Test this by calling suMainStrt directly from the constructor of Window1:
Class Window1
Dim clsIniti As New ExtractDetails
Public Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
'clsIniti = New ExtractDetails
Me.DataContext = clsIniti
' test (if this works, your problem is B.)
clsIniti.suMainStrt()
End Sub
End Class
As a side note: Unless you have good reasons to do this, I suggest you create a dedicated viewmodel (class, not usercontrol) that contains the properties you want to bind to.

Update LineGraph Every Second

Hi I'm trying to update a line chart every second (from the wpf data visualisation toolkit). The following code works for a PieChart:
VB:
Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
' DispatcherTimer setup
Dim dt As DispatcherTimer = New DispatcherTimer()
AddHandler dt.Tick, AddressOf dispatcherTimer_Tick
dt.Interval = New TimeSpan(0, 0, 1)
dt.Start()
End Sub
Public Sub dispatcherTimer_Tick(ByVal sender As Object, ByVal e As EventArgs)
UpadateChartData()
Chart1.DataContext = ""
Chart1.DataContext = ChartData
End Sub
Public Sub UpadateChartData()
Dim r As Integer = GetRandom(1, 10)
ChartData.Add(New ChartData() With {.Name = r.ToString, .Votes = r})
End Sub
XAML:
<chartingToolkit:Chart Name="Chart1" Title="Chart1" Width="400" Height="400" >
<chartingToolkit:LineSeries ItemsSource="{Binding}" IndependentValueBinding="{Binding Path=Name}" DependentValueBinding="{Binding Path=Votes}" />
</chartingToolkit:Chart>
But I get this error when I use LineSeries (or any other type of chart):
Cannot modify the logical children for this node at this time because a tree walk is in progress.
Can anyone tell me why I'm getting the error or suggest an alternative approach?
Thanks for any help!
It indeed appears to be a bug in the toolkit, as ColinE mentioned.
I would suggest to take a look at Dynamic Data Display, which really facilitates these kind of things and makes it very easy. They provide a few new objects like ObservableDataSource<T>, and on this you can call source.AppendAsync(Dispatcher, T) which will update the graph.

How to get ElementHost control, given one of WPF control's content

I am trying to get a reference to ElementHost control. For example in the below code I need to initially use the “testImage” content of the WPF user control to lunch the event. The WPF control is added at run-time, so does the ElementHost control, so I can’t use the WPF control’s name or ElementHost’s name.
My logic is to get the parent WPF user control of the “testImage”, and then get the parent ElementHost of the WPF’s user control.
But I am having troubles writing it in code. Please advise. Thanks.
<UserControl x:Class="WpfTest”
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="300" Height="300">
<Grid>
<Label FontSize="10" Height="24" Margin="74,16,0,0" Name="testLabel" VerticalAlignment="Top" />
<Image Name="testImage" Stretch="Uniform" HorizontalAlignment="Left" Width="64" Height="81" VerticalAlignment="Top" Margin="8,0,0,0"/>
</Grid>
</UserControl>
Here is some code that might help you. The key points are:
Name the ElementHost when you create it at runtime
Make use the the help function FindVisualChildByName() to search the WPF tree to get the desired control
I Hope this helps!
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim ElementHost1 As New System.Windows.Forms.Integration.ElementHost
Dim WpfTest1 As New WindowsApplication1.WPFTest
ElementHost1.Dock = DockStyle.Fill
ElementHost1.Name = "ElementHost1"
ElementHost1.Child = WpfTest1
Me.Controls.Add(ElementHost1)
End Sub
Private Sub GetImageReference_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim ElementHost1 As System.Windows.Forms.Integration.ElementHost = Me.Controls("ElementHost1")
Dim TheGrid As System.Windows.Controls.Grid = CType(ElementHost1.Child, WPFTest).MyGrid
Dim ImageTest As System.Windows.Controls.Image = FindVisualChildByName(TheGrid, "testImage")
Stop
End Sub
Public Function FindVisualChildByName(ByVal parent As System.Windows.DependencyObject, ByVal Name As String) As System.Windows.DependencyObject
For i As Integer = 0 To System.Windows.Media.VisualTreeHelper.GetChildrenCount(parent) - 1
Dim child = System.Windows.Media.VisualTreeHelper.GetChild(parent, i)
Dim controlName As String = child.GetValue(System.Windows.Controls.Control.NameProperty)
If controlName = Name Then
Return child
Else
Dim res = FindVisualChildByName(child, Name)
If Not res Is Nothing Then
Return res
End If
End If
Next
Return Nothing
End Function

Resources