20

I have a data-template

<Window.Resources>
         <DataTemplate x:Key="BarChartItemsTemplate">
         <Border Width="385" Height="50">
            <Grid>
               <Rectangle Name="rectangleBarChart" Fill="MediumOrchid" StrokeThickness="2" Height="40" Width="{Binding}" HorizontalAlignment="Right" VerticalAlignment="Bottom">
                  <Rectangle.LayoutTransform>
                     <ScaleTransform ScaleX="4"/>
                  </Rectangle.LayoutTransform>
               </Rectangle>
               <TextBlock Margin="14" FontWeight="Bold" HorizontalAlignment="Right" VerticalAlignment="Center" Text="{Binding}">
                  <TextBlock.LayoutTransform>
                     <TransformGroup>
                        <RotateTransform Angle="90"/>
                        <ScaleTransform ScaleX="-1" ScaleY="1"/>
                     </TransformGroup>
                  </TextBlock.LayoutTransform>
               </TextBlock>
            </Grid>
         </Border>
      </DataTemplate>
  </Window.Resources>

I have a button on the form. I need to change the scale(scaleTransform) the rectangle from the dataTemplate. How am I supposed to access the 'rectangleBarChart' element in the Button_Click event of the above mentioned button ?

H.B.
  • 166,899
  • 29
  • 327
  • 400
Robert Langdon
  • 855
  • 1
  • 11
  • 27

2 Answers2

38

I use this function a lot in my WPF programs to find children elements:

public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
   if (depObj != null)
   {
       for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
       {
           DependencyObject child = VisualTreeHelper.GetChild(depObj, i);

           if (child != null && child is T)
               yield return (T)child;

           foreach (T childOfChild in FindVisualChildren<T>(child))
               yield return childOfChild;
       }
   }
}

Usage:

foreach (var rectangle in FindVisualChildren<Rectangle>(this))
{
  if (rectangle.Name == "rectangleBarChart")
  {
    /*   Your code here  */
  }
}
Mafii
  • 7,227
  • 1
  • 35
  • 55
Mark Oreta
  • 10,346
  • 1
  • 33
  • 36
  • Thanks man I am able to get into the if block after finding the element, but after changing some properties of the rectangle suppose rectangle.Fill=Brushes.Red, these changes are not reflected back.( I am using the above mentioned dataTemplate as my ItemTemplate for a ListBox) So how to update the changes to the ListBox ? – Robert Langdon Aug 06 '12 at 11:46
  • You are a saint! This works great. I could not get other solutions to work. – nikotromus Apr 24 '18 at 21:10
4

Do not do it. If you need to change something in a DataTemplate then bind the respective properties and modify the underlying data. Also i would recommend binding the Button.Command to an ICommand on your data/view-model (see MVVM) instead of using events, then you are in the right context already and the view does not need to do anything.

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • @H. B. - I am using the DataTemplate as follows: I am able to access the ListBox in my code-behind but I want to scale the rectangle and reflect the changes again to the UI. For that I did: rectangle.Fill = Brushes.MediumVioletRed; rectangle.Height = 10; rectangle.LayoutTransform = new ScaleTransform(2, 1); – Robert Langdon Aug 07 '12 at 05:55
  • @GrowWithWPF: So what? Nothing prevents you from binding all those properties in the template and changing the bound object instead. – H.B. Aug 07 '12 at 20:58