Search code examples
c#jsonxamlxaml-binding

How to change a variable generated by JSON in c#


I'm having issues with something that should be very easy. I'm creating a flood warning app for windows phone 8. I have an integer Severity, which can be anything from 1 to 4, pulled from a JSON feed. I simply want to change the int to a string corresponding to the severity, then use the strings to populate a text block via binding. Here's the code

namespace FloodAlertsApp
{


public class RootObject
{

    public int Severity { get; set; }
    public string AreaDescription { get; set; }
    public string Raised { get; set; }
    public string severityTxt;      

    public string getsevText()
    {

        switch (Severity)
        {
            case 1:
                severityTxt = "Severe";
                break;
            case 2:
                severityTxt = "Warning";
                break;
            case 3:
                severityTxt = "Alert";
                break;
            case 4:
                severityTxt = "";
                break;
        }
        return severityTxt;
    }
}

And then the xaml where i'm using the binding is as follows,

<phone:PhoneApplicationPage
x:Class="FloodAlertsApp.ListView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d"
shell:SystemTray.IsVisible="True">

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
        <!--<RowDefinition Height="Auto"/>-->
    </Grid.RowDefinitions>

    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Width="Auto" HorizontalAlignment="Center"   Margin="10,10,10,10">
        <Image Width="Auto" Source="/nrw_logo_linear.png" Stretch="Fill"/>
    </StackPanel>

    <!--ContentPanel - place additional content here-->
    <StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="0,0,0,0">

        <ListBox Name="listBoxBeaches" SelectionChanged="listBoxBeaches_SelectionChanged" Margin="10,10,10,0" Padding="0,0,0,100" Height="{Binding ElementName=ContentPanel, Path=ActualHeight}">
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid Grid.Row="0" x:Name="TemplateLayout" Margin="0,5,0,5">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="60" />
                        </Grid.ColumnDefinitions>

                        <StackPanel Grid.Row="0" Grid.Column="0" x:Name="Stackpnl">
                            <TextBlock Foreground="Black" FontSize="28" Margin="5,0,5,0" Text="{Binding Path=AreaDescription}"></TextBlock>
Here be the binding---->    <TextBlock Foreground="Black" FontSize="28" Margin="5,0,5,0" Text="{Binding Path=SeverityTxt}"></TextBlock>
                            <TextBlock Foreground="Black" FontSize="22" Margin="5,0,5,0" Text="Raised at "></TextBlock>
                            <TextBlock Foreground="Black" FontSize="22" Margin="5,0,5,0" Text="{Binding Path=Raised}"></TextBlock>
                        </StackPanel>

                        <Ellipse Grid.Row="0" Grid.Column="1" Margin="5,0,5,0" x:Name="StatusEllipse" Height="50" Width="50" Fill="{Binding Path = Colour}" />

                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>

        </ListBox>


    </StackPanel>
</Grid>

</phone:PhoneApplicationPage>

The other bindings work fine, but when i try to change from an int to a string the binding shows up as nothing.


Solution

  • Firstly, RootObject should implement INotifyPorpertyChanged interface, so that bindings will work properly.

    Having done that you should remove public field, and add a new property called severityTxt(BTW it should be called SeverityText according to the C# naming convention) with only get accessor.

    The code will be like this:

    public class RootObject : INotifyPropertyChanged
    {
        private int serverity;
    
        private string areaDescription;
    
        private string raised;
    
        public int Severity 
        {
            get
            {
                return serverity;
            }
            set
            {
                serverity = value;
                NotifyPropertyChanged("Severity");
                NotifyPropertyChanged("SeverityTxt");
            }
        }
    
        public string AreaDescription 
        {
            get
            {
                return areaDescription;
            }
            set
            {
                areaDescription = value;
                NotifyPropertyChanged("AreaDescription");
            }
        }
    
        public string Raised 
        {
            get
            {
                return raised;
            }
            set
            {
                raised = value;
                NotifyPropertyChanged("Raised");
            }
        }
    
        public string SeverityTxt
        {
            get 
            {
                switch (Severity)
                {
                    case 1:
                        return "Severe";
                    case 2:
                        return "Warning";
                    case 3:
                        return "Alert";
                    default:
                        return string.Empty;
                }
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        private void NotifyPropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    With such implementation you should bind not to severityTxt but to SeverityTxt. It's the basic solution, for more solid code you should consider using MVVM framework, such as MVVM Light and\or IValueConverter's.