WPF Custom Control VB.net - wpf

I've created a custom control called ecTextBox in VB.NET which uses a control template in Generic.xaml. That works.
In code behind of the custom control I override metadata in the constructor:
Public Sub New()
DefaultStyleKeyProperty.OverrideMetadata(GetType(ecTextBox), New FrameworkPropertyMetadata(GetType(ecTextBox)))
End Sub
In MainWindow.xaml I use the custom control with a simple
<ec:ecTextBox/>
That works fine.
But if I throw a second control or change the propertys of the first ecTextBox in MainWindow.xaml, I get the message "PropertyMetaData is already registered for type ecTextBox".
In StackOverflow I've read, that C# programmers should use the static-Keyword for the constructor. But if I change the constructor to
Shared Sub New
DefaultStyleKeyProperty.OverrideMetadata(GetType(ecTextBox), New FrameworkPropertyMetadata(GetType(ecTextBox)))
End Sub
the second custom control don't uses the control template but appears as a normal TextBox without Border.
What is the correct way to override the metadata for all used ecTextBox controls and prevent the errors?

This is the solution:
Public Sub New()
MyBase.New()
End Sub
Shared Sub New()
DefaultStyleKeyProperty.OverrideMetadata(GetType(ecTextBox), New FrameworkPropertyMetadata(GetType(ecTextBox)))
End Sub

Related

How to use Ribbon Buttons to execute code?

So far I have managed to create a ribbon with several buttons by following this tutorial.
Now I want to make the buttons actually do stuff! I found this example which shows how to execute already existing method. However if I do: Command="myCustomClass.myCustomMethod" and use
Class myCustomClass
Public Sub myCustomMethod()
'do stuff
End Sub
End Class
I get the error myCustomClass is not supported in a Windows Presentation Foundation (WPF) project.
I also noticed this this post from the same post. After converting the code to VB.NET:
Public Class MyCommand
Implements ICommand
Public Sub Execute(parameter As Object) Implements ICommand.Execute
Dim hello As String = TryCast(parameter, String)
MsgBox(hello)
End Sub
Public Function CanExecute(parameter As Object) As Boolean Implements ICommand.CanExecute
Return True
End Function
Public Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
End Class
and adding the references to the <Window x:Class="MainWindow" ... element:
<Window.Resources>
<local:MyCommand x:Key="mycmd"/>
</Window.Resources>
I get the following error: The name 'MyCommand' does not exist in the namespace "clr-namespace:RibbonSample".
I'm at a complete loss as to what I need to do to implement these buttons. Would it be possible to get any full ribbon samples using the same framework, with which I can learn from? I assume the solution to this should be really simple.
Rebuild your project.
The WPF designer loads classes from your project's compiled assembly (so that it can actually execute your code).
If you add a new class, it will give you errors until you rebuild your project so the assembly includes that class.

What is the correct Xaml syntax (and underlying vb code) to have a event raised by a custom Control handled in a host application view model

I have a wpf Custom Control which is now raising custom events. In a test project that I have created to test the ongoing development of the control I have placed a copy of my new custom control on the main window.
In the properties dialog for said control I can see my new event and I can type in the name for a handler for it in the code behind the main window and it's not only created for me but when I place a break point on it I see both the sender and my own event args raised in the control.
What I would now like to know Is what is the correct way to alert a viewmodel about that event respecting the principles of MVVM.
Below is the xaml markup for my custom control in the mainwindow of the test application
<WpfControls:VtlDataNavigator Name="vtlDn"
ItemsSource="{Binding Path=Orders}"
Grid.Row="1"
AddButtonVisibility="True"
CancelNewRecordButtonVisibility="True"
SaveButtonVisibility="True" />
The event I want to catch is called 'RecordControlButtonClicked' and this is the event automatically created in the mainwindow code behind
Private Sub MyCustomHandlerForControlEvent(sender As Object, e As ViewToLearn.WpfControls.VtlDataNavigatorEventArgs) Handles vtlDn.RecordControlButtonClicked
End Sub
So now what I'm after is the correct syntax in both the xaml and my new MainWindowViewModel to have this event transferred across to the viewmodel for handling (or suggestions as to the most efficient way to do this idf there is no direct route.
FYI I already have a relay command set up in the test application but the way that I've used it to bind commands in the past doesn't appear to be working with events.
Edit
One approach I've tried which appears to work is to add the following in the code behind of the main window's loaded event.
Class MainWindow
Public Sub New()
InitializeComponent
DataContext = New MainWindowViewModel
End Sub
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Dim mvm As MainWindowViewModel = DirectCast(DataContext, MainWindowViewModel)
mvm.vtldn = vtlDn
End Sub
End Class
and then add the following in the viewmodel;
Private _vtldn As ViewToLearn.WpfControls.VtlDataNavigator
Public Property vtldn As ViewToLearn.WpfControls.VtlDataNavigator
Get
Return _vtldn
End Get
Set(ByVal Value As ViewToLearn.WpfControls.VtlDataNavigator)
If (_vtldn Is Value) Then Return
If Not IsNothing(vtldn) Then
RemoveHandler vtldn.RecordControlButtonClicked, AddressOf MyCustomHandler
End If
_vtldn = Value
If Not IsNothing(vtldn) Then
AddHandler vtldn.RecordControlButtonClicked, AddressOf MyCustomHandler
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(NameOf(vtldn)))
End Set
End Property
Private Sub MyCustomHandler(ByVal sender As Object, ByVal e As VtlDataNavigatorEventArgs)
'this does get called when buttons in the custom control are clicked
End Sub
However I'm acutely aware that this is not really 'pure' mvvm so if there are better ways to do this I'm open to suggestions.

