views:

395

answers:

1

Upgrading from SL3 -> SL4. First problem: this throws a parser exception:

<StackPanel Name={Binding} /> (same with x:Name)

Collection is ObservableCollection<string>. Worked fine in SL3. So it seems that SL4 doen't allow binding to the Name property. Huh?

So: changed to

<StackPanel Tag={Binding} />

... since I just need to ID the control in code behind. So here's the bug ('cuz this has got to be a bug!):

In this frag, AllAvailableItems is an ObservableCollection<string>:

<ItemsControl Name="lbItems"
                  ItemsSource="{Binding AllAvailableItems}"
                  Height="Auto"
                  Width="Auto"
                  BorderBrush="Transparent"
                  BorderThickness="0"
                  VerticalAlignment="Top"
                  HorizontalAlignment="Left"
                  Margin="12,6,0,0">
        <ItemsControl.ItemTemplate>
            <DataTemplate>

                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>

                    <CheckBox Tag="{Binding}"
                              Checked="ItemChecked_Click"
                              Unchecked="ItemUnchecked_Click"
                              Style="{StaticResource CheckBoxStyle}"
                              Grid.Row="0">
                        <CheckBox.Content>
                            <TextBlock Text="{Binding}"
                                       Style="{StaticResource FormLJustStyle}" />
                        </CheckBox.Content>
                    </CheckBox>

                    <StackPanel Tag="{Binding}"
                                Orientation="Vertical"
                                Grid.Row="1">
                        <configControls:ucLanguage /> <!-- simple user control -->
                    </StackPanel>

                </Grid>

            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

In the code behind, I use a recursive function to find the Dependency object with either the Name or Tag property provided:

public static T FindVisualChildByName<T>(DependencyObject parent, string name, DependencyProperty propToUse) where T : DependencyObject
    {
      for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
      {
        var child = VisualTreeHelper.GetChild(parent, i);
        string controlName = child.GetValue(propToUse) as string;
        if (controlName == name)
        {
          return child as T;
        }
        else
        {
          T result = FindVisualChildByName<T>(child, name, propToUse);
          if (result != null)
            return result;
        }
      }
      return null;
    }

OK, get this: in the code behind, I can get the control that is ORDERED FIRST in the XAML! In other words, if I put the CheckBox first, I can retrieve the CheckBox, but no StackPanel. And vice-versa. This all worked fine in SL3.

Any help, ideas ... ?

Thanks - Kurt

A: 

This is not a bug.

Your loop will never go past the first object because you return the child upon first match.

Add it to a collection and return a collection instead.

Something like so:

public static IEnumerable<T> FindVisualChildrenByName<T>(DependencyObject parent, string name, DependencyProperty propToUse) where T : DependencyObject
{
  List<T> children = new List<T>();
  for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
  {
    var child = VisualTreeHelper.GetChild(parent, i);
    string controlName = child.GetValue(propToUse) as string;
    if (controlName == name)
    {
      children.add(child as T);
    }
   // ...
  }
  return children;
}

EDIT: This of course is granted that you don't call your code multiple times using the return child element. In that case, you should provide the calling method code, so we can see what you're doing.

Sheeo
I found this myself earlier today - because SL4 doesn't let you bind to Name or x:Name, I switched to Tag, and in doing so introduced this bug. I fixed it by checking the type like so:if (controlName == name }The cast was failing - since there were 2 controls with the same Tag property! Easy fix, shoulda caught it sooner. Sometimes when you are upgrading to a new major version there's an inclination to imagine bugs, eh? Thank the good dude!
Kurt