locked
Changing the shape and color of an object based on numerical data in an xml file RRS feed

  • Question

  • Title kind of explains it all on this one.

    I need to make a proof of concept design in which a user can enter numerical values into a database and the changes will be reflected visually in a Silverlight web part. I'd like to just keep it simple for now. I only need three rows and two columns. In the rows I will have names. The two colums will be "Name" and then a green bar that reflects a percentage value. So if someone type "20" into the database, the bar is 1/5 of its size. It also has to change to red once it gets over 50%.

    I have the states and animation I think, but am struggling a bit with binding it to data. What might the best way be to accomplish this? Can I do it just using the GUI in Blend without having to dive into code? I need it by Friday morning in Germany, so if anyone knows the answer I'd deeply appreciate it!

    Wednesday, March 6, 2013 12:13 PM

All replies

  • Ok, it's come up again. Any way to transform an object in Silverlight via some type of numeric data bind from Access or Excel?
    Tuesday, March 12, 2013 2:29 PM
  • "Ok...no one answered and now you've made Chris cry. I hope you can all live with yourselves", said Chris.

    And so, having been rejected, Chris left his desk deciding to live out the rest of his days in a cave deep within the mountains. Day by day losing a piece of his humanity and becoming one with the darkness and stone. Until one day...he met a hobbit...

    ok....that last part might be from a book I read once...but still...

    Wednesday, March 13, 2013 8:16 AM
  • Hello Chris.

    Here is a sample based on what I think you described you are after.  2 columns one with a name and one with a visual representation of the number.

    SilverlightApplication1

    In my sample I created a SampleDataSource.

         Data panel > Create Sample Data Button > New Sample Data > Define in Project > Ok.

    Next I renamed the properties it created.

         Property1 > Name

         Property2 > Number (Also changed the property type to a number)

    Then I created a data entry grid.  A place where the numbers could be changed.

    <Grid x:Name="EnterDataGrid" HorizontalAlignment="Left" Height="143" Margin="8,8,0,0" VerticalAlignment="Top" Width="276" DataContext="{Binding Collection[0], Source={StaticResource SampleDataSource}}">
    	<Grid Height="24" VerticalAlignment="Top" Background="Black">
    		<TextBlock TextWrapping="Wrap" Text="Enter/Change Data" Margin="0" Foreground="White"/>
    	</Grid>
    	<TextBlock TextWrapping="Wrap" Text="Select An Item Index" VerticalAlignment="Top" Margin="22,37,83,0" />
    	<toolkit:NumericUpDown x:Name="numUpDown" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,38,22,0" Maximum="9" Cursor="Hand" ValueChanged="NumericUpDown_ValueChanged"/>
    	<TextBlock HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="100" Margin="22,0,0,36" Text="Name" Height="32"/>
    	<TextBox Text="{Binding Name, Mode=TwoWay}" VerticalAlignment="Bottom" Margin="126,0,8,36"/>
    	<TextBlock HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="100" Margin="22,0,0,0" Text="Number" Height="32"/>
    	<toolkit:NumericUpDown VerticalAlignment="Bottom" Margin="126,0,8,8" Value="{Binding Number, Mode=TwoWay}"/>
    </Grid

    I used a NumUpDown control to go through the items in the SampleDataSource and change the active item with a bit of code when the NumUpDown value changes. (This was just for the sample and to make it a bit easier to view changes.)

    using Expression.Blend.SampleData.SampleDataSource;
    using System;
    using System.Windows;
    using System.Windows.Controls;
    
    namespace SilverlightApplication1
    {
    	public partial class MainPage : UserControl
    	{
    		SampleDataSource sds;
    		
    		public MainPage()
    		{
    			InitializeComponent();
    			sds = Application.Current.Resources["SampleDataSource"] as SampleDataSource;
    		}
    		
    		private void NumericUpDown_ValueChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs<double> e)
    		{
    			if (sds != null)
    			{
    				EnterDataGrid.DataContext = sds.Collection[(Convert.ToInt16(numUpDown.Value))];
    			}
    		}
    	}
    }

    Next I added a ListBox that displayed the items in the SampleDataSource.

    I then edited the ItemTemplate of the ListBox.

          Right-Click the ListBox in the Objects and Timeline panel > Edit Additional Templates > Edit Generated Item (Item Template) > Edit Current if available or Edit a Copy.

    The ProgressBar.Value I bound to the Number and the TextBlock.Text to the Name

    <DataTemplate x:Key="ItemTemplate">
    	<StackPanel Orientation="Horizontal">
    		<TextBlock Text="{Binding Name}" Width="100" Height="23.2733325958252" Margin="0,0,5,0"/>
    		<ProgressBar x:Name="progressBar" Height="30" Width="100" Foreground="Lime" BorderBrush="{x:Null}" Background="{x:Null}" SmallChange="1" Value="{Binding Number}" Style="{StaticResource ProgressBarStyle1}">
    			<i:Interaction.Triggers>
    				
    				<ei:PropertyChangedTrigger Binding="{Binding Value, ElementName=progressBar}">
    					<i:Interaction.Behaviors>
    						<ei:ConditionBehavior>
    							<ei:ConditionalExpression>
    								<ei:ComparisonCondition LeftOperand="{Binding Value, ElementName=progressBar}" Operator="GreaterThanOrEqual" RightOperand="50"/>
    							</ei:ConditionalExpression>
    						</ei:ConditionBehavior>
    					</i:Interaction.Behaviors>
    					<ei:ChangePropertyAction TargetName="progressBar" PropertyName="Foreground">
    						<ei:ChangePropertyAction.Value>
    							<SolidColorBrush Color="Red"/>
    						</ei:ChangePropertyAction.Value>
    					</ei:ChangePropertyAction>
    				</ei:PropertyChangedTrigger>
    				
    				<ei:PropertyChangedTrigger Binding="{Binding Value, ElementName=progressBar}">
    					<i:Interaction.Behaviors>
    						<ei:ConditionBehavior>
    							<ei:ConditionalExpression>
    								<ei:ComparisonCondition LeftOperand="{Binding Value, ElementName=progressBar}" Operator="LessThan" RightOperand="50"/>
    							</ei:ConditionalExpression>
    						</ei:ConditionBehavior>
    					</i:Interaction.Behaviors>
    					<ei:ChangePropertyAction PropertyName="Foreground">
    						<ei:ChangePropertyAction.Value>
    							<SolidColorBrush Color="Lime"/>
    						</ei:ChangePropertyAction.Value>
    					</ei:ChangePropertyAction>
    				</ei:PropertyChangedTrigger>
    				
    				<i:EventTrigger EventName="Loaded">
    					<i:Interaction.Behaviors>
    						<ei:ConditionBehavior>
    							<ei:ConditionalExpression>
    								<ei:ComparisonCondition LeftOperand="{Binding Value, ElementName=progressBar}" Operator="GreaterThanOrEqual" RightOperand="50"/>
    							</ei:ConditionalExpression>
    						</ei:ConditionBehavior>
    					</i:Interaction.Behaviors>
    					<ei:ChangePropertyAction PropertyName="Foreground">
    						<ei:ChangePropertyAction.Value>
    							<SolidColorBrush Color="Red"/>
    						</ei:ChangePropertyAction.Value>
    					</ei:ChangePropertyAction>
    				</i:EventTrigger>
    				
    			</i:Interaction.Triggers>
    		</ProgressBar>
    	</StackPanel>
    </DataTemplate>

    In that template I put 3 ChangePropertyActions for changing the ProgressBar's color based on the value.  The first is if the value is 50 or over the color is Red. The second if it is below 50 the color is Lime(Green).  The first 2 are only triggered if a change is made.  So I added the 3rd for the loaded event.

    I did edit the ProgressBar style a bit to get rid of the background and overlay.

    <Style x:Key="ProgressBarStyle1" TargetType="ProgressBar">
    	<Setter Property="Foreground" Value="{x:Null}"/>
    	<Setter Property="Background" Value="{x:Null}"/>
    	<Setter Property="BorderThickness" Value="1"/>
    	<Setter Property="Maximum" Value="100"/>
    	<Setter Property="IsTabStop" Value="False"/>
    	<Setter Property="BorderBrush" Value="Black"/>
    	<Setter Property="Template">
    		<Setter.Value>
    			<ControlTemplate TargetType="ProgressBar">
    				<Grid x:Name="Root">
    					<Border x:Name="ProgressBarTrack" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3" Background="White" BorderBrush="Black"/>
    					<Grid x:Name="ProgressBarRootGrid">
    						<Grid x:Name="DeterminateRoot" Margin="1">
    							<Rectangle x:Name="ProgressBarIndicator" Fill="{TemplateBinding Foreground}" HorizontalAlignment="Left" Margin="{TemplateBinding BorderThickness}" RadiusY="1.5" RadiusX="1.5" StrokeThickness="0.5"/>
    						</Grid>
    					</Grid>
    				</Grid>
    			</ControlTemplate>
    		</Setter.Value>
    	</Setter>
    </Style>

    So basically by changing a value in the EnterDataGrid section, because the binding is TwoWay, the change will be immediatly reflected in the list.

    Some quick tips...

    Once your sample data is created, if you click the Data Panel > List Mode Button.  Then highlight "Collection" and drag it onto your art board, a ListBox will be created for you that you can easily work with and re-template.

    Likewise, if you click the Data Panel > Details Mode button.  In the collection select all the properties, Name and Number, then drag those onto the art board.  A grid with the basic data will be drawn and as you select different items in the ListBox they will show in the detail grid just created.

    Chuck once pointed me to this tutorial when I first started with Blend and working with data ... http://www.kirupa.com/blend_silverlight/intro_sample_data_pg1.htm

    http://www.kirupa.com/blend_silverlight/master_detail_sample_data.htm

    I highly recommend taking the time to walk through them.  It would not take long.

    ~Christine


    Wednesday, March 13, 2013 5:03 PM
  • This is great Christine, thank you so much. Is there anyway that you might be able to email me the file rather than linking to it? We have all "file sharing" sites blocked here so I can't access it. :(

    I'll start looking over everything you posted and trying to see if I can get things working in the mean time.

    Again, thank you!



    Thursday, March 14, 2013 8:06 AM
  • I'd be happy to, but will need an email address please. ~Christine
    Thursday, March 14, 2013 8:15 AM
  • Sorry!


    Thursday, March 14, 2013 8:33 AM
  • No problem. :)  I sent it.

    ~Christine


    Oh and delete your email address from this thread as soon as you get it.  So you don't get any crazy emails. :)
    Thursday, March 14, 2013 8:39 AM