How to do simple databinding in WPF

darbid73
darbid73 used Ask the Experts™
on
I cannot get anything to databind.  I have made a sample project just to understand this.  It only has 1 button and 1 textblock.

I have added the XAML, the code behind the window and a class.

I want my textbox to update and I thought that changing the value of prgValue would do this, but it is not updating.
****XAML****

<Window
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:local="clr-namespace:WpfApplication7.testms" 
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
	x:Class="testms.MainWindow"
	x:Name="Window"
	Title="MainWindow"
	Width="640" Height="480" xmlns:local1="clr-namespace:WpfApplication7.MyNS">

	<Window.Resources>
		<ObjectDataProvider x:Key="PrgBarDataSource1" d:IsDataSource="True"  ObjectType="{x:Type local1:PrgBar}"/>
	</Window.Resources>

	<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource PrgBarDataSource1}}" >
		<Button x:Name="mybtn" Content="Button" Height="40" Margin="208,0,272,170" VerticalAlignment="Bottom" Click="mybtnclick"/>
		<TextBlock x:Name="mytxt" Height="32" Margin="184,96,288,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="{Binding prgValue}"/>
	</Grid>
</Window>


****Class****

Imports System.ComponentModel


Namespace MyNS

    Public Class PrgBar

        Implements INotifyPropertyChanged


        Private _prgValue As Double

        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged


        Property prgValue() As Double
            Get
                Return _prgValue
            End Get
            Set(ByVal Value As Double)
                _prgValue = Value
                '   OnPropertyChanged("prgValue")
                Debug.Print("propert value now " + _prgValue.ToString)
            End Set
        End Property

        Friend Overridable Sub OnPropertyChanged(ByVal sProp As String)
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(sProp))
            Debug.Print("raised event")

        End Sub

    End Class


****End Namespace****


Imports WpfApplication7.MyNS



Namespace testms


    Class MainWindow

        Dim myProgress As PrgBar




        Private Sub mybtnclick(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)


            myProgress = New PrgBar

            myProgress.prgValue = 100

          
        End Sub
    End Class

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Whats wrong with my code?
Why Diversity in Tech Matters

Kesha Williams, certified professional and software developer, explores the imbalance of diversity in the world of technology -- especially when it comes to hiring women. She showcases ways she's making a difference through the Colors of STEM program.

The xaml  ObjectDataProvider creates an instance of prgBar. The code-behind then creates another one (Dim myProgress As PrgBar) and makes the update to that. The window is still showing the unchanged instance.

The attached code is my usual approach to binding to a class. It uses xaml to create an instance of the class directly, rather than using an ObjectDataProvider, but apart from that it's the same (I'll try it with the objectdataprovider after I've posted this):
        <local:prgBar x:Key="pb"/>
... then uses that as the datacontext of the Grid:
    <Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource pb}}" >
Since wpf needs to be prompted to requery a clr property, I uncommented this line:
            OnPropertyChanged("prgValue")
Finally, in the code-behind the prgvalue property is changed for the class instance created in xaml:
        CType(mytxt.DataContext, prgBar).prgValue = 42




<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:wpfTestBed"
    Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
    </Window.Resources>


    <Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource pb}}" >
        <Button x:Name="mybtn" Content="Button" Height="40" Margin="208,0,272,170" VerticalAlignment="Bottom" Click="mybtnclick"/>
        <TextBlock x:Name="mytxt" Height="32" Margin="184,96,288,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="{Binding prgValue}"/>
    </Grid>

</Window>

Class MainWindow 

    Private Sub mybtnclick(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        CType(mytxt.DataContext, prgBar).prgValue = 42
    End Sub
End Class

Imports System.ComponentModel
Public Class prgBar
    Implements INotifyPropertyChanged
    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    Private _prgValue As Double

    Property prgValue() As Double
        Get
            Return _prgValue
        End Get
        Set(ByVal Value As Double)
            _prgValue = Value
            OnPropertyChanged("prgValue")
            Debug.Print("propert value now " + _prgValue.ToString)
        End Set
    End Property

    Friend Overridable Sub OnPropertyChanged(ByVal sProp As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(sProp))
        Debug.Print("raised event")

    End Sub


End Class

Open in new window

I needed to remove
   d:IsDataSource="True"
... from the ObjectDataProvider definition because I'm not using ExpressionBlend
   <ObjectDataProvider x:Key="pb" ObjectType="{x:Type local:prgBar}"/>
That apart, it worked in the same way as in my previous post.

To get your example working you need to:
1. In code-behind, address the instance created in xaml:
        CType(mytxt.DataContext, prgBar).prgValue = ...
2. Reinstate the OnPropertyChanged line

Here's a post from Bea Stollnitz on the use of ObjecDataProvider vs direct object instantiation
http://bea.stollnitz.com/blog/?p=22
Perfect Mike thank you.  That is a stupid mistake I was making but I have to learn.

There is something troubling me.  To change the value you suggest this

 CType(mytxt.DataContext, prgBar).prgValue = 42

But I could just put then Me.mytxt.value = 42 everytime I wanted to change it.  As long I was on the UI thread it would update or I could use the Dispatcher to get it to the right thread.

I thought the principle here was that the XAML linked to a property of an object and when the object changed for any reason then the XAML would reflect that change.

For example how do I get the XAML instance of my prgBar object, I could then at least use that in my code behind.
The point is that you could make your TextBlock a TextBox and then you wouldn't need a button or any code behind to update the bound property, just typing into the textbox would do it.
The code I suggested does exactly what you request - it gets the xaml instance, but uses it immediately - you could code it more specifically:

Dim myinstance = CType(mytxt.DataContext, prgBar)
Thank you Mike.  Great answers, for the first time I am impressed with EE on questions about VB.net and WPF.
Thank you again.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial