How to presist XML Document on Post Back?
I have this xmlDocument to persist in SaveViewState() method:
Private _xmlSaveDispatch As XmlDocument = New XmlDocument
In my Page_Load...
If Not IsPostBack Then
Me._xmlSaveDispatch = New XmlDocument
Private Property XMLSaveDispatch As XmlDocument
Get
Return _xmlSaveDispatch
End Get
Set(value As XmlDocument)
_xmlSaveDispatch = value
End Set
End Property
Button Click Event:
Protected Sub dispatchButton_OnSave(sender As Object, e As EventArgs) _
Handles dispatchButtons.SaveDispatch
XMLSaveDispatch = _objDispatchInfo.GetSaveXML()
End Sub
I am writing a C# application and ran into the same issue (the asp:Xml tag does not persist between postbacks). Here is my code to persist it in C#:
//.aspx Presentation
<asp:Xml ID="xmlFormDisplay" runat="server"></asp:Xml>
//.aspx.cs Code Behind
private string formXSLT
{
get { return ViewState["FormXSLT"].ToString(); }
set { ViewState["FormXSLT"] = value; }
}
private string formXML
{
get { return ViewState["FormXML"].ToString(); }
set { ViewState["FormXML"] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
...
}
xmlFormDisplay.TransformSource = formXSLT;
xmlFormDisplay.DocumentContent = formXML;
}
I'm not much of a VB developer, but this ought to work (or be pretty close):
//.aspx Presentation
<asp:Xml ID="xmlFormDisplay" runat="server"></asp:Xml>
//.aspx.vb Code Behind
Private Property FormXSLT As String
Get
Return ViewState["FormXSLT"].ToString()
End Get
Set(value As String)
ViewState["FormXSLT"] = value
End Set
End Property
Private Property FormXML As String
Get
Return ViewState["FormXML"].ToString()
End Get
Set(value As String)
ViewState["FormXML"] = value
End Set
End Property
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
...
End If
xmlFormDisplay.TransformSource = formXSLT
xmlFormDisplay.DocumentContent = formXML
End Sub
Related
I'm new to vb.net and trying to build a win CE app in vb.net. The sdk of the handheld device is in C# which I converted with an online converter to vb.net.
Below is the C# code:
public class DecodeEventArgs : EventArgs
{
private string barcode;
private byte type;
public DecodeEventArgs(string barcodeData, byte typeData)
{
barcode = barcodeData;
type = typeData;
}
public string Barcode
{
get { return barcode; }
set { barcode = value; }
}
public byte Type
{
get { return type; }
set { type = value; }
}
}
Converted to vb.net as:
Public Class DecodeEventArgs
Inherits EventArgs
Public barcode As String
Public type As Byte
Public Sub New(ByVal barcodeData As String, ByVal typeData As Byte)
barcode = barcodeData
type = typeData
End Sub
Public Property pBarcode() As String
Get
Return barcode
End Get
Set(ByVal value As String)
barcode = value
End Set
End Property
Public Property pType() As Byte
Get
Return type
End Get
Set(ByVal value As Byte)
type = value
End Set
End Property
End Class
In my conversion from C# I added a 'p' to the name of the Properties as you see in my vb.net code because I had a error that said
Barcode is already declared as a public string in this class
I'm not sure if that is part of my problem but my real issue is, on a form they used .BeginInvoke to call the class with this code:
void scanner_DecodeEvent(object sender, DecodeEventArgs e)
{
Win32.sndPlaySound(Properties.Resources.Scan, Win32.SND_ASYNC | Win32.SND_MEMORY);
this.BeginInvoke((Action<string>)delegate(string barcode)
{
scanCount = 0;
ListViewItem item = new ListViewItem(new string[] { barcode });
lstView.Items.Insert(0, item);
}, e.Barcode);
}
Which I converted to vb.net as:
Private Sub scanner_DecodeEvent(ByVal sender As Object, ByVal e As DecodeEventArgs)
PlaySound()
Me.BeginInvoke(DirectCast(Barcode As String) )
scanCount = 0
Dim item As New ListViewItem(New String() {barcode})
lstView.Items.Insert(0, item)
End Sub
Which gives me an error about Barcode not being declared. This is where I'm stuck. Thanks for your assistance in advance
That C# snippet creates an anonymous method which it invokes to perform the actions on the UI thread, and it sends e.Barcode as a parameter. Your VB.NET conversion only tries to invoke some strange, and incomplete, use of DirectCast. DirectCast is not needed in the VB.NET conversion as you don't have any delegate keyword which you must cast to a delegate method.
Your most simple solution would be to use a Lambda method:
Me.BeginInvoke(Sub() 'Lambda anonymous method.
scanCount = 0
Dim item As New ListViewItem(New String() {e.Barcode})
lstView.Items.Insert(0, item)
End Sub)
EDIT:
Since you get errors when using the lambda expression I assume you target .NET Framework 3.5 or lower. For that matter it gets a bit more complicated as you must now put the code in a different method:
Private Sub AddBarcode(ByVal Barcode As String)
scanCount = 0
Dim item As New ListViewItem(New String() {Barcode})
lstView.Items.Insert(0, item)
End Sub
Then you must declare your own delegate method which you can use to perform the invocation:
Delegate Sub AddBarcodeDelegate(ByVal Barcode As String)
Private Sub scanner_DecodeEvent(ByVal sender As Object, ByVal e As DecodeEventArgs)
Me.BeginInvoke(New AddBarcodeDelegate(AddressOf AddBarcode), e.Barcode)
End Sub
I want change a textbox value, but this code doesn't work. I see only the last value.
If you want to help me copy and paste the code .
Thanks a lot
This is XAML
<TextBox HorizontalAlignment="Left" Height="46"
Margin="4,4,4,4" VerticalAlignment="Top" Width="162"
Text="{Binding Path=Msg,
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
This is VB code.
Imports System.Threading
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System
Class MainWindow
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
Dim x As New Abc
Me.DataContext = x
End Sub
End Class
Public Class Abc
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private Sub OnPropertyChanged(ByVal info As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub
Protected Sub OnNotifyPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Private Property _Msg As String
Public Property Msg As String
Get
Return _Msg
End Get
Set(value As String)
_Msg = value
OnPropertyChanged("Msg")
End Set
End Property
Private m_ButtonCommand As ICommand
Public Property ButtonCommand() As ICommand
Get
Return m_ButtonCommand
End Get
Set(value As ICommand)
m_ButtonCommand = value
End Set
End Property
Public Sub displayMessage(ByVal param As Object)
Msg = "How"
System.Threading.Thread.Sleep(1000)
Msg = "Are"
System.Threading.Thread.Sleep(1000)
Msg = "you"
System.Threading.Thread.Sleep(1000)
Msg = "?"
System.Threading.Thread.Sleep(1000)
End Sub
Private Function CandisplayMessage(ByVal param As Object) As Boolean
Return True
End Function
Public Sub New()
m_ButtonCommand = New DelegateCommand(AddressOf displayMessage, AddressOf CandisplayMessage)
End Sub
End Class
Public Class DelegateCommand
Implements ICommand
Private m_canExecute As Func(Of Object, Boolean)
Private m_executeAction As Action(Of Object)
Private m_canExecuteCache As Boolean
Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) Implements ICommand.CanExecuteChanged
Public Sub New(ByVal executeAction As Action(Of Object), ByVal canExecute As Func(Of Object, Boolean))
Me.m_executeAction = executeAction
Me.m_canExecute = canExecute
End Sub
Public Function CanExecute(ByVal parameter As Object) As Boolean Implements ICommand.CanExecute
Dim temp As Boolean = m_canExecute(parameter)
If m_canExecuteCache <> temp Then
m_canExecuteCache = temp
RaiseEvent CanExecuteChanged(Me, New EventArgs())
End If
Return m_canExecuteCache
End Function
Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
m_executeAction(parameter)
End Sub
End Class
.............................................
When you use Thread.Sleep on UI Thread you block the UI thread, So nothing can happen in UI. If you want to show a 1 second wait after each message you have two choices.
1 - Using the Delay command in an Async method. https://msdn.microsoft.com/en-us/library/hh194873(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-4
2 - Using a dispatcher frame, which can let the dispatcher work while your method waits. http://www.codeproject.com/Articles/152137/DispatcherFrame-Look-in-Depth
Unfortunately I'm not a VB programmer, But the code in c# would be like this.
Async Sample:
public Task displayMessage(object param){
Msg = "How";
await Task.Delay(1000);
Msg = "Are";
await Task.Delay(1000);
Msg = "you";
await Task.Delay(1000);
Msg = "?";
await Task.Delay(1000);
}
DispatcherFrame sample:
public void displayMessage(object param){
Msg = "How";
Wait(1000);
Msg = "Are";
Wait(1000);
Msg = "you";
Wait(1000);
Msg = "?";
Wait(1000);
}
public void Wait(int sleep)
{
var dFrame = new DispatcherFrame();
ThreadPool.QueueUserWorkItem(state => {
Thread.Sleep(sleep);
dFrame.Continue = false;
});
Dispatcher.PushFrame(dFrame);
}
enter code hereGiven this exmample:
Public Enum Gender
Masculine
Femenine
End Enum
public class ViewModel
private _gender as Gender
Public Property Gender() As Gender
Get
Return _gender
End Get
Set(ByVal value As Gender)
_gender = value
End Set
End Property
end class
Private Sub Form_Load
cmbGender.DataSource = [Enum].GetValues(GetType(Enums.Sexo)) //combobox shows gender ok
cmbGender.DataBindings.Add(New Binding("SelectedItem",ViewModel , "Gender", False, DataSourceUpdateMode.OnPropertyChanged))
end sub
Combobox use ViewModel getter to set its SelectedItem as soon as the Databindings.Add executes but never use the setter when SelectedItem change in the User Interface.
What I am doing wrong?
EDIT
Thanks to Sriram Sakthivel to enlighten me and check combobox events. The final situation is:
Using SelectedItem, DataSourceUpdateMode.OnValidation and combobox.causesValidation = true works when LostFocus raises. If you need onPropertyChanged you should use SelectedIndex and the Sriram Sakthivel's code below.
It will be updated in LostFocus event of ComboBox because SelectedItem doesn't raise change notification (which is necessary for immediate update).
As a workaround you can use SelectedIndex property, which publishes change notification via SelectedIndexChanged event. But there is a problem, SelectedIndex is of type Int32 you need to convert it to Gender and vice versa.
Here's how you'll do that: C# version
private void SetupBinding()
{
var binding = new Binding("SelectedIndex", model, "Gender", true, DataSourceUpdateMode.OnPropertyChanged);
binding.Format += binding_Format;
binding.Parse += binding_Parse;
comboBox1.DataBindings.Add(binding);
}
void binding_Parse(object sender, ConvertEventArgs e)
{
if (e.DesiredType == typeof(Gender))
{
e.Value = comboBox1.Items[(int)e.Value];
}
}
void binding_Format(object sender, ConvertEventArgs e)
{
if (e.DesiredType == typeof(int))
{
e.Value = comboBox1.Items.IndexOf(e.Value);
}
}
Am poor in Vb.net. So I used code converter to convert it to vb.net from c#.
Private Sub SetupBinding()
Dim binding = New Binding("SelectedIndex", model, "Gender", True, DataSourceUpdateMode.OnPropertyChanged)
AddHandler binding.Format, AddressOf binding_Format
AddHandler binding.Parse, AddressOf binding_Parse
comboBox1.DataBindings.Add(binding)
End Sub
Private Sub binding_Parse(sender As Object, e As ConvertEventArgs)
If e.DesiredType = GetType(Gender) Then
e.Value = comboBox1.Items(CInt(e.Value))
End If
End Sub
Private Sub binding_Format(sender As Object, e As ConvertEventArgs)
If e.DesiredType = GetType(Integer) Then
e.Value = comboBox1.Items.IndexOf(e.Value)
End If
End Sub
I'm trying to create a multithreaded program to poll machines for data but I can't seem to get it working correctly. The code below is working and is creating 4 threads as it should but the flow of the code seems to happen in series and on the main UI thread.
What I'm trying to achieve is for each row of the datagrid to update simultaneously without locking up the UI.
Below is a dumbed down version of what I have but it serves to demonstrate the problem.
For info the 'testclass' is a class used as an instance of a machine with each class element representing a property of a machine.
Hope I've given enough info to explain the problem. Thanks in advance.
Ps I shouldn't need to refresh form should I?
Imports System.Threading
Public Class TestForm
Public threadcount As Integer
Public Delegate Sub testclassDelegate(test As Object)
Private Class testclass
Public index As Integer
Public TestVal1 As Integer = 100
Public TestVal2 As Integer = 200
Public TestVal3 As Integer = 300
Public TestVal4 As Integer = 400
Public TestVal5 As Integer = 500
Public TestVal6 As Integer = 600
Public testDel As testclassDelegate
End Class
Private Sub TestForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For i As Integer = 0 To 3
DataGridView1.Rows.Add()
DataGridView1.Rows(i).Cells(0).Value = i + 1
Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For i As Integer = 0 To 3
DataGridView1.Rows(i).Cells(1).Value = ""
DataGridView1.Rows(i).Cells(2).Value = ""
DataGridView1.Rows(i).Cells(3).Value = ""
DataGridView1.Rows(i).Cells(4).Value = ""
DataGridView1.Rows(i).Cells(5).Value = ""
DataGridView1.Rows(i).Cells(6).Value = ""
Next
Poll_FreeThread()
End Sub
Private Sub Poll_FreeThread()
For i As Integer = 0 To DataGridView1.Rows.Count - 1
Dim test As New testclass
test.index = i
test.testDel = AddressOf UIUpdate
Interlocked.Increment(threadcount)
Me.Label2.Text = threadcount
Try
Dim thPoll As New Thread(Sub() invokeUIUpdate(test))
thPoll.IsBackground = True
thPoll.Priority = ThreadPriority.BelowNormal
thPoll.Start()
Catch ex As Exception
MsgBox(ex.Message)
End Try
Next
End Sub
Public Sub invokeUIUpdate(test As Object)
If DataGridView1.InvokeRequired Then
DataGridView1.Invoke(New testclassDelegate(AddressOf UIUpdate), test)
Else
UIUpdate(test)
End If
End Sub
Public Sub UIUpdate(test As Object)
Thread.Sleep(test.index * 100)
DataGridView1.Rows(test.index).Cells(1).Value = test.TestVal1
Me.Refresh()
Thread.Sleep(100)
DataGridView1.Rows(test.index).Cells(2).Value = test.TestVal2
Me.Refresh()
Thread.Sleep(100)
DataGridView1.Rows(test.index).Cells(3).Value = test.TestVal3
Me.Refresh()
Thread.Sleep(100)
DataGridView1.Rows(test.index).Cells(4).Value = test.TestVal4
Me.Refresh()
Thread.Sleep(100)
DataGridView1.Rows(test.index).Cells(5).Value = test.TestVal5
Me.Refresh()
Thread.Sleep(100)
DataGridView1.Rows(test.index).Cells(6).Value = test.TestVal6
Me.Refresh()
Interlocked.Decrement(threadcount)
Me.Label2.Text = threadcount
End Sub
End Class
Run your code a little bit different, This is how the Structure should look like for Multithreading in vb.net ( it has something to do with Vb.net not passing Namespaces into Models from what i Understand )
This would be your startThread from MainThread in load or w/e have you
Private Sub DoSomethingSimple()
Dim DoSomethingSimple_Thread As New Thread(AddressOf DoSimple)
DoSomethingSimple_Thread.Priority = ThreadPriority.AboveNormal
DoSomethingSimple_Thread.Start(Me)
End Sub
This would be the actual thread Itself ( new model / class or in the same class )
Private Sub DoSimple(beginform As Form)
'Do whatever you are doing that has nothing to do with ui
'For UI calls use the following
SomethingInvoked(PassibleVariable, beginform)
End Sub
Write a Delegate and Invoke Method for Each Call to the Main Thread.
Delegate Sub SomethingInvoked_Delegate(s As Integer, beginform As Form)
Sub SomethingInvoked_Invoke(ByVal s As Integer, beginform As Form)
If beginform.NameOfControlYouAreUpdating.InvokeRequired Then ' change NameOfControlYouAreUpdating to the Name of Control on the form you wish to update
Dim d As New SomethingInvoked_Delegate(AddressOf SomethingInvoked_Invoke)
beginform.Invoke(d, New Object() {s, beginform})
Else
'Do something...
beginform.NameOfControlYouAreUpdating.Condition = Parameter
End If
End Sub
This is tested ( non hanging ) way of writing Threads in vb.net
If you need further help implementing your code to this Template let me know :P
You can use timer and backgroundworker with event of DoWorkEventHandler and RunWorkerCompletedEventHandler.
Example: C# example:
private void Button1_Click(object sender, EventArgs e)
{
workerThreadForLetters.WorkerReportsProgress = true; workerThreadForLetters.WorkerSupportsCancellation = true;
workerThreadForLetters.DoWork -= new DoWorkEventHandler(workerThreadForLetters_DoWork);
workerThreadForLetters.DoWork += new DoWorkEventHandler(workerThreadForLetters_DoWork);
workerThreadForLetters.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(workerThreadForLetters_RunWorkerCompleted);
workerThreadForLetters.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workerThreadForLetters_RunWorkerCompleted);
}
private void workerThreadForLetters_DoWork(object sender, DoWorkEventArgs e)
{
//DO SOMETHING
}
private void workerThreadForLetters_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//DO AS REQUIRED
Timer1.enable = false;
}
private void tmCollectionLettersUpdate_Tick(object sender, EventArgs e)
{
//Content update like % of data progressed or any.
}
Is there a Tag for an Item in the CheckedListBox? Or something similar? I would like to be able to store and ID associated with the item that I'm displaying.
You don't need a Tag property. The control accepts any object, that means you don't have to put just strings in it. Make a class that has a string (and overrridden ToString()) and any other data members you need.
Public Class Form1
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
MyBase.OnLoad(e)
CheckedListBox1.Items.Add(New MyListBoxItem() With {.Name = "One", .ExtraData = "extra 1"})
CheckedListBox1.Items.Add(New MyListBoxItem() With {.Name = "Two", .ExtraData = "extra 2"})
End Sub
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
For Each obj As Object In CheckedListBox1.CheckedItems
Dim item As MyListBoxItem = CType(obj, MyListBoxItem)
MessageBox.Show(String.Format("{0}/{1} is checked.", item.Name, item.ExtraData))
Next
End Sub
End Class
Public Class MyListBoxItem
Private _name As String
Private _extraData As String
Public Property Name As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
Public Property ExtraData As String
Get
Return _extraData
End Get
Set(ByVal value As String)
_extraData = value
End Set
End Property
Public Overrides Function ToString() As String
Return Name
End Function
End Class
(The overridden ToString() dictates what will be displayed in the box.)
You can inherit your own control from CheckedListBox and create a property, in C# it would be like this, the rest of the functionality remains the same as it is inherited so no further additional code required:
public class MyCheckedListbox : System.Windows.Forms.CheckedListBox{
private object thisObj;
public object Tag{
get{ return this.thisObj; }
set{ this.thisObj = value; }
}
}
Edit: Decided to include the VB.NET version for everyone's benefit also...
Public Class MyCheckedListBox Inherits System.Windows.Forms.CheckedListBox
Private thisObj As Object
Public Property Tag As Object
Get
Tag = thisObj
End Get
Set (objParam As Object)
thisObj = objParam
End Set
End Property
End Class
Of course, this is plain and uses boxing but works nicely...
Hope this helps
Translation of tommieb75 answer to VB.NET:
Public Class MyCheckedListbox
Inherits System.Windows.Forms.CheckedListBox
Private thisObj As Object
Public Property Tag() As Object
Get
Return Me.thisObj
End Get
Set(ByVal value As Object)
Me.thisObj = value
End Set
End Property
End Class
I use the translator at www.developerfusion.com/tools