我整天坐着,试图找出为什么绑定到 AvalonEdits Document 属性不起作用。AvalonEdit 是一个高级 WPF 文本编辑器 - SharpDevelop 项目的一部分。(它将在 SharpDevelop v4 Mirador 中使用)。
因此,当我建立一个简单的项目时——一个 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>
这行不通。到目前为止我调查的内容:
- TextEditor 的 DataContext 设置为 SomeEditor 的正确实例
- TextEditors Document 属性设置为 SomeEditor.Document 属性以外的其他实例
- 当我将断点设置为附加到该绑定的无操作转换器时,它会向我显示 Document 的正确值(使用了转换器!)
我还挖掘了 VisualTree 以获取对 TextEditor 的引用并调用 GetBindingExpression(TextEditor.DocumentProperty) 但这并没有返回任何内容
WPF 产生以下信息:
System.Windows.Data 信息:10:无法使用绑定检索值,并且不存在有效的备用值;改用默认值。绑定表达式:路径=文档;DataItem='SomeEditor' (HashCode=26280264); 目标元素是'TextEditor'(名称='avalonEdit');目标属性是“文档”(类型“文本文档”)
绑定到的 SomeEditor 实例在绑定发生之前已经创建并缓存了 Document 的副本。getter 永远不会被调用。
谁能告诉我可能出了什么问题?为什么没有设置 BindingExpression ?为什么永远不会调用属性获取器?
//编辑:新测试和新结果
我已经阅读了更多内容并在后面的代码中设置了绑定。当我这样做时,它会起作用。为什么在 XAML 中设置它不起作用而在代码中做同样的事情呢?
//edit2:在将对象添加到用作更高级别数据源的可观察集合后立即调用代码也会失败。(在 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)
{
}
}
}
}
}
}