私は一日中座って、AvalonEditsDocumentプロパティへのバインドが機能しない理由を調べようとしています。AvalonEditは、SharpDevelopプロジェクトの一部である高度なWPFテキストエディターです(SharpDevelop v4 Miradorで使用される予定です)。
したがって、単純なプロジェクト(1つのTextEditor(ライブラリ内のAvalonEditsの実名)を設定し、1つのプロパティを持つ単純なクラスを作成した場合)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プロパティ以外のインスタンスに設定されています
- そのバインディングに接続されているno-opコンバーターにブレークポイントを設定すると、Documentの正しい値が表示されます(コンバーターが使用されます!)
また、VisualTreeを掘り下げてTextEditorへの参照を取得し、GetBindingExpression(TextEditor.DocumentProperty)を呼び出しましたが、これは何も返しませんでした。
WPFは次の情報を生成します。
System.Windows.Data情報:10:バインディングを使用して値を取得できず、有効なフォールバック値が存在しません。代わりにデフォルトを使用します。BindingExpression:Path = Document; DataItem ='SomeEditor'(HashCode = 26280264); ターゲット要素は'TextEditor'(Name ='avalonEdit');です。ターゲットプロパティは'Document'(タイプ'TextDocument')です
バインドされているSomeEditorインスタンスには、バインドが発生する前に、ドキュメントの作成およびキャッシュされたコピーがすでにあります。ゲッターが呼び出されることはありません。
誰が私に何が間違っているのか教えてもらえますか?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)
{
}
}
}
}
}
}