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

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()

Related

Unable to find the correct Dispatcher to prevent the "This type of CollectionView does not support changes to from a thread..." Exception

In the code below I am unable to get the WPF Window to be updated from a ansynchronous call. All that is shown is the line "First item". The problem is that the Windowis not launched from a WPF Application, but from a class module. As our main UI application is a VB6 application it launches som WPF elements though calls to a Com visible Net dll. This works very well, but not in the case below.
THE MAIN CONSOLE APPLICATION
Imports Window
Imports System.Windows
Imports System.Threading
Module Module1
Sub Main()
Dim launcher As New WindowLauncher
launcher.LaunchWindow()
Console.WriteLine("Press a key to continue...")
Console.ReadLine()
End Sub
End Module
THE WPF WINDOW LAUNCHER
Imports Window
Public Class WindowLauncher
Public Sub LaunchWindow()
Dim model As New ViewModel
Dim window As New DisplayWindow
model.Dispatcher = window.Dispatcher
window.DataContext = model
window.Show()
model.Collection.Add("Second item.")
model.StartAddingItems()
'window.Close()
End Sub
End Class
THE WPF WINDOW AND ITS VIEWMODEL IN WPF USERCONTROL LIBRARY PROJECT
<Window x:Class="DisplayWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DisplayWindow" Height="300" Width="300">
<Grid>
<ListBox ItemsSource="{Binding Collection}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
Imports System.Collections.ObjectModel
Imports System.Threading
Imports System.Windows.Threading
Public Class ViewModel
Public Sub New()
Collection = New ObservableCollection(Of String)
Collection.Add("First item")
End Sub
Public Property Collection As ObservableCollection(Of String)
Public Property Dispatcher As Dispatcher
Public Sub StartAddingItems()
Dim progress As New Progress(Of String)
AddHandler progress.ProgressChanged, AddressOf ProgressChanged
For i = 1 To 10
DoSomething(progress).Wait()
Next
End Sub
Private _counter As Integer
Private Async Function DoSomething(progress As IProgress(Of String)) As Task
Await Task.Delay(10 * _counter)
_counter += 1
progress.Report(CStr(_counter))
End Function
Private Sub ProgressChanged(sender As Object, e As Object)
Dim text = CStr(e)
Me.Dispatcher.BeginInvoke(Sub() AddToCollection(text), DispatcherPriority.Background)
'The challenge seems to be to find the correct Dispatcher. Now the property is set from the WPF Window, but the code never reaches the AddToCollection method. `
AddToCollection(text)
`This call throws the well known "This type of CollectionView does not support changes..." exception.`
End Sub
Private Sub AddToCollection(text As String)
Collection.Add(String.Format("item {0}", text))
End Sub
End Class
The problem lies in the following calls:
model.Collection.Add("Second item.")
model.StartAddingItems()
This seems to block updates to the user interface.
I moved these calls to the window.Loaded event of the WPF.Form (the form holds a reference to the viewmodel) and I set the viewmodel's Dispatcher to that of the window there.
If you're displaying WPF windows, you really need a separate WPF thread (with an STA main loop):
var thread = new Thread(() =>
{
var application = new Application();
application.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

WPF binded Listbox bug when display 2 items

I have a WPF listbox in my window. In the Load event of the window, i create a List(of Object) and I added some items. At application starts or debug, I can see items.
If I add 1 item on the list, i correctly see 1 only item. If I add 3 or more items, i correctly see 3 or more items. If I add 2 only items, i see 1 only item. Why?
Here is my WPF code
<Window x:Class="Cacatua.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Cacatua;assembly=" >
<Grid>
<ListBox Name="lbSearch" ItemsSource="{Binding}" />
</Grid>
</Window>
And here is my code-behind (same assembly, in Cacatua namespace):
Private myLstSearch As List(Of Object)
Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
myLstSearch = New List(Of Object)
lbSearch.ItemsSource = myLstSearch
Dim myMedia1 as Media1
myMedia1 = New Media1("IdMedia1-A")
myLstSearch.Add(myMedia1)
myMedia1 = New Media1("IdMedia1-B")
myLstSearch.Add(myMedia1)
End Sub
where Media1 is a simple class that contains a string
Public Class Media1
Private myIdTitolo As String
Public ReadOnly Property IDTitolo As String
Get
Return (myIdTitolo)
End Get
End Property
Public Sub New(str As String)
myIdTitolo = str
End Sub
End Class
With this code, I would see a list with this output (there is no datatemplate):
Cacatua.Media1
Cacatua.Media1
but I see only
Cacatua.Media1
I think it's a bug. But am I the first with this problem?
You've got the right idea, but the problem is your ItemsSource doesn't know when to update since you're not using an ObservableCollection. Also there is a timing issue between rendering and loading the window, and I think this has to do with the fact you aren't properly binding your items source.
For starters, try changing the type of myLstSearch to ObservableCollection(Of Media1).
Also, a better way to do this would be to databind it from the XAML directly, so your code-behind would be something like:
Public property MyListSearch As ObservableCollection(Of Media1)
Then your XAML would look like:
<Window x:Class="Cacatua.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Cacatua;assembly=">
<Grid>
<ListBox Name="lbSearch" ItemsSource="{Binding Path=MyListSearch}" />
</Grid>
</Window>
That way, you can simply initialize MyListSearch in your window constructor, and then add elements to it whenever, while your view will automatically update.

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.

Cannot dynamically add new button

I'm just starting to learn VB and Visual Studio and I've run across a problem. I've spent the best part of a day trying to find the answer and I have a horrible feeling that it's going to be something very simple that I've over looked.
I'm working on a WPF in Visual Studio 2010 and am trying to dynamically create a button on the main window when a button is clicked (I know, everything I've read tells me this is pretty basic!) Here's an edited snippet of the code I've written:
Imports System.Data.OleDb
Imports System.Windows.Forms
Imports Excel = Microsoft.Office.Interop.Excel
Class MainWindow
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles edit.Click
...
Dim newButton As New Button
newButton.Text = "New Button"
newButton.Top = 200
newButton.Left = 20
Me.Controls.Add(newButton)
...
End Sub
To my eyes, this looks perfectly simple and correct, but I'm getting an error:
"'Controls' is not a member of 'myApp.MainWindow'."
Has anybody come across this before or know what the problem is? Apologies if this does turn out to be a simple fix :)
The error you are getting is telling you that Controls does not exist within MainWindow. Basically, there is not property by that name accessible from your event handler. If you are working with WPF and MainWindow inherits Window, then you need to set something within the Content property.
The best way to go about this, would be to have some form of container control as the content of the window. You can define this in XAML or in code (via code you should set the Window.Content property). Then, you can add more controls to that container. Suggested containers are Grid, Canvas and StackPanel, etc.
I would suggest something like this:
XAML
<MainWindow ...>
<StackPanel x:Name="ControlContainer">
<Button Content="Click me to create buttons!" Click="CreateButton_Click" />
</StackPanel>
</MainWindow>
Code Behind
Private Sub CreateButton_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim button As New Button()
' Initialize the button
' ...
' Add the button to the stack panel
Me.ControlContainer.Children.Add(button)
End Sub
well MainWindow is not a form. create a new project and copy the same code in a button it will work.
you must find out what is the problem with your form control.
It looks like you are mixing WinForms and WPF coding - these are two different technologies.
This link may help you to add a button at runtime in WPF

