I've got this function that receives a digital output pin address uscita as Integer and status high as boolean, and updates the pin-out and fills color red in a LED-like Ellipse on the UI.
Private Function comandaUscita(ByVal uscita As Integer, ByVal high As Boolean) As Boolean
If high Then
Select Case uscita
Case 1
If gpin1 IsNot Nothing Then gpin1.Write(GpioPinValue.High)
LED1.Fill = redBrush
Case 2
If gpin1 IsNot Nothing Then gpin2.Write(GpioPinValue.High)
LED2.Fill = redBrush
...
End Select
Return True
End If
End Function
The function is called every 500ms via a timer. Debugging shows that the function is working only once. From the second time and for all other times, the function throws an exception
The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))
How can I prevent that without using the f... dispatchers and similar cumbersome stuff. Additionally, how to refresh the UIelements, given that no .Refresh method exists, again without using the f... dispatchers?
The old winforms didn't have these issues... ah, the old times.
My UI XAML looks something like this:
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Height="60"
Margin="10,10,10,569"
Width="340">
<TextBlock x:Name="DelayText1"
Text="Uscita digitale 1"
Margin="10"
TextAlignment="Center"
FontSize="26.667"
HorizontalAlignment="Right" />
<Ellipse x:Name="LED1"
Fill="LightGray"
Stroke="White"
Width="25"
Height="25"
Margin="10,-40,10,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
RenderTransformOrigin="3.524,-1.209"/>
</StackPanel>
Data Binding!
Create an LED ViewModel object, bind one to each LED UI element. Give the LED ViewModel a "Fill" property of the appropriate type. Then, every 500 ms when your timer ticks, update the property and fire off the PropertyChanged event. When the UI element sees the PropertyChanged event, it will refresh "Fill"
It's a bit of an architecture change, but you won't need to worry about using the dispatcher.
This website http://blogs.msdn.com/b/jerrynixon/archive/2012/10/12/xaml-binding-basics-101.aspx has an OK example of binding a string to a button's text. See "Binding a property" - you're going to need to do something similar, but you'll be binding to "Fill"
This question: How can I bind a background color in WPF/XAML? is also doing something pretty similar to what you're trying to do.
Followup to address questions in comments
In your viewmodel, you would need to create a property of type "Brush" and then in the XAML, bind it to the Fill property of the ellipse like:
//The viewmodel:
public sealed class LedViewModel: INotifyPropertyChanged {
// Update this property and fire the PropertyChanged
// event to propagate the change to the UI.
public Brush LedFill { get; set; }
. . .
//In the XAML:
<Ellipse x:Name="LED Whatever"
Fill="{Binding Path=LedFill}"
. . .
Sorry - I just realized that my example is c# and you're doing VB - the XAML part will be the same - The syntax for your ViewModel will be a little different from mine.
Ok, so what I did:
Public NotInheritable Class LedViewModel
Implements INotifyPropertyChanged
Private _LEDFill As Brush
Public Property LEDfill As Brush
Get
Return _LEDFill
End Get
Set(value As Brush)
_LEDFill = value
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler
Implements INotifyPropertyChanged.PropertyChanged
End Class
in the XAML
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Height="60" Margin="10,10,10,569" Width="340">
<TextBlock x:Name="DelayText1" Text="Uscita digitale 1" Margin="10" TextAlignment="Center" FontSize="26.667" HorizontalAlignment="Right" />
<Ellipse x:Name="LED1" Fill="{Binding Path=LEDfill}" Stroke="White" Width="25" Height="25" Margin="10,-40,10,0" HorizontalAlignment="Left" VerticalAlignment="Top" RenderTransformOrigin="3.524,-1.209"/>
</StackPanel>
And in the code? LED1.fill = whatever?
User contributions licensed under CC BY-SA 3.0