views:

153

answers:

1

Using a gridview I a have one column with a NumericUpDown control bound to an underlying list of objects. The problem is I can bind to the valuechanged eventon the UpDown control, however when I update the percentages, it doesn't update on the screen (GridView). If in member.refreshCandidatesGrid i call grid.Rebind() it causes a mess (screen locks up). If I add a button off to the side and click that after I set all the values and have that call member.refreshCandidatesGrid with the rebind everythgin works fine.

I would love to have 1 of 2 approaches work:

  1. push the spinner (numeric updown), and have that fire an event (per tick in the spinner) that I can use to update the percentages

  2. have an event fire when i leave that spinner field, unfortunately the LostFocus looks to be the only event that may make sense and seems to fire during the sue of the spinner...

Thoughts on approach, code structure (even if unrelated) are all appreciated - thank you in advance.

The XAML looks somesthing like this:

<telerik:RadGridView x:Name="candidateGrid" DataContext="{Binding}">
            <telerik:RadGridView.Columns>
                <telerik:GridViewDataColumn Header="Score" IsFilterable="False"
                        DataMemberBinding="{Binding score, Mode=TwoWay}" Width="80" >
                    <telerik:GridViewDataColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding score}" HorizontalAlignment="Right"/>
                        </DataTemplate>
                    </telerik:GridViewDataColumn.CellTemplate>
                    <telerik:GridViewDataColumn.CellEditTemplate>
                        <DataTemplate>
                            <telerik:RadNumericUpDown Loaded="Editor_Loaded" Maximum="10000" UpdateValueEvent="PropertyChanged"  IsInteger="True"  Minimum="0" ValueChanged="score_ValueChanged"
                                    Value="{Binding score, Mode=TwoWay, UpdateSourceTrigger=Explicit}" Width="60" O />
                        </DataTemplate>
                    </telerik:GridViewDataColumn.CellEditTemplate>
                </telerik:GridViewDataColumn>
                <telerik:GridViewDataColumn Header="Percent" IsReadOnly="True" IsFilterable="False" Width="70">
                    <telerik:GridViewDataColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding percent}" HorizontalAlignment="Right"/>
                        </DataTemplate>
                    </telerik:GridViewDataColumn.CellTemplate>
                </telerik:GridViewDataColumn>

and it is bound to an f# class like the following:

namespace BV

open System
open System.Text.RegularExpressions
open System.Windows ;
open System.Windows.Controls;
open System.Windows.Controls.Primitives ;
open System.Windows.Media ;
open Telerik.Windows.Controls;

open Globals
open RpcBV

type Page() as this =    
    inherit UriUserControl("/BV;component/page.xaml", "page")

    // instance data
    let mutable brokers = RpcBV.getCandidates()

    // bound controls for add candidate
    let FE : FrameworkElement = (this.Content :?> FrameworkElement)
    let candidateGrid : RadGridView = FE ? candidateGrid

    do
        firm.ItemsSource <- RpcBV.getFirms()
        email.Background <- SolidColorBrush(Colors.Red)
        addBtn.IsEnabled <- false
        this.refreshCandidatesGrid() ;

    member this.refreshCandidatesGrid () =
        candidateGrid.ItemsSource <- brokers ;
        ()



    member this.calculatePercentages() =
        let totalScore = List.fold (fun acc (candidate: ScorableCandidate) -> acc + candidate.score) 0 brokers

        let scoreEm (candidate: ScorableCandidate) =
             candidate.percent <- (float candidate.score) / float totalScore * 100.

        List.iter scoreEm <| brokers

    member this.addCadidate_Click (sender : obj) (args : RoutedEventArgs)  = 
        this.addCandidateFromForm()
        this.resetAddCandidateForm()
        this.refreshCandidatesGrid()

    member this.score_LostFocus (sender : obj) (args : RoutedEventArgs)  = 
        ()

    member this.score_ValueChanged (o : obj) (arg : RadRangeBaseValueChangedEventArgs) = 
        this.calculatePercentages()

    member this.Editor_Loaded (sender:obj) (args: RoutedEventArgs) =
        let ctrl = sender :?> Control;
        ctrl.Focus() |> ignore ;
        ()
+1  A: 

If you want property changes to be reflected immediately in the UI then the type that your controls are bound to should probably implement the INotifyPropertyChanged interface (or use another mechanism such as exposing DependencyProperties). What does your definition of ScorableCandidate look like?

kvb
It is just a record list, nothing special...
akaphenom
It was an easy enough change - thank you.
akaphenom
implmemented the Inotify everywhere...
akaphenom