How to remove all event handlers from a control in VB.NET - c#-to-vb.net

I found this very interessting Code here. I tried to translate it to VB.NET, but I am not able to. I want to remove all Handlers for the event 'click' of a known button.
Can anybody help me and translate it to VB.NET?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
button1.Click += button1_Click;
button1.Click += button1_Click2;
button2.Click += button2_Click;
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Hello");
}
private void button1_Click2(object sender, EventArgs e)
{
MessageBox.Show("World");
}
private void button2_Click(object sender, EventArgs e)
{
RemoveClickEvent(button1);
}
private void RemoveClickEvent(Button b)
{
FieldInfo f1 = typeof(Control).GetField("EventClick",
BindingFlags.Static | BindingFlags.NonPublic);
object obj = f1.GetValue(b);
PropertyInfo pi = b.GetType().GetProperty("Events",
BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList list = (EventHandlerList)pi.GetValue(b, null);
list.RemoveHandler(obj, list[obj]);
}
}
}

This is a direct translation into VB syntax, as per the OPs request.
Imports System.Reflection ' Required if not already in your code
Imports System.ComponentModel
Partial Public Class Form1
Inherits Form
Public Sub New()
InitializeComponent()
AddHandler button1.Click, AddressOf button1_Click
AddHandler button1.Click, AddressOf button1_Click2
AddHandler button2.Click, AddressOf button2_Click
End Sub
Private Sub button1_Click(sender As Object, e As EventArgs)
MessageBox.Show("Hello")
End Sub
Private Sub button1_Click2(sender As Object, e As EventArgs)
MessageBox.Show("World")
End Sub
Private Sub button2_Click(sender As Object, e As EventArgs)
RemoveClickEvent(button1)
End Sub
Private Sub RemoveClickEvent(b As Button)
Dim f1 As FieldInfo = GetType(Control).GetField("EventClick", BindingFlags.Static Or BindingFlags.NonPublic)
Dim obj As Object = f1.GetValue(b)
Dim pi As PropertyInfo = b.GetType().GetProperty("Events", BindingFlags.NonPublic Or BindingFlags.Instance)
Dim list As EventHandlerList = DirectCast(pi.GetValue(b, Nothing), EventHandlerList)
list.RemoveHandler(obj, list(obj))
End Sub
End Class
It works fine, provided of course the form has button1 and button2 dropped onto it.
The thing that makes people reject your question (aside from #phaedra 's perfectly valid comments) is that there is little point in this code. The function RemoveHandler can be used instead.

Related

UI Freezes When Try to Update textbox in wpf

I have a code that has a text box and a button, when i press the button, the code update the text box and after words sleep for 5 seconds, in those seconds the ui is freezing
I tried with delegates, and threading but nothing works
This is the code with delegates:
MainWindow.vb
Class MainWindow
Delegate Sub MySubDelegate(ByVal x As String)
Private m_engine As Engine
Public Sub New()
m_engine = New Engine(AddressOf WriteToLog)
InitializeComponent()
Me.DataContext = m_engine.GetViewModel()
End Sub
Public Sub WriteToLog(str As String)
Dim vv As ViewModel = CType(DataContext, ViewModel)
vv.Log = str
End Sub
Private Sub clicked(sender As Object, e As RoutedEventArgs)
m_engine.TimingRecord()
End Sub
End Class
Engine.vb
Private m_viewModel As New ViewModel
Private _msd As MainWindow.MySubDelegate
Public Sub New()
End Sub
Sub New(msd As MainWindow.MySubDelegate)
_msd = msd
End Sub
Public Function GetViewModel() As ViewModel
Return m_viewModel
End Function
Public Sub TimingRecord()
_msd("aaaaa")
SetText()
End Sub
Public Sub SetText()
Thread.Sleep(5000)
End Sub
viewModel.vb
Public Class ViewModel
Implements INotifyPropertyChanged
Private m_log As String
Public Property Log As String
Get
Return m_log
End Get
Set(value As String)
m_log = value
End Set
End Property
Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
Private Sub NotifyPropertyChanged(Optional ByVal propertyName As String = Nothing)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
End Class
This is the code with thread:
MainWindow.vb
Delegate Sub MySubDelegate(ByVal x As String)
Private m_engine As Engine
Public Sub New()
m_engine = New Engine(AddressOf WriteToLog)
InitializeComponent()
Me.DataContext = m_engine.GetViewModel()
End Sub
Public Sub WriteToLog(str As String)
Me.Dispatcher.Invoke(Sub() CType(DataContext, ViewModel).Log = str)
'Dim vv As ViewModel = CType(DataContext, ViewModel)
'vv.Log = str
End Sub
Private Sub clicked(sender As Object, e As RoutedEventArgs)
m_engine.TimingRecord()
End Sub
Engine.vb
Public Class Engine
Private m_viewModel As New ViewModel
Private m_thread As Thread
Private _msd As MainWindow.MySubDelegate
Public Sub New(msd As MainWindow.MySubDelegate)
_msd = msd
End Sub
Public Function GetViewModel() As ViewModel
Return m_viewModel
End Function
Public Sub TimingRecord()
m_thread = New Thread(AddressOf DoRecordThread)
m_thread.IsBackground = True
m_thread.Start("aa")
SetText()
End Sub
Public Sub SetText()
Thread.Sleep(5000)
End Sub
Private Sub DoRecordThread(str As String)
_msd(str)
'm_viewModel.Log = str
End Sub
End Class
The ViewModel Stay The same. I'm using wpf so i bind the Log into the textbox and with simple code it works.
Thank you all in advance.
Thread.Sleep causing the issue. It blocks the UI thread that makes the UI frozen.
Have the long running task in different thread and once completed Update the UI(TextBox) with Application.Current.Dispatcher.
Sample Code to update the UI from background thread with Dispatcher :
Application.Current.Dispatcher.Invoke(new Action(() => { Textbox1.Text = result; }))
This is not a right way but I hope this is what you are looking for.
Update
Also, there is another way, you can use builtin BackgroundWorker.
//Add the namespace
using System.ComponentModel;
//Declare
private readonly BackgroundWorker worker = new BackgroundWorker();
//Initialize
worker.DoWork += worker_DoWork;
worker.ProgressChanged += worker_ProgressChanged;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
//method declaration
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
worker.ReportProgress(0, "Process started");
// run all background tasks here
}
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Progress update with e.UserState.ToString();
}
private void worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
//update ui once worker complete his work
}
//Invoke
worker.RunWorkerAsync();
The problem solved by put the thread.sleep but very foolish of me in the viewmodel class i accidently delete the property changed now it is working perfectly thank you all for helping