Setting User Control's DataContext from Code-Behind

This should be pretty easy, but it throws VS2008 for a serious loop.
I'm trying out WPF with MVVM, and am a total newbie at it although I've been developing for about 15 years, and have a comp. sci. degree. At the current client, I am required to use VB.Net.
I have renamed my own variables and removed some distractions in the code below, so please forgive me if it's not 100% syntactically perfect! You probably don't really need the code to understand the question, but I'm including it in case it helps.
I have a very simple MainView.xaml file:
<Window x:Class="MyApp.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Main Window" Height="400" Width="800" Name="MainWindow">
<Button Name="Button1">Show Grid</Button>
<StackPanel Name="teststack" Visibility="Hidden"/>
</Window>
I also have a UserControl called DataView that consists of a DataGrid:
<UserControl x:Class="MyApp.Views.DataView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfToolkit="http://schemas.microsoft.com/wpf/2008/toolkit" >
<Grid>
<WpfToolkit:DataGrid
ItemsSource="{Binding Path=Entries}" SelectionMode="Extended">
</WpfToolkit:DataGrid>
</Grid>
</UserControl>
The constructor for the DataView usercontrol sets up the DataContext by binding it to a view model, as shown here:
Partial Public Class DataView
Dim dataViewModel As ViewModels.DataViewModel
Public Sub New()
InitializeComponent()
dataViewModel = New ViewModels.DataViewModel
dataViewModel.LoadDataEntries()
DataContext = dataViewModel
End Sub
End Class
The view model for DataView looks like this (there isn't much in ViewModelBase):
Public Class DataViewModel
Inherits ViewModelBase
Public Sub New()
End Sub
Private _entries As ObservableCollection(Of DataEntryViewModel) = New ObservableCollection(Of DataEntryViewModel)
Public ReadOnly Property Entries() As ObservableCollection(Of DataEntryViewModel)
Get
Return _entries
End Get
End Property
Public Sub LoadDataEntries()
Dim dataEntryList As List(Of DataEntry) = DataEntry.LoadDataEntries()
For Each dataentry As Models.DataEntry In dataEntryList
_entries.Add(New DataEntryViewModel(dataentry))
Next
End Sub
End Class
Now, this UserControl works just fine if I instantiate it in XAML. When I run the code, the grid shows up and populates it just fine.
However, the grid takes a long time to load its data, and I want to create this user control programmatically after the button click rather than declaratively instantiating the grid in XAML. I want to instantiate the user control, and insert it as a child of the StackPanel control:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
Dim dataView As New DataView
teststack.Children.Add(dataView)
End Sub
When I do this, as soon as the Button1_Click finishes, my application locks up, starts eating RAM, and hits the CPU about 50%.
Am I not instantiating my UserControl properly? It all seems to come down to the DataContext assignment in DataEntry's constructor. If I comment that out, the app works as expected (without anything in the grid, of course).
If I move this code block into Button1_Click (basically moving DataEntry's constructor code up a level), the app still fails:
dataViewModel = New ViewModels.DataViewModel
dataViewModel.LoadDataEntries()
dataView.DataContext = dataViewModel
I'm stumped. Can anybody give me some tips on what I could be doing wrong, or even how to debug what infinite loop my app is getting itself into?
Many thanks.
The root cause of your issue appears to be either the raw amount of data you're loading or some inefficiency in how you load that data. Having said that, the reason you're seeing the application lock up is that you're locking the UI thread when loading the data.
I believe that in your first case the data loading has been off loaded onto another thread to load the data. In you second example you're instantiating the control on the UI thread and as a result all the constructor and loading logic is performed on the current thread (the UI thread). If you offload this work onto another thread then you should see similar results to the first example.
I eventually gave up on trying to get the DataContext on the UserControl set during instantiation of the UserControl (either in XAML or code). Now I load up the data and set the DataContext of the UserControl in an event in the UserControl (IsVisibleChanged, I believe). When I instantiate the UserControl in XAML, I have it's Visibility set to Hidden. When Button1 is clicked, I set the UserControl's Visibility to Visible. So the UserControl pops into view, and it loads up its data and DataContext is set. Seems to work, but also seems very kludgey. :-( Thanks for the help, folks!
If it's only a matter of your control taking a long time to populate data, you should populate the control on another thread then add it through a delegate:
Since I'm not too good at writing VB.NET, but here's the C# equivalent:
private void Button1_Click(Object sender, RoutedEventArgs e)
{
Thread thr = new Thread(delegate()
{
DataView dataView = new DataView();
this.Dispatcher.BeginInvoke((Action) delegate()
{
teststack.Children.Add(dataView);
});
});
thr.Start();
}

Resources