WPF调试AvalonEdit绑定到Document属性 [英] WPF Debugging AvalonEdit binding to Document property

查看:984
本文介绍了WPF调试AvalonEdit绑定到Document属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

整天我坐下来试图找出为什么绑定到AvalonEdits文档属性不起作用。 AvalonEdit是一个高级的WPF文本编辑器 - SharpDevelop项目的一部分(将用于SharpDevelop v4 Mirador)。

all day long I am sitting and trying to find out why binding to AvalonEdits Document property isn't working. AvalonEdit is an advanced WPF text editor - part of the SharpDevelop project.(it's going to be used in SharpDevelop v4 Mirador).

所以当我设置一个简单的项目 - 一个TextEditor(这是库中的AvalonEdits实名),并且做了一个简单的类,它具有一个属性 - Document,它返回一个带有一些静态文本的虚拟对象,绑定正常工作。

So when I set up a simple project - one TextEditor (that's the AvalonEdits real name in the library) and made a simple class that has one property - Document and it returns a dummy object with some static text the binding is working perfectly.

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

However in real life solution I'm binding a collection of SomeEditor objects to TabControl. TabControl has DataTemplate for SomeEditor and there's the TextEditor object.

<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>

这不行。目前为止我已经调查过:

This doesn't work. What I've investigated so far:


  • TextEditor的DataContext设置为SomeEditor的正确实例

  • < text> TextEditors当我将断点设置为附加到该绑定的no-op转换器时,Document属性设置为SomeEditor.Document属性
  • 之外的其他实例,它显示文档的正确值(转换器使用!)

  • 我还通过VisualTree挖掘了TextEditor的引用,并调用了GetBindingExpression(TextEditor.DocumentProperty),这样做没有返回任何

  • DataContext of TextEditor is set to the proper instance of SomeEditor
  • TextEditors Document property is set to some other instance than SomeEditor.Document property
  • when I set breakpoint to no-op converter that is attached to that binding it shows me the correct value for Document (the converter is used!)
  • I also dug through the VisualTree to obtain reference to TextEditor and called GetBindingExpression(TextEditor.DocumentProperty) and this did return nothing

WPF生成以下信息:

WPF produces the following information:

System.Windows.Data信息:10:无法使用绑定和没有有效的回退值存在;使用默认代替。 BindingExpression:Path = Document; DataItem ='SomeEditor'(HashCode = 26280264); target元素是'TextEditor'(Name ='avalonEdit');目标属性是'Document'(类型'TextDocument')

System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=Document; DataItem='SomeEditor' (HashCode=26280264); target element is 'TextEditor' (Name='avalonEdit'); target property is 'Document' (type 'TextDocument')

绑定前已经具有已创建和缓存的Document副本的SomeEditor实例。吸气剂从来不会被调用。

SomeEditor instance that is bound to already has a created and cached copy of Document before the binding occurs. The getter is never called.

任何人都可以告诉我可能是什么错误?为什么没有设置BindingExpression?为什么没有调用物质吸气剂?

Anyone can tell me what might be wrong? Why BindingExpression isn't set ? Why property getter is never called?

//编辑:新测试和新结果

//edit: new tests and new results

我已经阅读了一些更多的内容,代码背后。当我这样做它是有效的。
如何在XAML中设置此功能不起作用,并且在代码中执行相同的操作?

I've read some more and set the binding in code behind. When I do that it works. How come setting this in XAML doesn't work and doing the same thing in code does?

// edit2:代码也会在立即调用后失败将对象添加到用作更高级DataSource的可观察集合(即xaml绑定应该触发后不久)。这让我觉得这是时间问题。任何人都可以告诉你一些事情?

//edit2: The code also fails when called immediately after adding the object to the observable collection that is used as higher level DataSource.(that's not long after the xaml binding should fire). That makes me think this is timing issue. Anyone can tell something about it ?

// edit3:绑定代码:

//edit3: The binding code:

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)
                    {


                    }
                }
            }
        }
    }
}


推荐答案

尝试:

在您直接分配到TextEditor的Document属性的所有地方搜索您的精心申请。它看起来像一些代码,某处正在做一个 avalonEdit.Document = ... ,这将覆盖绑定。我会搜索整个应用程序的匹配案例全字字符串文档和DocumentProperty,并给出每一次的想法,看看是否可以设置此属性。

Search your carefully application for any place at all where you directly assign to the Document property of a TextEditor. It looks like some code, somewhere is doing an avalonEdit.Document = ... which would overwrite the binding. I would search your entire app for the match-case whole-word strings "Document" and "DocumentProperty" and give each occurence a moment's thought to see if it could be setting this property.

在TextEditor.OnDocumentChanged中设置断点,以查看文档是否正确绑定,然后稍后更改。检查使用Just My Code的调用堆栈,并显示外部代码。

Set a breakpoint in TextEditor.OnDocumentChanged to see if the document is being properly bound and then changed back later. Check call stacks with "Just My Code" disabled and showing external code.

尝试在NoopConverter.Convert,SomeEditor.get_Document和TextEditor.OnDocumentChanged中设置断点,以找出精确的操作顺序。另请注意,当显示Binding错误消息时。

Try setting breakpoints in the NoopConverter.Convert, SomeEditor.get_Document, and TextEditor.OnDocumentChanged to figure out the precise sequence of operations. Also note when the Binding error message is shown.

临时修改TextEditor的构造函数,以便在公共静态列表字段中存储每个实例的引用,以便您可以确定哪些TextEditor有创建,然后编写代码,显示他们显示他们的 GetHashCode()和他们的 BindingOperations.GetBindingExpression(editor,DocumentProperty)结果。确保您完成后取出公共静态字段!

Temporarily modify TextEditor's constructor to store a reference to every instance in a public static List field so you can determine which TextEditors have ever been created, then write code that looks through them displaying their GetHashCode() and their BindingOperations.GetBindingExpression(editor, DocumentProperty) results. Make sure you take out the public static field when you're done!

从构建Binding的XAML中取出Path =,以便更好地匹配C#版本。 (我曾经有一个问题,其中XAML解释的路径不同于Binding构造函数,因为传递给PropertyConverter的ITypeDescriptorContext。)与您发布的C#代码完全相同的是 Document ={Binding Document}

Take the "Path=" out of your XAML that constructs the Binding so it will better match the C# version. (I once had a problem where the XAML interpreted the path different than the Binding constructor because of the ITypeDescriptorContext passed to PropertyConverter.) The exact equivalent to the C# code you posted is Document="{Binding Document}".

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

Create a custom trace listener and set a breakpoint in it to get the call stack when the binding error is produced, search up the stack frames to find the objects involved and give them debugger object ids (right-click, Make Object ID), then investigate the actual values of properties to make sure they are as expected.

享受!

这篇关于WPF调试AvalonEdit绑定到Document属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