Translating from Forms UserControl to WPF UserControl

I am in the process of translating a Forms user control into a WPF user control. In my forms version do i overwrite a method called CreateHandle, where i hook up some events. I am having problems translating this to WPF as it do not have a CreateHandle method to overwrite, and i have been unable to figure out what else to overwrite. I am not able to do it in the constructor as the events i want to hook up is have not been created at this point.
Update: What i would like to do it have a method that is executed in WPF roughly at the some time the CreateHandle method in a forms user control would have.
Found a way to do it.
Public Sub New()
' This call is required by the designer.
InitializeComponent()
AddHandler Me.IsVisibleChanged, AddressOf OnView
End Sub
Private Sub OnView(ByVal sender As Object, ByVal e As DependencyPropertyChangedEventArgs)
' Do stuff here
RemoveHandler Me.IsVisibleChanged, AddressOf OnView
End Sub

WPF and VB.net: Data Binding to Separate Class created outside of Expression Blend

I have a WPF application with form that has a textbox named "txtStatusWindow". I also have a vb.net class handed to me by a co-worker that needs to be called and executed by the code in my application code-behind. My co-worker insists that I will need to use common .net events to update the textbox on my form.
The separate vb.net class:
Public Class globalclass
Public Event txtStatusWindow(ByVal Text As String)
Public Sub InitializeProgram()
RaiseEvent txtStatusWindow("Updating something.")
System.Threading.Thread.Sleep(2000)
RaiseEvent txtStatusWindow("Updating something else.")
System.Threading.Thread.Sleep(2000)
RaiseEvent txtStatusWindow("Updating something other than else.")
System.Threading.Thread.Sleep(2000)
RaiseEvent txtStatusWindow("Updating something other than the else stuff.")
System.Threading.Thread.Sleep(2000)
End Sub
End Class
I need to be able to call the sub "InitializeProgram()" from my code-behind, and it needs to be able to update "txtStatusWindow.text" as it runs.
I told him that the updating of the text box can be done with data-binding, but I don't know how to integrate a separate class like this into my project, how to call methods in it, or how to cause it to update my text blocks through data binding.
I also suggested that the methods in this class aren't optimal for connecting to the WPF project anyway, but he just wrote it as an example to discover how to connect the two projects.
Eventually, I will need to integrate classes like these that will be running separate threads to update their data from a dynamic source, and cause many controls to update in my application.
So far, the only way we have been able to get this to work from my code-behind is this:
Partial Public Class SplashScreen
Dim NewText as String
Public WithEvents Globals As globalclass = New globalclass
Public Delegate Sub StringDelegate(ByVal Text As String)
Public SplashText As String
Public Sub New()
MyBase.New()
Me.InitializeComponent()
Me.Show()
Globals.InitializeProgram()
End Sub
Public Sub UpdateSplashscreenHandler(ByVal Text As String) Handles Globals.UpdateSplashScreen
StatusWindowText.Text = Text
End Sub
Notwithstanding the fact that the WPF screen "freezes" until the "globalclass InitializeProgram" method completes (txtStatusWindow.Text does not update while sub without using the esoteric "refresh" extension...), I fully believe we are going about this the wrong way.
There are precious few examples out there concerning the integration and then binding to objects in existing code. Thanks for examining our little quandary.
If this status window is in XAML and the status window is a UserControl, then add a StatusText dependency property to the status window. Then, in the XAML you can bind to the value of that property with something like:
<UserControl x:Name="MyStatusWindow" ...>
<TextBlock Text="{Binding Path=StatusText, ElementName=MyStatusWindow}" />
</UserControl>
Then, from your event, just update the value of that StatusText property.
(Is that even close to what you were asking?)
Also, about that freezing: Instead of doing that updating in the constructor of that class, you might want to do it from the Loaded event of that control. It will still be freezing, though, unless you move it to a separate thread. Right now, that's happening on the same thread that the UI message pump is running on. This is the Dispatcher for that UI.

Basic WPF question: How to add a custom property trigger?

I am using Expresion Blend 3 and created a new user control in my project. I want a storyboard to run if a custom property of that user control is triggered like with the ones shown here in the list..
I learnt you need a dependency property, but my understanding there is limited. Here's the basic code I set up with property "IsAwesome" as an example..
Partial Public Class simpleControl
Public Sub New()
MyBase.New()
Me.InitializeComponent()
End Sub
Public Shared ReadOnly IsAwesomeProperty As DependencyProperty = _
DependencyProperty.Register("IsAwesome", GetType(Boolean), GetType(simpleControl))
Public Property IsAwesome() As Boolean
Get
Return DirectCast(Me.GetValue(IsAwesomeProperty), Boolean)
End Get
Set(ByVal value As Boolean)
Me.SetValue(IsAwesomeProperty, value)
End Set
End Property
End Class
However, my property doesn't show in that list. What am I missing? Or is my entire approach wrong?
Any help or advice would be appreciated!
Cheers
I created a new Wpf project. Added a new UserControl (UserControl1) with a custom dependency property called Foo.
Then I opened Blend and added an instance of UserControl1 to Window1. I right clicked on UserControl1 and said EditTemplate | Edit a Copy.
This created a copy of my user control template in the Window.Resources. From within this new template I went up to the Triggers panel and clicked the button to add a new property trigger.
Right away Blend defaulted to selecting my property in the "Activated When" section.
alt text http://blog.BradCunningham.net/Images/ForumImages/CustomDPInBlend.png
You can grab my little sample app from here: http://blog.BradCunningham.net/SourceCode/ForumSamples/CustomDPInBlend.zip

Resources