LogicalTreeHelper.GetChildren - ObservableCollection Move()导致DataTemplate中的ContentControl失去它的内容?

时间:2013-03-08 01:13:33

标签: c# wpf recursion observablecollection visualtreehelper

这很奇怪。下面代码的要点是支持attachProperty,如果容器的任何一个孩子已经获得焦点,它将通知容器。

即。我的内容中有一个带有textBox的Grid,如果其中一个控件获得焦点,我想将Grid Blue变为蓝色。

我有一个带有ItemsTemplate的ListView。 ItemsTemplate是一个包含一些东西的DataTemplate ......但其中一个是ContentControl。

示例:

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

ContentControl上的Binding应该显示某种类型的UserControl。 创作后......工作得很好。如果我以Grid元素开始递归迭代listViewItem的模板......它也会遍历ContentControl的“内容”。

HOWEVER ...一旦我在ListView ItemsSource绑定的ObservableCollection上执行了.Move(),根据LogicalTreeHelper,ContentControl.Content为空。

是什么给出了?

如果我检查ContentControl,它会向我显示内容......但是LogicalTreeHelper.GetChildren返回并清空Enumerator。

我很困惑......

任何人都可以解释为什么会这样吗?

LogicalTreeHelper迭代器方法

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);
  }
}

1 个答案:

答案 0 :(得分:0)

阿罗哈,

以下是您如何解决问题的建议:

我不确定我是否拼写了GotFocus事件,但它是一个RoutedEvent,你可以在视觉树的任何地方使用它。

如果您的某个项目获得了焦点,您的ListView将会收到通知,并且在处理程序中您可以执行任何操作。

这个怎么样:

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

这只是一些随机逻辑来证明你可以做什么。

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是一个RoutedEvent,如果被触发,它将冒泡视觉树。因此,在某处捕获事件并检查哪个是触发事件的原始源对象。或者检查触发事件的对象的ViewModel属性是什么。