1

私は一日中座って、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)
                    {


                    }
                }
            }
        }
    }
}
4

2 に答える 2

2

さらに6つのことを試してみてください。

TextEditorのDocumentプロパティに直接割り当てる場所を注意深くアプリケーションで検索します。いくつかのコードのように見えますが、どこかでavalonEdit.Document = ...バインディングを上書きするコードを実行しています。アプリ全体でマッチケースの単語全体の文字列「Document」と「DocumentProperty」を検索し、各オカレンスにこのプロパティを設定できるかどうかを考えてみます。

TextEditor.OnDocumentChangedにブレークポイントを設定して、ドキュメントが適切にバインドされ、後で元に戻されているかどうかを確認します。「JustMyCode」が無効になっていて、外部コードが表示されているコールスタックを確認します。

NoopConverter.Convert、SomeEditor.get_Document、およびTextEditor.OnDocumentChangedでブレークポイントを設定して、操作の正確なシーケンスを把握してください。バインディングエラーメッセージが表示された場合にも注意してください。

TextEditorのコンストラクターを一時的に変更して、すべてのインスタンスへの参照をパブリック静的リストフィールドに格納します。これにより、これまでに作成されたTextEditorを特定し、それらを調べてそれらGetHashCode()とそのBindingOperations.GetBindingExpression(editor, DocumentProperty)結果を表示するコードを記述できます。完了したら、必ずパブリック静的フィールドを削除してください。

バインディングを構成するXAMLから「Path=」を取り出して、C#バージョンとの一致度を高めます。(私はかつて、PropertyConverterに渡されたITypeDescriptorContextのために、XAMLがBindingコンストラクターとは異なるパスを解釈するという問題を抱えていました。)投稿したC#コードとまったく同じものはですDocument="{Binding Document}"

カスタムトレースリスナーを作成し、それにブレークポイントを設定して、バインディングエラーが発生したときに呼び出しスタックを取得し、スタックフレームを検索して関連するオブジェクトを見つけ、デバッガーオブジェクトID(右クリック、[オブジェクトIDの作成])を指定します。プロパティの実際の値を調べて、期待どおりであることを確認します。

楽しみ!

于 2010-06-15T19:56:47.977 に答える
0

ただの観察:私は同じ問題を抱えていて、AvalonEditソースを調べました。問題は、TextEditorコンストラクターがDocumentプロパティを上書きする(新しいTextDocumentをインスタンス化する)ことだと思われます。これをコメントアウトすると、バインディングは機能します。ただし、バインディングがない場合は、さらに変更を加える必要があります。これについて作者と話し合い、パッチを提案するつもりです。

于 2010-08-31T12:07:57.683 に答える