How do I get a radio box that permits no selections? - vb.net

I have a pair of radio buttons on top of a panel to function as a radio box, and it is mostly fine, but I need the user to have the option of leaving both of them unchecked (I wish the user to select zero or one of the options). They are both unchecked when the form is displayed, but after the user checks one of them, it is impossible to revert to the original state. I would expect clicking the selected radio box would clear it (I vaguely remember this from my X/Motif days) but that doesn't seem to happen.
How do I program the radio buttons to allow both of them the be unchecked? Or should I be using some other control for this purpose?

There is no built in way to do what you're asking for. It is not that hard to do it our-self. Here's the sample code which shows how to do that.
C# version:
private void Initialize()
{
radioButton1.AutoCheck = false;
radioButton2.AutoCheck = false;
radioButton1.Click += radioButton_Click;
radioButton2.Click += radioButton_Click;
}
void radioButton_Click(object sender, EventArgs e)
{
RadioButton radio = (RadioButton)sender;
radio.Checked = !radio.Checked;
if (!radio.Checked)
{
return;
}
var otherRadios = radio.Parent
.Controls
.OfType<RadioButton>()
.Where(r => r != radio);
foreach (var r in otherRadios)
{
r.Checked = !radio.Checked;
}
}
Vb.net version:(Converted using http://converter.telerik.com/)
Private Sub Initialize()
radioButton1.AutoCheck = False
radioButton2.AutoCheck = False
AddHandler radioButton1.Click, AddressOf radioButton_Click
AddHandler radioButton2.Click, AddressOf radioButton_Click
End Sub
Private Sub radioButton_Click(sender As Object, e As EventArgs)
Dim radio As RadioButton = DirectCast(sender, RadioButton)
radio.Checked = Not radio.Checked
If Not radio.Checked Then
Return
End If
Dim otherRadios = radio.Parent.Controls.OfType(Of RadioButton)().Where(Function(r) r <> radio)
For Each r As var In otherRadios
r.Checked = Not radio.Checked
Next
End Sub

It should be simple if you think hatke.. Create your custom control
Imports System.ComponentModel
Public Class MyRadio
Inherits RadioButton
Private _permitted As Boolean = True
<DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
<Browsable(True)> _
Public Property Permitted() As Boolean
Get
Return _permitted
End Get
Set(ByVal value As Boolean)
_permitted = value
End Set
End Property
Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
If _permitted Then MyBase.OnClick(e)
End Sub
End Class
HOW TO USE IT?
myRadio1.Permitted = False 'Assigning it to false will not allow you to select it.

You can use checkboxes, they can be checked and unchecked.
If you really want to uncheck a radio button then use the code below:
Private Sub RadioButton1_MouseDown(sender As Object, e As MouseEventArgs) Handles RadioButton1.MouseDown
If RadioButton1.Checked = True Then
Dim thr As New Threading.Thread(AddressOf unticker)
thr.Start()
End If
End Sub
Private Sub unticker()
Threading.Thread.Sleep(100)
Do Until RadioButton1.Checked = False
Invoke(Sub() RadioButton1.Checked = False)
Loop
End Sub
Use this for each radiobutton individually

Related

How do I code out with numeric keypads with multi textboxes?

I'm trying to code out a programme where the user sees a form and in that form, there are 2 text boxes and 10 buttons.
Username:
Password:
1 2 3
4 5 6
7 8 9
0
I've tried this code
Private Sub Btn1_Click(sender As Object, e As EventArgs) Handles Btn1.Click
If UsernameTextbox.Focused = True Then
UsernameTextbox.Text = UsernameTextbox.Text + "1"
End If
End Sub
I understand that clicking on Btn1 will steal the focus from the text box. So how can I write the programme?
One option would be to declare a variable of type Control and, in the Leave event handler for each control, assign the sender to that variable. You can then use that variable in the Click event handler of your Button to determine which control had focus and possibly reassign back to that control and then update it appropriately. You can do the lot with two event handlers, e.g.
Private previouslyActiveTextBox As TextBox
Private Sub TextBoxes_Leave(sender As Object, e As EventArgs) Handles TextBox2.Leave,
TextBox1.Leave
previouslyActiveTextBox = DirectCast(sender, TextBox)
End Sub
Private Sub Buttons_Click(sender As Object, e As EventArgs) Handles Button3.Click,
Button2.Click,
Button1.Click
previouslyActiveTextBox.Select()
previouslyActiveTextBox.SelectedText = CStr(DirectCast(sender, Button).Tag)
End Sub
That code handles multiple events with a single method in both cases. It also requires that you assign the number for each Button to the Tag property of that control. Note that it also sets the SelectedText, rather than appending to the Text property. That is more correct because it will add the new text where the caret is actually located and replace text if it is selected.
An even better option might be to use a custom button control that doesn't take focus. Here's one I prepared earlier:
http://www.vbforums.com/showthread.php?459890-Building-Blocks-for-an-On-screen-Keyboard
Items within a ToolStrip do not grab focus when clicked. While the standard ToolStrip usage is as a menu bar, there is nothing that prevents you from using it as a container for buttons laid out in a grid. In fact, the class ToolStrip.LayoutStyle Property allows you select a table style.
The following is a proof-of-concept custom ToolStrip that is prepopulated with the buttons to create a number pad like control. The control has sufficient function to work as intended, but is not locked down to prevent misuse by manipulating the Items collection and other properties.
Public Class NumPadToolstrip : Inherits ToolStrip
Private _ButtonSize As Size = New Size(50, 50)
Private _ButtonMargin As Padding = New Padding(5)
Private _ButtonBackColor As Color = Color.Ivory
Public Sub New()
MyBase.New
LayoutStyle = ToolStripLayoutStyle.Table
Dim settings As TableLayoutSettings = CType(LayoutSettings, TableLayoutSettings)
settings.ColumnCount = 3
settings.RowCount = 4
AddButtons(7, 9)
AddButtons(4, 6)
AddButtons(1, 3)
AddButtons(0, 0)
Dock = DockStyle.None
AutoSize = True
BackColor = Color.LightGray
End Sub
Public Property ButtonSize As Size
Get
Return _ButtonSize
End Get
Set(value As Size)
If value <> _ButtonSize Then
_ButtonSize = value
UpdateButtonSizes()
End If
End Set
End Property
Public Property ButtonMargin As Padding
Get
Return _ButtonMargin
End Get
Set(value As Padding)
If value <> _ButtonMargin Then
_ButtonMargin = value
UpdateMargins()
End If
End Set
End Property
Public Property ButtonBackColor As Color
Get
Return _ButtonBackColor
End Get
Set(value As Color)
If value <> _ButtonBackColor Then
_ButtonBackColor = value
UpdateButtonBackColor()
End If
End Set
End Property
Private Sub AddButtons(start As Int32, [end] As Int32)
For num As Int32 = start To [end]
Dim b As New ToolStripButton With {.Text = num.ToString(),
.Size = ButtonSize,
.Margin = ButtonMargin,
.BackColor = ButtonBackColor,
.AutoSize = False}
AddHandler b.Paint, Sub(sender As Object, e As PaintEventArgs)
With e.Graphics
Dim r As Rectangle = e.ClipRectangle
r.Inflate(-1, -1)
r.Location = Point.Empty
.DrawRectangle(Pens.Black, r)
End With
End Sub
Items.Add(b)
Next
End Sub
Private Sub UpdateButtonSizes()
SuspendLayout()
For Each btn As ToolStripButton In Items.OfType(Of ToolStripButton)
btn.Size = _ButtonSize
Next
ResumeLayout()
End Sub
Private Sub UpdateMargins()
SuspendLayout()
For Each btn As ToolStripButton In Items.OfType(Of ToolStripButton)
btn.Margin = _ButtonMargin
Next
ResumeLayout()
End Sub
Private Sub UpdateButtonBackColor()
SuspendLayout()
For Each btn As ToolStripButton In Items.OfType(Of ToolStripButton)
btn.BackColor = _ButtonBackColor
Next
ResumeLayout()
End Sub
End Class
Add the above class to your project and perform a build operation. The NumPadToolstrip control should then be available in the ToolBox. Add the control to the form and then add a handler for its ItemClicked event to pass the proper text to the TextBox.
Private Sub NumPadToolstrip1_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles NumPadToolstrip1.ItemClicked
Dim tb As TextBoxBase = TryCast(ActiveControl, TextBoxBase)
If tb IsNot Nothing Then tb.SelectedText = e.ClickedItem.Text
End Sub

Highlight scroll bar of textbox [duplicate]

Is it possible to show/hide the scroll bar in a text box only when the line count in the text box is more than the number of lines displayed?
Consider using the RichTextBox -- it has that behavior built in.
Thanks dummy, it works! Here short version of dummy answer in c#
Call this code at the end of your SizeChanged and TextChanged handlers:
Size textBoxRect = TextRenderer.MeasureText(
this.YourTextBox.Text,
this.YourTextBox.Font,
new Size(this.YourTextBox.Width, int.MaxValue),
TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl);
try
{
this.YourTextBox.ScrollBars = textBoxRect.Height > this.YourTextBox.Height ?
ScrollBars.Vertical :
ScrollBars.None;
} catch (System.ComponentModel.Win32Exception)
{
// this sometimes throws a "failure to create window handle" error.
// This might happen if the TextBox is unvisible and/or
// too small to display a toolbar.
}
Public Class TextBoxScrollbarPlugin
Private WithEvents mTarget As TextBox
''' <summary>
''' After the Handle is created, mTarget.IsHandleCreated always returns
''' TRUE, even after HandleDestroyed is fired.
''' </summary>
''' <remarks></remarks>
Private mIsHandleCreated As Boolean = False
Public Sub New(item As TextBox)
mTarget = item
mIsHandleCreated = mTarget.IsHandleCreated
End Sub
Private Sub Update()
If Not mTarget.IsHandleCreated Then
Return
ElseIf Not mIsHandleCreated Then
Return
End If
Dim textBoxRect = TextRenderer.MeasureText(mTarget.Text,
mTarget.Font,
New Size(mTarget.Width, Integer.MaxValue),
TextFormatFlags.WordBreak + TextFormatFlags.TextBoxControl)
Try
If textBoxRect.Height > mTarget.Height Then
mTarget.ScrollBars = ScrollBars.Vertical
Else
mTarget.ScrollBars = ScrollBars.None
End If
Catch ex As System.ComponentModel.Win32Exception
'this sometimes throws a "failure to create window handle"
'error.
'This might happen if the TextBox is unvisible and/or
'to small to display a toolbar.
If mLog.IsWarnEnabled Then mLog.Warn("Update()", ex)
End Try
End Sub
Private Sub mTarget_HandleCreated(sender As Object, e As System.EventArgs) Handles mTarget.HandleCreated
mIsHandleCreated = True
End Sub
Private Sub mTarget_HandleDestroyed(sender As Object, e As System.EventArgs) Handles mTarget.HandleDestroyed
mIsHandleCreated = False
End Sub
Private Sub mTarget_SizeChanged(sender As Object, e As System.EventArgs) Handles mTarget.SizeChanged
Update()
End Sub
Private Sub mTarget_TextChanged(sender As Object, e As System.EventArgs) Handles mTarget.TextChanged
Update()
End Sub
End Class
Private mPlugins As New List(Of Object)
Private Sub Form_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
mPlugins.Add(New TextBoxScrollbarPlugin(txtBoxOne))
mPlugins.Add(New TextBoxScrollbarPlugin(txtBoxTwo))
mPlugins.Add(New TextBoxScrollbarPlugin(txtBoxThree))
End Sub
I've got tnimas solution working in vb. Functions quite well as written and I've not seen the errors.
Private Sub TextBoxSizeChanged(sender As Object, e As EventArgs) Handles Me.SizeChanged
Dim textBoxRect As Size = TextRenderer.MeasureText(TextBox.Text, TextBox.Font, New Size(TextBox.Width, Integer.MaxValue), TextFormatFlags.WordBreak Or TextFormatFlags.TextBoxControl)
Try
TextBox.ScrollBar = If(textBoxRect.Height > TextBox.Height, ScrollBars.Vertical, ScrollBars.None)
Catch ex As Exception
'handle error
End Try
End Sub
I myself tried tnimas' solution but unable to catch the exception, so I use the WinApi to toggle the visible state of scrollbars instead like so:
Size textBoxRect = TextRenderer.MeasureText(YourTextBox.Text, YourTextBox.Font, new Size(YourTextBox.Width, int.MaxValue), TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl);
WinApi.ShowScrollBar(YourTextBox.Handle, (int)WinApi.ScrollBar.SB_VERT, textBoxRect.Height > YourTextBox.Height ? true : false);
This method does not cause the exception, though should note that hiding scrollbars like this will disable scroll messages, but this is fine if you're just hiding the scrollbars for when the text area can't be scrolled anyway.

calling button class in a form in vb.net

I am herewith develop an application but I have created a class which calls button events(i.e. enable or visible)
Public Class ClassfrmLoad
Dim btnAdd As New Button
Dim btnEdit As New Button
Private Sub FormLoad()
Me.btnAdd.Visible = True
Me.btnAdd.Enabled = True
Me.btnEdit.Visible = True
Me.btnEdit.Enabled = False
End Sub
End Class
I am actually created the button events class(classfrmLoad) for the way which buttons should be enabled and visible when each & every form loading.
There are 6 buttons in the forms (frm1, frm2 etc.,) like btnAdd, btnEdit, btnCancel etc., i don't want to display the buttons(visible/enable) while loading the form.
Here is the question:
How can i call this class(classfrmLoad) events to alter (enable/visible) the buttons positioned in the forms(frm1, frm2, etc.,) and how to get the buttons events in those forms?
Dear Sergio,
Thanks for your immediate response. I am missing something and it is not as expected, here is my complete code for the form including yours.
This is the code you suggested for the classfrmLoad:
Public Class ClassfrmLoad
Public Shared Sub FormLoad(ByRef Target As Form)
For Each ctl As Control In Target.Controls
If Not TypeOf ctl Is Button Then Continue For
Dim btn As Button = DirectCast(ctl, Button)
Select Case btn.Name.ToLower()
Case "btnadd"
btn.Visible = True
btn.Enabled = True
Case "btnsave"
btn.Visible = False
btn.Enabled = False
Case "btnedit"
btn.Visible = True
btn.Enabled = True
Case "btncancel"
btn.Visible = True
btn.Enabled = False
Case "btnclose"
btn.Visible = True
btn.Enabled = True
Case "btnupdate"
btn.Visible = False
btn.Enabled = False
Case "btnfind"
btn.Visible = False
btn.Enabled = False
'and so on
End Select
Next
End Sub
End Class
This is the code for the formload event:
Private Sub frmCreate_Unit_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ClassfrmLoad.FormLoad(Me)
'Display software and title of the page
Me.Text = msgCap & " | " & " CREATE UNIT"
Me.lblComp.Text = CompName
Me.stBar_User.Text = frmMain.stBar_User.Text
Me.stBar_UserID.Text = frmMain.stBar_UserID.Text
Me.stBar_G_ID.Text = frmMain.stBar_G_ID.Text
Me.stBar_G_No.Text = frmMain.stBar_G_No.Text
Me.cboUnit.Visible = False
Me.txtUnit_Long.Visible = True
Me.btnfind.Visible = False
Me.txtUnit_ID.Enabled = False
Me.btnadd.Focus()
End Sub
Please help me to sort out this one. Thanks...
Every form in WinForms is a class instance, inherited from Form class.
Because of this, you cannot make static references to it's members from another class, given any Form instance.
Generic class won't cut it either because you're after specific class members.
I would take advantage of the Controls collection and would check it's name and type. Once caught, we can cast the control to button and set it's visibility and access.
For this, you should make small adjustments to your code:
Public Class ClassfrmLoad
Public Shared Sub FormLoad(ByRef Target As Form)
For Each ctl As Control In Target.Controls
If Not TypeOf ctl Is Button Then Continue For
Dim btn As Button = DirectCast(ctl, Button)
Select Case btn.Name.ToLower()
Case "btnadd", "btnedit"
btn.Visible = True
btn.Enabled = True
'and so on
End Select
Next
End Sub
End Class
Changed the FormLoad visibility and access. It should be shared so we don't need to create unnecessary instances of this class
Added a parameter, passe by reference that referrs the target form. This will assure that you can use it on any class that inherits Form class
Iterated the Controls collection and find a candidate based on it's type and name
When found, we cast it to Button and access it's properties normally.
It's just an example, based on your code.
You should now call it on every Form's formload handler, like so:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ClassfrmLoad.FormLoad(Me)
End Sub
Finally I got the solution. It is very simple and any way thanks to sergio.
Here is the complete code.
Public Class ClassfrmLoad
Public Shared Sub formLoad(ByVal btnAdd As Button, ByVal btnEdit As Button, ByVal btnSave As Button, ByVal btnCancel As Button, ByVal btnClose As Button, ByVal btnUpdate As Button, ByVal btnFind As Button)
btnAdd.Visible = True
btnAdd.Enabled = True
btnSave.Visible = False
btnSave.Enabled = False
btnCancel.Visible = True
btnCancel.Enabled = False
btnClose.Visible = True
btnClose.Enabled = True
btnEdit.Visible = True
btnEdit.Enabled = True
btnUpdate.Visible = False
btnUpdate.Enabled = False
btnFind.Visible = False
btnFind.Enabled = False
End Sub
End Class
And calling proceedure in a form like this:
Dim x As New ClassfrmLoad
ClassfrmLoad.formLoad(Me.btnAdd, Me.btnEdit, Me.btnSave, Me.btnCancel, Me.btnClose, Me.btnUpdate, Me.btnFind)

Radiobuttons in different group boxes

Quite a silly question, but still annoying.
The thing is that i have two group boxes where the titles have radiobuttons covering the group box titles.
Something like
(x) I want pizza
*Pizza stuff*
( ) I want Hamburger
*Hamburger stuff*
Since they're now in different group boxes, they can both be selected.
Is there a way to set/force the radiobuttons to be in the same "group"? Like in HTML where you set
name="WhatToEat" value="Pizza" for the first value and then
name="WhatToEat" value="Hamburger"
Or can i set the title for the groupbox to behave like a radio button or something?
Of course i can have the radio button outside the grop boxes, but i think having the titles as radiobuttons just makes the most sense and looks nicer.
If you have all your RadioButtons on a form. You can use a RadioButton variable to mark what is currently checked. Every time user checks a RadioButton, if it's not the currently checked RadioButton, make the currently checked RadioButton unchecked, and set the currently checked RadioButton to that RadioButton.
Here is my code:
public Form1(){
InitializeComponents();
currentChecked = radioButton1;
}
//Suppose the initially checked radio is radioButton1
RadioButton currentChecked;
//This is the CheckedChanged event handler used for all the radiobuttons
private void radioButtonChecked(object sender, EventArgs e)
{
RadioButton r = (RadioButton)sender;
if (r != currentChecked)
{
currentChecked.Checked = false;
currentChecked = r;
}
}
My code is much simpler without using any loop. It costs the additional currentChecked but it's not much.
Hope it helps!
No, it have to in one group ..
But for that case you can control in checked_change event
Private Sub RadioButton2_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButton2.CheckedChanged
RadioButton1.Checked = Not RadioButton2.Checked
End Sub
Private Sub RadioButton1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButton1.CheckedChanged
RadioButton2.Checked = Not RadioButton1.Checked
End Sub
Just move them to the Form at run-time. Use PointToScreen() and PointToClient() to keep them in the same position as you placed them at desing-time. So you'd replace "RadioButton1", "RadioButton2", and "RadioButton3" with your title RadioButtons:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim RadioTitles() As RadioButton = {RadioButton1, RadioButton2, RadioButton3}
For Each rb As RadioButton In RadioTitles
Dim pt As Point = Me.PointToClient(rb.PointToScreen(New Point(0, 0)))
Me.Controls.Add(rb)
rb.Location = pt
rb.BringToFront()
Next
End Sub
*You could put a value into the Tag() property of each RadioButton that should be the "title" and then search for those instead of hard-coding them into the array. Or maybe you could name them a certain way.
EDIT: You could make the "title" RadioButtons enable/disable their associated GroupBoxes when they are checked like this:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim RadioTitles() As RadioButton = {RadioButton1, RadioButton2, RadioButton3}
For Each rb As RadioButton In RadioTitles
rb.Parent.Enabled = False
rb.Tag = rb.Parent
AddHandler rb.CheckedChanged, AddressOf TitleRadioButtons_CheckedChanged
Dim pt As Point = Me.PointToClient(rb.PointToScreen(New Point(0, 0)))
Me.Controls.Add(rb)
rb.Location = pt
rb.BringToFront()
Next
End Sub
Private Sub TitleRadioButtons_CheckedChanged(sender As Object, e As System.EventArgs)
Dim rb As RadioButton = DirectCast(sender, RadioButton)
If Not IsNothing(rb.Tag) AndAlso TypeOf rb.Tag Is Control Then
Dim ctl As Control = DirectCast(rb.Tag, Control)
ctl.Enabled = rb.Checked
End If
End Sub
Unfortunately, that's not how radio buttons work.
As I'm sure you're aware, radio buttons get their grouping from containers. To my knowledge, if you want to be able to accomplish what you're asking, you'll probably need to code a custom solution. For instance, you could place an event handler on each radio button to fire off the same event to uncheck other boxes, e.g.
radioButton1.CheckedChanged += anyRadioButton_CheckedChanged;
radioButton2.CheckedChanged += anyRadioButton_CheckedChanged;
radioButton3.CheckedChanged += anyRadioButton_CheckedChanged;
...
private void anyRadioButton_CheckedChanged(object sender, EventArgs e)
{
foreach (var control in this.Controls)
{
if(control is GroupBox)
{
foreach (var childControl in ((GroupBox)control).Controls)
{
if (childControl is RadioButton && childControl != sender)
{
((RadioButton)childControl).Checked = false;
}
}
}
}
}
You can set text of the GroupBox to empty string and put RadioButton over it. The trick is to put it on form actually but move it the way it looks like part of GroupBox. But this is sufficient only if your group boxes are static and won't be moved. Otherwise it is better to use solution which #matzone proposed. But even in that case you can put all radio buttons in collection in your code and use the only event handler for all of them. Something like
private List<RadioButton> radioButtons;
public YourFormConstructor()
{
InitializeComponent();
radioButtons.Add(radio1);
radioButtons.Add(radio2);
radioButtons.Add(radio3);
foreach (var radio in radioButtons)
radio.CheckedChanged += RadioCheckedChanged;
}
private void CheckedChanged(object sender, EventArgs e)
{
var thisRadio = sender as RadioButton;
if (!thisRadio.Checked)
return;
foreach (var radio in radioButtons)
if (radio != thisRadio)
radio.Checked = false;
}

Disabling checkbox selections in VB .NET 2008 Winform Listview

How do you disable additional checkbox selections/deselections without sacrificing the functionality of the ListView? I know you can call: ListView.Enabled = False, but that also disables any scrolling within it.
For example: I have a timer that starts a backup based on the Listview items that are checked. After a certain time, I don't want the end-user to be able to click on any of the checkboxes within the listview (so I have a set number of items to backup), but I do want them to be able to scroll the list while the backup is being performed. I tried this:
Private Sub clboxOptions_ItemChecked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ItemCheckedEventArgs) Handles clboxOptions.ItemChecked
If backupStarted = True Then
If e.Item.Checked = True Then
e.Item.Checked = False
Else
e.Item.Checked = True
End If
But this doesn't seem to work for me.
Thanks!
JFV
Here is an other method to disable the users click on listviewitem checkbox.
Public Sub ChangeItemCheckState(ByVal val As Boolean, ByVal index As Integer)
If Monitor.TryEnter(Me.Items(index), 10) Then
Try
Me.Items(index).Checked = val
Finally
Monitor.Exit(Me.Items(index))
End Try
End If
End Sub
Public Sub ChangeItemCheckState(ByVal val As Boolean, ByVal item As ListViewItem)
If Monitor.TryEnter(item, 10) Then
Try
item.Checked = val
Finally
Monitor.Exit(item)
End Try
End If
End Sub
Private Sub ListviewOPC_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles Me.ItemCheck
If Monitor.IsEntered(Me.Items(e.Index)) Then
'
Else
'prevent click from users
e.NewValue = e.CurrentValue
End If
End Sub
this method is thread safe. To change the checkedstate of an item you have to call the ChangeItemCheckState methods. If you want to enable/disable the itemcheck by click, you have to add another property.
Private disableUserCheckItem As Boolean
Public Property PreventUserCheckItem() As Boolean
Get
Return disableUserCheckItem
End Get
Set(ByVal value As Boolean)
disableUserCheckItem = value
End Set
End Property
Public Sub ChangeItemCheckState(ByVal val As Boolean, ByVal index As Integer)
If Monitor.TryEnter(Me.Items(index), 10) Then
Try
Me.Items(index).Checked = val
Finally
Monitor.Exit(Me.Items(index))
End Try
End If
End Sub
Public Sub ChangeItemCheckState(ByVal val As Boolean, ByVal item As ListViewItem)
If Monitor.TryEnter(item, 10) Then
Try
item.Checked = val
Finally
Monitor.Exit(item)
End Try
End If
End Sub
Private Sub ListviewOPC_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles Me.ItemCheck
If Monitor.IsEntered(Me.Items(e.Index)) Then
'do nothing or other nessesary things.
Else
'prevent click from users
If PreventUserCheckItem Then
e.NewValue = e.CurrentValue
End If
End If
End Sub
Instead using the built-in CheckBoxes property, you could draw the check boxes yourself.
Google around and find an example of an OwnerDraw ListView. Draw the checkboxes yourself. Add a new property to your ListView (something like ReadOnly). When ReadOnly is true, draw the checkboxes as disabled and ignore the click messages.
You could use ObjectListView (which is a wrapper around a normal .NET ListView). It provides a callback, CheckStatePutter, which is called when the user clicks on a checkbox. In that callback, you can decide whether or not to accept the new checkbox value.
This is a recipe describing this process: How do I use checkboxes in my ObjectListView?
I found out what my issue was. I was using the 'ItemChecked' instead of the 'ItemCheck' Method. The below code works for me:
Private Sub clboxOptions_ItemCheck(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs) Handles clboxOptions.ItemCheck
Try
If backupStarted = True Then
If e.CurrentValue <> e.NewValue Then
e.NewValue = e.CurrentValue
Else
e.NewValue = e.NewValue
End If
End If
End Sub
I want disable CheckBox in Listview. When I click Button Go. I was using the 'ItemChecked' Method. I use code this:
Public Sub CheckBoxChecked(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckedEventArgs)
Try
If bCheckFromEvent Then
bCheckFromEvent = False
Return
End If
If BrunService Then
bCheckFromEvent = True
ListView.Items(e.Item.Index).Checked = Not ListView.Items(e.Item.Index).Checked
End If
Catch ex As Exception
MsgBox("CheckBoxChecked: " & ex.Message, MsgBoxStyle.Critical Or MsgBoxStyle.OkOnly, "ERROR")
End Try
End Sub