How to detect a workstation lock

I'm developing an application and I'm trying to detect when the workstation gets locked, for example by the user pressing the Windows + L keys.
I know that the lock event has the value
WTS_SESSION_LOCK 0x7
But i don't know how to use it. I've searched the web but found nothing.
You should use the SystemEvents class in the Microsoft.Win32 namespace, especially the SystemEvents.SessionSwitch event.
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; // Subscribe to the SessionSwitch event
static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
if (e.Reason == SessionSwitchReason.SessionLock)
// Add your session lock "handling" code here
}
Update
If you need to have this event activated from the program startup in a Winforms application:
static class Program
{
[STAThread]
private static void Main()
{
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; // Subscribe to the SessionSwitch event
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
if (e.Reason == SessionSwitchReason.SessionLock)
// Add your session lock "handling" code here
}
}
Finnallly managed to do it on VB :D
First you need to import the libs:
Imports System
Imports Microsoft.Win32
Imports System.Windows.Forms
Then you add the handler:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddHandler SystemEvents.SessionSwitch, AddressOf SessionSwitch_Event
End Sub
Finnally you create the sub that captures it:
Private Sub SessionSwitch_Event(ByVal sender As Object, ByVal e As SessionSwitchEventArgs)
If e.Reason = SessionSwitchReason.SessionLock Then
MsgBox("Locked")
End If
If e.Reason = SessionSwitchReason.SessionUnlock Then
MsgBox("Unlocked")
End If
End Sub
Last you remove the handler:
Private Sub closing_event(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
RemoveHandler SystemEvents.SessionSwitch, AddressOf SessionSwitch_Event
End Sub

Is there a way to prevent a user selecting another row when DataGrid is in edit mode?

I want, that if a cell/row goes to edit mode, then, if the user attempts to select a different row, it should try to commit that row, if the row is not committed sucessfully, it should decline the selection request and the editing row should remain selected and in edit mode.
Do you have experience with a good helper for it? any good workaround?
NOTE: I've been struggling with this issue for a long time and already got some experience, so please post only working examples, not random thoughts.
The code bellow is includes extension from here (code normalized to fit StackOverflow screen witdh, sorry).
Imports System.ComponentModel
Imports System.Windows.Threading
Namespace Components
Public NotInheritable Class DataGridSelectionChangingBehavior
Public Shared Function GetEnableSelectionChanging(
ByVal element As DataGrid) As Boolean
If element Is Nothing Then Throw New ArgumentNullException("element")
Return element.GetValue(EnableSelectionChangingProperty)
End Function
Public Shared Sub SetEnableSelectionChanging(
ByVal element As DataGrid, ByVal value As Boolean)
If element Is Nothing Then Throw New ArgumentNullException("element")
element.SetValue(EnableSelectionChangingProperty, value)
End Sub
Public Shared ReadOnly EnableSelectionChangingProperty As _
DependencyProperty =
DependencyProperty.RegisterAttached("EnableSelectionChanging",
GetType(Boolean),
GetType(DataGridSelectionChangingBehavior),
New FrameworkPropertyMetadata(False,
New PropertyChangedCallback(
AddressOf EnableSelectionChanging_PropertyChanged)))
Public Shared Sub AddSelectionChangingHandler(
ByVal element As DataGrid, handler As SelectionChangingEventHandler)
If element IsNot Nothing Then _
element.AddHandler(
DataGridSelectionChangingBehavior.SelectionChangingEvent, handler)
End Sub
Public Shared Sub RemoveSelectionChangingHandler(
ByVal element As DataGrid, handler As SelectionChangingEventHandler)
If element IsNot Nothing Then _
element.RemoveHandler(
DataGridSelectionChangingBehavior.SelectionChangingEvent, handler)
End Sub
Public Shared ReadOnly SelectionChangingEvent As RoutedEvent =
EventManager.RegisterRoutedEvent("SelectionChanging",
RoutingStrategy.Bubble,
GetType(SelectionChangingEventHandler),
GetType(DataGridSelectionChangingBehavior))
Private Shared Sub EnableSelectionChanging_PropertyChanged(
ByVal sender As Object, ByVal e As DependencyPropertyChangedEventArgs)
Dim dataGrid = DirectCast(sender, DataGrid)
If CBool(e.NewValue) Then
AddHandler dataGrid.PreparingCellForEdit,
AddressOf DataGrid_PreparingCellForEdit
AddHandler dataGrid.SelectionChanged,
AddressOf DataGrid_SelectionChanged
Else
RemoveHandler dataGrid.PreparingCellForEdit,
AddressOf DataGrid_PreparingCellForEdit
RemoveHandler dataGrid.SelectionChanged,
AddressOf DataGrid_SelectionChanged
RecentColumn.Remove(dataGrid)
End If
End Sub
Private Shared Sub DataGrid_SelectionChanged(
ByVal sender As Object, ByVal e As SelectionChangedEventArgs)
If e.RemovedItems.Count = 0 Then Exit Sub
Dim dataGrid = DirectCast(sender, DataGrid)
Dim removed = e.RemovedItems(0)
Dim row = dataGrid.GetContainerFromItem(Of DataGridRow)(removed)
Dim scea As New SelectionChangingEventArgs(row,
DataGridSelectionChangingBehavior.SelectionChangingEvent, dataGrid)
dataGrid.RaiseEvent(scea)
If scea.Cancel Then
RemoveHandler dataGrid.SelectionChanged,
AddressOf DataGrid_SelectionChanged
Dim operation = dataGrid.Dispatcher.BeginInvoke(
Sub()
dataGrid.SelectedItem = removed
Dim column As DataGridColumn = Nothing
If RecentColumn.TryGetValue(dataGrid, column) Then
Dim cellsPanel =
row.GetVisualDescendant(Of DataGridCellsPanel)().
Children.Cast(Of DataGridCell)()
Dim recentCell =
If(cellsPanel.SingleOrDefault(
Function(cell) cell.Column Is column),
cellsPanel.FirstOrDefault)
If recentCell IsNot Nothing Then
recentCell.IsEditing = True
Keyboard.Focus(recentCell)
End If
End If
End Sub,
DispatcherPriority.ContextIdle)
AddHandler operation.Completed,
Sub(s, ea) AddHandler dataGrid.SelectionChanged,
AddressOf DataGrid_SelectionChanged
End If
End Sub
Private Shared m_RecentColumn As Dictionary(Of DataGrid, DataGridColumn)
Public Shared ReadOnly Property RecentColumn() As Dictionary(Of DataGrid,
DataGridColumn)
Get
If m_RecentColumn Is Nothing Then m_RecentColumn =
New Dictionary(Of DataGrid, DataGridColumn)()
Return m_RecentColumn
End Get
End Property
Private Shared Sub DataGrid_PreparingCellForEdit(
ByVal sender As Object, e As DataGridPreparingCellForEditEventArgs)
Dim dataGrid = DirectCast(sender, DataGrid)
RecentColumn(dataGrid) = e.Column
End Sub
End Class
Public Delegate Sub SelectionChangingEventHandler(
ByVal sender As Object, ByVal e As SelectionChangingEventArgs)
Public Class SelectionChangingEventArgs : Inherits RoutedEventArgs
Public Sub New(ByVal row As DataGridRow, routedEvent As RoutedEvent)
MyBase.New(routedEvent)
m_CurrentRow = row
End Sub
Public Sub New(ByVal row As DataGridRow,
ByVal routedEvent As RoutedEvent,
ByVal source As Object)
MyBase.New(routedEvent, source)
m_CurrentRow = row
End Sub
Private m_CurrentRow As DataGridRow
Public ReadOnly Property CurrentRow() As DataGridRow
Get
Return m_CurrentRow
End Get
End Property
Public ReadOnly Property Item() As Object
Get
If CurrentRow IsNot Nothing Then Return CurrentRow.Item
Return Nothing
End Get
End Property
Public Property Cancel As Boolean
End Class
End Namespace
Usage:
<DataGrid Name="dg"
src:DataGridSelectionChangingBehavior.EnableSelectionChanging="True"
src:DataGridSelectionChangingBehavior.SelectionChanging="dg_SelectionChanging">
Code behind (pseudu):
Private Sub dg_SelectionChanging(ByVal sender As Object,
ByVal e As SelectionChangingEventArgs)
If e.CurrentRow.IsEditing Then
Dim item = TryCast(e.CurrentRow.Item, MyEntityType)
If item IsNot Nothing AndAlso item.IsValid Then
Dim dataGrid = DirectCast(sender, DataGrid)
Dim committed = dataGrid.CommitEdit(DataGridEditingUnit.Row, True)
If committed Then Exit Sub
End If
e.Cancel = True
End If
End Sub
Note: visual studio might not show the event in the intellisense and might even generate a design-time error, but it should compile and work perfect.
FYI: code formatted modified to fit SO screen.

Even though form3 is created from form2, why it is not disposed on form2 close?

I need your help to clarify whether form work exactly like object?
If I create an object,obj2, from another object,obj1. the obj2 will be disposed on obj1 dispose.
However it is not so with forms.
check out the case & pseudo code give below.
I have three forms; form1, form2 & form2.
form1 is the startup form.
form1 will create &s how a form2 and from2 will create & show form3 using a button in each form.
if I close form2, after opening all the 3 forms, I am able to work in form1 and form3.
my question is even though form3 is created from form2, why it is not disposed on form2 close?
Form1
Public Class Form1
Private Sub cmdOpenForm2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenForm2.Click
Dim frm As New Form2
With frm
''/.MdiParent = frmMain
.Show()
.BringToFront()
End With
End Sub
Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
''//frmMain.tsStatus.Text = "Form1 disposed"
End Sub
End Class
Form2
Public Class Form2
Private Sub cmdRandomColor_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdRandomColor.Click
Randomize()
Label1.ForeColor = Color.FromArgb(Rnd() * 255, Rnd() * 255, Rnd() * 255, Rnd() * 255)
End Sub
Private Sub Form2_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
frmMain.tsStatus.Text = "Form2 disposed"
End Sub
Private Sub cmdOpenForm3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenForm3.Click
Dim frm As New Form3
With frm
''//.MdiParent = frmMain
.Show()
.BringToFront()
End With
End Sub
End Class
Form3
Public Class Form3
Private Sub cmdRandomColor_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdRandomColor.Click
Randomize()
Label1.ForeColor = Color.FromArgb(Rnd() * 255, Rnd() * 255, Rnd() * 255, Rnd() * 255)
End Sub
Private Sub Form3_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
frmMain.tsStatus.Text = "Form3 disposed"
End Sub
End Class
Any Help will be greatly appreciated.
EDIT
thank you all for the solution
Sorry to mention, I am not looking for a solution how to do dispose form3 on form2 close.
my interest is what is happening behind... Is there any possibility that form3 instance created from2 get GC collect and i get a memory error.
since i am getting protect memory access exception in my real application, which is not properly designed, and it too big to refactor now.
my question is where the form3 instance created? Is it in Form2 instance or somewhere else.
since i can able to access form3 instance after form2 disposed. i doubt it is created in somewhere else
There's nothing automatic happening in Dispose calls on forms related to new forms you create yourselves.
If you want a form to automatically dispose of a form it creates, you have to add code yourself to do this. Either find the .Dispose method added by the designer, and add it there, or implement the FormClosed event on the form.
That form2 "creates" form1 does not make any kind of relationship between the two.
Automatic disposal is available as an option. The form must be an "owned" form. The easiest way to do this is to use the Form.Show(owner) overload:
private void button1_Click(object sender, EventArgs e) {
new Form3().Show(this);
}
Or you can do it afterwards with the Form.AddOwnedForm() method. Beware that this has side-effects, an owned form is always shown in front of the owner. And it will get minimized and restored along with the owner. If you don't want this, you can keep explicit track of the lifetime of the form and dispose it yourself:
private Form3 mForm3;
private void button1_Click(object sender, EventArgs e) {
if (mForm3 == null) {
mForm3 = new Form3();
mForm3.FormClosed += (s, ea) => mForm3 = null;
mForm3.Show();
}
else {
mForm3.WindowState = FormWindowState.Normal;
mForm3.Focus();
}
}
protected override void OnFormClosed(FormClosedEventArgs e) {
if (mForm3 != null) mForm3.Dispose();
}
The framework is still holding on to your form object, until it gets closed. You can get a reference to it using My.Application.OpenForms.
If i create an object,obj2, from another object,obj1. the obj2 will be disposed on obj1 dispose.
Not necessarily. If some other object, say obj3 has a reference to obj2, then obj2 will stick around even after obj1 has been garbage collected.
In this case, the window manager has a reference to form3, so it won't be garbage collected even when form2 is.
You have to use the Form-Constructor that takes a Win32-Window-Handle as a parameter. You can pass a reference of form2 to form3 then and it works as you expected.
Private Sub cmdOpenForm2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenForm2.Click
Dim frm As New Form2(Me)
With frm
.Show()
.BringToFront()
End With
End Sub
If you change the form variables to instance variables, and include this in the Show method, it will work
Code for Form1
public partial class Form1 : Form
{
Form2 f;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
f = new Form2();
f.Show(this);
}
private void button2_Click(object sender, EventArgs e)
{
f.Close();
f = null;
}
}
Code for Form2
public partial class Form2 : Form
{
Form3 f;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
f = new Form3();
f.Show(this);
}
}

