0
votes

I have a WPF Window which has its DataContext set to a ViewModel object, and which has child controls databound to properties of that DataContext (ViewModel) object. Those databound controls are correctly displaying the data from the ViewModel object. However, there is a StatusBar containing a TextBlock, which is supposed to update when the underlying ViewModel object's bound property changes -- and TextBlock is not updating.

The problem is due to the fact that nothing is attaching to the ViewModel object's PropertyChanged event during the binding (or when it is set as the DataContext), and so notification of changes to the data are not routed to the TextBlock control.

The abbreviated XAML is this:

Window x:Class="MarketFeedViewer.MainWindow"
        xmlns:marketFeedViewer="clr-namespace:MarketFeedViewer"
        mc:Ignorable="d"
        Title="Market Data Viewer" Height="500" Width="300" >
    <Window.DataContext>
        <marketFeedViewer:MarketDataViewModel />
    </Window.DataContext>

    <Grid Margin="0,0,0,0">
        <WrapPanel  HorizontalAlignment="Center" VerticalAlignment="Top" Grid.Row="0" Grid.ColumnSpan="2" Margin="0,3,3,0">
            <Label>Host</Label>
            <TextBox x:Name="Host" VerticalContentAlignment="Center" MinWidth="100" Text="{Binding Host}" />

            <Label Content="Port" />
            <TextBox x:Name="Port" MinWidth="50" VerticalContentAlignment="Center"  Text="{Binding Port}"/>
        </WrapPanel>
        <DataGrid x:Name="PricesGrid"  HorizontalAlignment="Center" Margin="5,5,5,5" Grid.Row="1" Grid.ColumnSpan="2"
                  Grid.Column="0"
                  VerticalAlignment="Stretch"

                  ItemsSource="{Binding MarketData}"
                  MinHeight="200" MinWidth="200" VerticalScrollBarVisibility="Auto"/>
 <StatusBar Grid.Row="3" Grid.ColumnSpan="2" Grid.Column="0">
            <StatusBarItem HorizontalAlignment="Right">
                <TextBlock Name="StatusText"  Text="{Binding FeedStatus}" />
            </StatusBarItem>

        </StatusBar>
    </Grid>
</Window>

The ViewModel class implements INotifyPropertyChanged, and when the Status Bar's underlying property is updated from a background thread, it is firing the PropertyChange event:

public class MarketDataViewModel : INotifyPropertyChanged
    { 

    public ObservableCollection<WPFL1Data> MarketData { get; set; }

    ...

    public string FeedStatus
    {
        get { return GetStatus(); }
    }
       ...
       ...
    private void ClientOnOnStateChange(object sender, MarketFeedConnectionState e)
    {
        if (App.IsInvokeRequired)
        {
            App.InvokeMethod(() => ClientOnOnStateChange(sender, e));
            return;
        }

        ...
        // here is where Status Bar's TextBlock should be notified
        // that value has changed.
        OnPropertyChanged(FeedStatus);
    }

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        // problem is here: handler ==  null
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

What is the missing piece of code of XAML configuration?

1
are you saying that textbox with Host binding is working properly, but not the FeedStatus? your VM code looks good to raise FeedStatus property changed. - LadderLogic
Also, the UpdateSourceTrigger doesn't make sense on the TextBlock. This is telling WPF when to update the source property of the view model. Textblock is not editable, so there won't be a change to update the source property - LadderLogic
@LadderLogic: The FeedStatus binding is working correctly, as far as displaying the initial value. The problem as that when the FeedStatus property is updated with a new value, the new value does not show in TextBlock. As far as I can tell, the problem is that no PropertyChanged event handler is being attached to the PropertyChanged event. I thought that by setting the _MarketDataViewModel _ as the DataContext in the Window, that somehow the Window would attach to its PropertyChanged event and then propagate events to the children. But this is not happening. - Sam Goldberg
@LadderLogic: re: UpdateSourceTrigger - yes, you're correct. That was a left-over from my flailing around trying to find how to get something to attach to the ViewModel's PropertyChanged event. - Sam Goldberg

1 Answers

3
votes

You are passing the FeedStatus property value to the OnPropertyChanged method, instead of its name. It should look like this:

OnPropertyChanged("FeedStatus");

or better this:

OnPropertyChanged(nameof(FeedStatus));