2

This is very strange. The point of the code below is to support an attachedProperty which will notify a container if any of it's children have received focus.

i.e. I have a Grid with a textBox somewhere in it's Content and I want to turn the Grid Blue if one of those controls gets focus.

I have a ListView with an ItemsTemplate. The ItemsTemplate is a DataTemplate containing a few things...but one of them being a ContentControl.

Example:

<ListView>
   <ListView.ItemTemplate>
      <DataTemplate>
         <Grid>
           <Border>
            <ContentControl Content="{Binding Something}"/>
           </Border>
         </Grid>
      </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

The Binding on the ContentControl should display a certain type of UserControl. Upon creation...works just fine. If I recursively iterate template of the listViewItem starting with the Grid element...it will traverse the ContentControl's "Content" as well.

HOWEVER...once I do a .Move() on the ObservableCollection that the ListView ItemsSource is bound to, the ContentControl.Content is empty according to the LogicalTreeHelper.

What gives?

If I inspect the ContentControl, it SHOWS me the content...but LogicalTreeHelper.GetChildren returns and empty Enumerator.

I'm confused...

Can anyone explain why this would be the case?

LogicalTreeHelper iterator method

public static void applyFocusNotificationToChildren(DependencyObject parent)
{
  var children = LogicalTreeHelper.GetChildren(parent);

  foreach (var child in children)
  {
    var frameworkElement = child as FrameworkElement;

    if (frameworkElement == null)
      continue;

    Type frameworkType = frameworkElement.GetType();

    if (frameworkType == typeof(TextBox) || frameworkType == typeof(ListView) ||
      frameworkType == typeof(ListBox) || frameworkType == typeof(ItemsControl) ||
      frameworkType == typeof(ComboBox) || frameworkType == typeof(CheckBox))
    {
      frameworkElement.GotFocus -= frameworkElement_GotFocus;
      frameworkElement.GotFocus += frameworkElement_GotFocus;

      frameworkElement.LostFocus -= frameworkElement_LostFocus;
      frameworkElement.LostFocus += frameworkElement_LostFocus;

      // If the child's name is set for search
    }

    applyFocusNotificationToChildren(child as DependencyObject);
  }
}
tronious
  • 1,547
  • 2
  • 28
  • 45

1 Answers1

0

Aloha,

Here is an suggetion how you could solve your problem:

I am not sure if i spelled right the GotFocus event but its a RoutedEvent and you can use it anywhere in your visual tree.

If one of your items receives a focus your ListView will get notified and inside the handler you can do whatever you want.

How about this:

<ListView GotFocus="OnGotFocus">
   <ListView.ItemTemplate>
      <DataTemplate>
         <Grid>
           <Border>
            <ContentControl Content="{Binding Something}"/>
           </Border>
         </Grid>
      </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

This is just some random logic to demonstrate what you can do.

public void OnGotFocus(object sender, RoutedEventArgs e)
{
  TreeViewItem item = sender as TreeViewItem;

  if(((MyViewModel)item.Content).SomeColor == "Blue")
  {
    Grid g = VisualTreeHelper.GetChild(item, 0) as Grid;
    g.Background = Colors.Blue;
  }
}

GotFocus is a RoutedEvent which will bubble up the visual tree if fired. So catch the event somewhere and inspect which was the original source object that fired the event. Or inspect what was the ViewModel propery of the object which fired the event.

snowy hedgehog
  • 652
  • 1
  • 7
  • 23