Click here to Skip to main content
15,881,752 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi,

I'm new to WPF and C#. In my XAML file, I have a simple Rectangle, where I am binding the width and the fill color:
<Rectangle HorizontalAlignment="Stretch" Height="20" Width="{Binding A.W1}" Fill="{Binding A.B1}"/>


When my program loads, I am reading the width and the color from a file using C# and dynamcially setting the A.W1 with an integer value and A.B1 with a SolidBrushColor value. I know my code is working, because, the width and the color are set correctly @ runtime.

However, the problem I am having is that I need to resize the width of the rectangle and the color during runtime, it does not show the changes in the window screen. How can one change the width/fill properties of a Rectangle during run-time. Note that there are no action events such as mouseover or clicking. I need to change the properties as and when I receive data in my program.

Are there any alternative options on how I can achieve this. Basically, I'm trying to create a bar chart that has a MIN, MAX and MEAN values where the MEAN value will be a red color rectangle that is always width=5. However, visually, the display should change as and when the MIN, MAX and MEAN values change in my code.

Would appreciate any help on this matter.

My XAML looks like the following....the Rectangles are in a DataTemplate and thus I can not get a handle on the Rectangles. I can update the NAME value during runtime and this reflects in the WPF.

The A class implements the INotifyPropertyChanged and has the the correct implementation for the get/set as the data list loaded when first loaded. Subsequent changes to the A.W1 and A.B1 values, reflect in the A OnPropertyChanged event manager, but does not reflect on the WPF screen.

<Window.Resources>
    <ResourceDictionary>
        <CollectionViewSource x:Key="TestDataSource"/>
    </ResourceDictionary>
</Window.Resources>

<DockPanel Name="DP" LastChildFill="False">
    <DataGrid x:Name="DG" ItemsSource="{Binding Source={StaticResource TestDataSource}}"
              HeadersVisibility="Column"
              HorizontalAlignment="Stretch"
              CanUserAddRows="True"
              AutoGenerateColumns="False"
              Margin="0,0,0,0">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Testing" Binding="{Binding NAME}" Width="130*"></DataGridTextColumn>
            <DataGridTemplateColumn x:Name="ABC" Header="ABC Rectangle" Width="103">
                <DataGridTemplateColumn.CellTemplate>

                    <!-- Cant get handle on DataTemplate or other child elements - WHY? -->
                    <DataTemplate x:Name="XYZ">
                        <Grid HorizontalAlignment="Left" VerticalAlignment="Stretch">
                            <StackPanel x:Name="STACK" Grid.Row="0" Orientation="Horizontal">
                                <Rectangle Name="R1" Height="18" Width="{Binding A.W1}" Fill="{Binding A.B1}"/>
                                <Rectangle Name="R2" Height="18" Width="{Binding A.W2}" Fill="{Binding A.B2}"/>
                            </StackPanel>
                        </Grid>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>

    </DataGrid>
</DockPanel>
Posted
Updated 15-Jun-11 8:27am
v2
Comments
Manish V Mahajan 15-Jun-11 16:31pm    
Please note that the values are being updated via a seperate thread running to simulate data updates from a background process:

driverThread = new Thread(new ThreadStart(updateData));

driverThread.Start();

Not sure why, but I was able to resolve the issue with the Width Property by removing the W1, W2 properties from Class A and directly add them to the TestDataSource ViewModel Object - List<testdata>.

This seems to work for the Width Property only. To further explain what I did earlier....I have a List<testdata.cs> that contains all the data elements and is bound to the TestDataSource in the CollectionViewSource.

In the TestData.cs, I had previously created a custom object BarChart (this is the A object referenced above in the XAML). In the A.cs (also implementing INotifyPropertyChanged), I had W1 as int and B1 as Brush. I removed the W1 and B1 from A and moved it to TestData and changed by Binding references to just W1 and B1 in the XAML - this seemed to work for W1 only...issue with B1...see below.

When I perform the following on the TestData (implements INotifyPropertyChanged) object, I am now getting a Dependancy Issue.

td.W1 = 10....or any other Integer - This updates fine if I comment out the td.B1 from my code.

td.B1 = new SolidColorBrush(Colors.Green) - this fails (Must create DependencySource on same Thread as the DependencyObject.

Why does the Width property change, but I need a DependencySource on the other property? Also, how can I resolve this issue. Thanks,Manish

1 solution

The reason you get a thread error when you update your brush is because all graphical objects are expecting a single threaded always.

Now fortunately for you in this case, there is an exception and that is the Freezable class which all brushes inherit from. Those can, after they have been frozen, be shared between threads.

To make a long story short, make sure you call myNewBrush.Freeze() before assigning it to the databound property.
 
Share this answer
 
Comments
Manish V Mahajan 16-Jun-11 8:32am    
Dude, you are a genius man....this worked!!!!

I would only ask one additional favor for now...as I am learning C# and WPF....can you recommend any books or materials that I can use to learn. I've been seaching the web for things like this, and it's all bits of information, here and there - which is fine, but would like to get a good foundation and understanding of how things works with some simple examples.

Thanks again for your input!!!!!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900