[beginner] data binding examples

Jul 28, 2011 at 7:49 AM

Hi, 

continuing experimenting with ShowUI, I'm facing these issues. I want to make a Label reflect text values entered in a Textbox.

I would like to refer to these values outside of the GUI, in a function, without passing the component as param. Is it possible? 

Could you tell what I'm missing? searching WPF docs didn't help enough!

Regards, 

jucg

Here's the example:

# basis taken from http://www.powershellcommunity.org/Forums/tabid/54/aft/6716/Default.aspx

ipmo showui
$person = New-Object -TypeName PSObject -Property @{ lname ="john"; fname = "smith" }

# question 1. Is it possible to refer to Label $fname content in this function ?

function echo-fname(){   

Write-Host ($fname -eq $null) #$true $fname is null. How to refer to it from here?

#Write-Host $fname.Content 

}
Stackpanel -Margin 5 {   

Label -Name lname -DataBinding @{ Content = Binding -Path lname -Source $person -UpdateSourceTrigger PropertyChanged } 

Label -Name fname -DataBinding @{ Content  = Binding -Path fname -Source $person -UpdateSourceTrigger PropertyChanged } 

 

# same as question 1. how to call an external function which would refer to the GUI values? I can modify the echo-fname parameters as to accept the Label and call it like in  Button -on_Click { echo-fname $fname}, but that's not my question!

Button "echo firsName" -on_Click { echo-fname }

 

# question 2. how to make the label $fname2 reflect whatever values are filled in TextBox $tbx?   

# question 3. then, how to update $person so $fname would be updated too after modifying  $tbx text? tbx -> $person -> changes reflected in Label fname2   

TextBox -name tbx -text "change first name here"    

Label -name fname2 -DataBinding @{ Content = Binding -Path fname -Source $tbx -UpdateSourceTrigger PropertyChanged }    

} -show 

Jul 28, 2011 at 12:29 PM

while retrying, I found this post:

http://www.mindstick.com/Articles/51e2fae3-d7be-45af-a77d-09a86b2738e1/?Dynamic%20Bind%20TextBox%20data%20to%20Label%20control%20in%20WPF

which is exactly my question #2.

Hope it helps make things a bit clearer.

jucg

Coordinator
Jul 28, 2011 at 3:03 PM
Edited Jul 28, 2011 at 3:04 PM

The answer to #1 is: No, But.

We create the "$fname" variable in the module scope, so that it doesn't leak out to the global scope. 

There's a way around that: use the call operator to run code in the module scope: 

 

    # question 1. Is it possible to refer to Label $fname content in this function ?
    # answer: It's defined in the module scope, so you need to & call it in the module:
    function write-fname() {  
        $_fname = &(Get-Module ShowUI){ $fname }
        Write-Host ($_fname -eq $null)
        Write-Host $_fname.Content
    }

 

Personally, that makes me nervous. The other work-arounds are: 

  1. Put the function definition inside the Loaded or Initialized event handler of your main UI so that it gets defined in module scope.
  2. Pass the module scope variables as parameters to the function (if you actually want the function to be reuseable, this is what I would recommend).

 

I'm still wrestling with the 2nd question.

What you SHOULD be able to do is specify the binding using ElementName, but when the binding is created and applied, the Label hasn't yet been put into the parent control, so ElementName binding doesn't work.

However, the problem is simple, if you approach is using Source as you did: in the current release, magic variables like $tbx only exist in event handlers, so you just need to make sure one gets set. Change the last two lines like this:

    TextBox -name tbx -Text {Binding -Path fname -Source $person -UpdateSourceTrigger PropertyChanged -NotifyOnSourceUpdated} -OutVariable tbx
    Label -name fname2 -DataBinding @{ Content = Binding -Path Text -Source $tbx[0] -UpdateSourceTrigger PropertyChanged }

Incidentally: PATH needs to be the PROPERTY of the TEXTBOX that you want to bind to (the Text, in this case). And $TBX will be an array, because OutVariable is always an array.

Jul 29, 2011 at 7:11 AM

Thanks a lot Jaykul, 

I wasn't expecting so deep help. It's a like a tuto ! 

Maybe there's a better place for beginners coming to WPF through PowerShell. What do you think about posting newby question here (I have many more ;-) ) ?

 

>What you SHOULD be able to do is specify the binding using ElementName, but when the binding is created and applied, the Label hasn't yet been put into the parent control, so ElementName binding doesn't work.

I might not understand this sentence well. In this case, Should means... some king of a missing feature in ShowUI? in the cited article Dynamic "Bind TextBox data to Label control in WPF", the xaml code is written like that

<Label  Content="{Binding Text,ElementName=txtinput,UpdateSourceTrigger=PropertyChanged}"></Label>

Indeed I had tried to transpose this code to my snippet without success.

 

Thanks a lot again,

Regards, 

jucg

 

Coordinator
Jul 29, 2011 at 7:36 PM

Well, basically, yes, it's a WPF feature that doesn't work correctly in ShowUI.

I believe that the problem is that when we add the binding, the control hasn't yet been added to the window, so it can't find the other Element to bind to it.  We *might* be able to fix it, but I'm not making any guarantees, and it's a little low priority right now because there are several workarounds :) (Obviously using OutVariable with Source works).

In theory, we should be able to use the Element binding by moving the creation of the element into an event like On_Load, or if you databind there, { $this.Content.Add(( Label ... )) } but I can't seem to get it to work :-)