2010-06-07 144 views
1

我整天坐在一边,试图找出为什么绑定到AvalonEdits文档属性不起作用。 AvalonEdit是一个先进的WPF文本编辑器 - SharpDevelop项目的一部分(将在SharpDevelop v4 Mirador中使用)。WPF调试AvalonEdit绑定到文档属性

因此,当我建立一个简单的项目 - 一个TextEditor(这是库中的AvalonEdits实名)并且创建了一个具有一个属性的简单类--Document并且它返回一个带有一些静态文本的虚拟对象,该绑定正在工作完美。

但是在现实生活中,我将SomeEditor对象的集合绑定到TabControl。 TabControl具有用于SomeEditor的DataTemplate,并且存在TextEditor对象。

<TabControl Grid.Column="1" x:Name="tabControlFiles" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" > 
<TabControl.Resources> 
    <DataTemplate DataType="{x:Type m:SomeEditor}"> 
    <a:TextEditor 
    Document="{Binding Path=Document, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource NoopConverter}, IsAsync=True}" 
    x:Name="avalonEdit"></a:TextEditor> 
    </DataTemplate> 
</TabControl.Resources> 

<TabControl.ItemContainerStyle> 
    <Style BasedOn="{StaticResource TabItemStyle}" TargetType="{x:Type TabItem}"> 
    <Setter Property="IsSelected" Value="{Binding IsSelected}"></Setter> 
    </Style> 
</TabControl.ItemContainerStyle> 
</TabControl> 

这是行不通的。什么到目前为止,我已经调查:

  • 文本编辑的DataContext设置
  • TextEditors文件属性设置为一些其他的实例比SomeEditor.Document财产
  • SomeEditor的正常情况下,当我设置断点附加到该绑定它无操作器显示我要文件的正确值(转换器使用!)
  • 我还通过挖的VisualTree获得参考文本编辑,并呼吁GetBindingExpression(TextEditor.DocumentProperty),这没有任何回报

  • WPF产生以下信息:

    System.Windows.Data信息:10:使用结合和没有有效的回退值存在无法检索值;改为使用默认值。 BindingExpression:路径=文档; DataItem ='SomeEditor'(HashCode = 26280264);目标元素是'TextEditor'(Name ='avalonEdit');目标属性为'文档'(类型'TextDocument')

  • 绑定到的SomeEditor实例已经在绑定发生之前创建并缓存了Document的副本。吸气剂从不叫。

任何人都可以告诉我什么可能是错的?为什么BindingExpression没有设置?为什么属性getter不会被调用?

//编辑:新的考验,新成果

我读过一些,并设置在代码背后的结合。当我这样做的时候,它会有效。 如何在XAML中设置它不起作用,并在代码中做同样的事情呢?

//编辑2:在将对象添加到用作更高级别DataSource的可观察集合后(即在xaml绑定应激后不久),该代码也会失败。这让我觉得这是计时问题。任何人都可以讲述这件事吗?

// EDIT3:绑定代码:

private List<T> GetObjectOfTypeInVisualTree<T>(DependencyObject dpob) where T : DependencyObject 
{ 
    int count = VisualTreeHelper.GetChildrenCount(dpob); 
    List<T> returnlist = new List<T>(); 

    for (int i = 0; i < count; i++) 
    { 
     DependencyObject child = VisualTreeHelper.GetChild(dpob, i); 
     T childAsT = child as T; 
     if (childAsT != null) 
     { 
      returnlist.Add(childAsT); 
     } 
     List<T> lst = GetObjectOfTypeInVisualTree<T>(child); 
     if (lst != null) 
     { 
      returnlist.AddRange(lst); 
     } 
    } 
    if (returnlist.Count > 0) 
    { 
     return returnlist; 
    } 
    return null; 
} 