Raising event in custom control

I'm writing a custom textblock control thats populate hyperlinks and raises event when clicked to hyperlink.
I wrote this code but I got stucked.
My code is :
Imports System.Text.RegularExpressions
Public Class CustomTextBlock
Inherits TextBlock
Public Event Klik As EventHandler(Of EventArgs)
Public ReadOnly InlineCollectionProperty As DependencyProperty = DependencyProperty.Register("InlineCollection", GetType(String), GetType(CustomTextBlock), New PropertyMetadata(New PropertyChangedCallback(AddressOf CustomTextBlock.InlineChanged)))
Private Shared Sub InlineChanged(ByVal sender As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
DirectCast(sender, CustomTextBlock).Inlines.Clear()
Dim kelimeler = Split(e.NewValue, " ")
For i = 0 To kelimeler.Length - 1
If Regex.Match(kelimeler(i), "(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,#?^=%&:/~\+#]*[\w\-\#?^=%&/~\+#])?").Success Then
Dim x = New Hyperlink(New Run(kelimeler(i)))
x.AddHandler(Hyperlink.ClickEvent, New RoutedEventHandler(AddressOf t_Click))
x.ToolTip = kelimeler(i)
x.Tag = kelimeler(i)
DirectCast(sender, CustomTextBlock).Inlines.Add(x)
If Not i = kelimeler.Length Then DirectCast(sender, CustomTextBlock).Inlines.Add(" ")
Else
DirectCast(sender, CustomTextBlock).Inlines.Add(kelimeler(i))
If Not i = kelimeler.Length Then DirectCast(sender, CustomTextBlock).Inlines.Add(" ")
End If
''//Console.WriteLine(kelime(i).ToString.StartsWith("#"))
Next
kelimeler = Nothing
End Sub
Public Property InlineCollection As String
Get
Return DirectCast(GetValue(InlineCollectionProperty), String)
End Get
Set(ByVal value As String)
SetValue(InlineCollectionProperty, value)
End Set
End Property
Private Shared Sub t_Click(ByVal sender As Hyperlink, ByVal e As System.Windows.RoutedEventArgs)
e.Handled = True
RaiseEvent Klik(sender, EventArgs.Empty)
End Sub
End Class
This code gives error at RaiseEvent Klik(sender, EventArgs.Empty)
Error is : Cannot refer to an instance member of a class from within a shared method or shared member initializer without an expliticit instance of the class.
Thanks for your answers,
Alper
The problem is clearly stated in the exception message. The t_Click method is Shared (which means common to all instances of the class), so it cannot raise an Event that is specific to an instance of the class. You should only raise the event from a method that is not shared.
Do something like this -
Imports System
Imports System.Text.RegularExpressions
Public Class CustomTextBlock
Inherits TextBlock
Public Event Klik As EventHandler(Of System.EventArgs)
Public ReadOnly InlineCollectionProperty As DependencyProperty = DependencyProperty.Register("InlineCollection", GetType(String), GetType(CustomTextBlock), New PropertyMetadata(New PropertyChangedCallback(AddressOf CustomTextBlock.InlineChanged)))
Private Shared Sub InlineChanged(ByVal sender As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
Dim d As CustomTextBlock = DirectCast(sender, CustomTextBlock)
d.Inlines.Clear()
d.OnInlineChanged(CType(e.NewValue, String))
End Sub
Private Sub OnInlineChanged(ByVal Value As String)
Dim kelimeler = Split(Value, " ")
For i As Integer = 0 To kelimeler.Length - 1
If Regex.Match(kelimeler(i), "(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,#?^=%&:/~\+#]*[\w\-\#?^=%&/~\+#])?").Success Then
Dim x = New Hyperlink(New Run(kelimeler(i)))
x.AddHandler(Hyperlink.ClickEvent, New RoutedEventHandler(AddressOf t_Click))
x.ToolTip = kelimeler(i)
x.Tag = kelimeler(i)
Me.Inlines.Add(x)
If Not i = kelimeler.Length Then Me.Inlines.Add(" ")
Else
Me.Inlines.Add(kelimeler(i))
If Not i = kelimeler.Length Then Me.Inlines.Add(" ")
End If
''//Console.WriteLine(kelime(i).ToString.StartsWith("#"))
Next
kelimeler = Nothing
End Sub
Public Property InlineCollection As String
Get
Return DirectCast(GetValue(InlineCollectionProperty), String)
End Get
Set(ByVal value As String)
SetValue(InlineCollectionProperty, value)
End Set
End Property
Private Sub t_Click(ByVal sender As Hyperlink, ByVal e As System.Windows.RoutedEventArgs)
e.Handled = True
RaiseEvent Klik(sender, System.EventArgs.Empty)
End Sub
End Class

Resources