c# - LogicalTreeHelper.GetChildren - ObservableCollection Move() 导致 DataTemplate 中的 ContentControl 丢失其内容?

标签 c# wpf recursion observablecollection visualtreehelper

这很奇怪。下面代码的要点是支持一个 attachedProperty,如果它的任何子元素获得焦点,它会通知容器。

即我有一个 Grid,它的 Content 中某处有一个文本框,如果其中一个控件获得焦点,我想将 Grid 变成蓝色。

我有一个带有 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 的“Content”。

但是...一旦我在 ListView ItemsSource 绑定(bind)到的 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);
  }
}

最佳答案

你好,

以下是解决问题的建议:

我不确定我是否正确拼写了 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 属性是什么。

关于c# - LogicalTreeHelper.GetChildren - ObservableCollection Move() 导致 DataTemplate 中的 ContentControl 丢失其内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15285041/

相关文章:

c# - 动态生成、分组和绑定(bind)单选按钮到枚举

mysql - SQL/MySQL 递归地从同一个表中提取

python - 使用递归从字符列表打印 n 长度组合

c# - TF30063 : You are not authorized . .. 编程访问不起作用

c# - 用于 .NET/C# 编程的最佳等效 VisualStudio IDE for Mac

c# - 如何调用ListView的SelectionChanged方法?

wpf - 如何在 WPF 中重新设置 TabControl 的样式

c# - 如何选择带触发器的DataTemplate?

c# - 在 Asp.NET MVC 中排除空表单数据

java - 在 Java 中使用递归打印长度为 N 的位串的排列