private void RebindMenuItem_Click(object sender, RoutedEventArgs e) 
{ 
    foreach (XHTMLStudioPrototypeFileEditor ed in CurrentProject.OpenedFiles) 
    { 

     List<ContentPresenter> cps = GetObjectOfTypeInVisualTree<ContentPresenter>(tabControlFiles); 
     if (cps != null) 
     { 
      foreach (ContentPresenter cp in cps) 
      { 

       foreach (DataTemplate dt in tabControlFiles.Resources.Values) 
       { 
        try 
        { 
         object o = dt.FindName("avalonEdit", cp); 
         TextEditor ted = (TextEditor)o; 

         bool isDataBound = BindingOperations.IsDataBound(ted, TextEditor.DocumentProperty); 
         if (!isDataBound) 
         { 
          BindingOperations.SetBinding(ted, TextEditor.DocumentProperty, new Binding("Document")); 
         } 
         Console.WriteLine(isDataBound); 
        } 
        catch (Exception) 
        { 


        } 
       } 
      } 
     } 
    } 
} 
+0

您可以显示您用于以编程方式创建绑定的代码吗?另外,如果删除IsAsync,会发生什么情况? – JustABill 2010-06-09 01:39:10

+0

如果我删除IsAsync,则不会发生任何情况。我正在尝试每个组合都有它的工作。 – kubal5003 2010-06-09 07:19:34

回答

2

这里有六个更多的事情尝试:

搜索您精心申请任何地方都在那里你直接分配到的文档属性文本编辑器。它看起来像一些代码,某处正在做一个avalonEdit.Document = ...它会覆盖绑定。我会搜索你的整个应用程序的匹配全字符字符串“文档”和“DocumentProperty”,并给每一个想法,看看它是否可以设置此属性。

在TextEditor.OnDocumentChanged中设置断点,以查看文档是否被正确绑定,然后再返回。检查“Just My Code”已禁用并显示外部代码的调用堆栈。

尝试在NoopConverter.Convert,SomeEditor.get_Document和TextEditor.OnDocumentChanged中设置断点,以确定操作的精确顺序。还要注意显示“绑定”错误消息的时间。

临时修改文本编辑的构造来存储在一个公共的静态列表字段每个实例的引用,因此您可以决定哪些曾经被创建TextEditors,然后编写代码,看起来通过他们展示自己的GetHashCode()及其BindingOperations.GetBindingExpression(editor, DocumentProperty)结果。确保在完成后取出公共静态字段!

从构建绑定的XAML中取出“Path =”,以便更好地匹配C#版本。 (我曾经遇到过一个问题,即由于传递给PropertyConverter的ITypeDescriptorContext,XAML解释的路径与Binding构造函数不同。)与您发布的C#代码的确切等效参数是Document="{Binding Document}"

创建自定义跟踪侦听器并在其中设置断点以在产生绑定错误时获取调用堆栈,搜索堆栈帧以查找涉及的对象并为其提供调试器对象标识(右键单击,使对象ID),然后调查属性的实际值以确保它们符合预期。

享受!

+0

我会简单回答一下几点。 1)完成,没有结果。 2)首先完成。 3)每次都有不同的结果 - 可能不同的线程正在进行绑定,其余的都是。 4)&​​5)创建文本编辑器没有问题。我已经检查过了。我总是得到一个新的实例,我知道C#代码是可以的 - 它工作。 现在最终的结果是:经过几次清理和建设后,突然开始工作。我不知道是什么原因,但我仍然猜测是线程安全和时机。我想并不是所有的代码都是线程安全的,这就是为什么它表现得如此奇怪。 – kubal5003 2010-06-15 22:39:37

+0

几天后,我下载了AvalonDock,并要求以另一种方式重写 - 现在我可以直接访问AvalonEdit实例,我可以做任何我想做的事情。它正在工作。 非常感谢您的回答。这是非常彻底的,你提出了宝贵的调试技术。赏金是你的。 – kubal5003 2010-06-15 22:42:35

0

只是一个观察:我有同样的问题,并通过AvalonEdit来源看;看起来问题在于TextEditor构造函数覆盖了Document属性(实例化了一个新的TextDocument);如果你评论这一点,绑定工作;但是,如果您没有绑定,则需要进一步修改。我会试着与作者讨论这个问题,也许会提出一个补丁。