私は現在、ユーザーが動的にコンパイルおよび実行される C# スクリプトを入力するプロジェクトに取り組んでいます。後でプロジェクトの他の側面について質問する可能性があるため、詳細についてはここでは省略します。
私には制御できない高レベルの決定がいくつかあるため、ユーザー インターフェイスは WPF を使用して開発され、Quantum Whale Editor.NET コントロールがエディターとして使用されます。悲しいことに、QWhale Editor.NET の WPF バージョンはまだ完全に成熟していないようです。そのため、ドキュメントが不足しており、最悪の場合、バインディング フレンドリーではないようです。
私はまだ WPF に慣れていませんが、MVVM にはある程度慣れているので、それを適用したいと思っています。ただし、評価版をテストしていて、エディターのテキストをモデルのプロパティにバインドしようとしたときに最初の課題に直面し、それが不可能であるという例外を受け取りました。
タイプ 'TextEditor' の 'Text' プロパティに 'Binding' を設定することはできません。「Binding」は、DependencyObject の DependencyProperty でのみ設定できます。
代替案を確認しながら AvalonEdit を試してみたところ、別のスタック オーバーフローの質問であるMaking AvalonEdit MVVM Compatibleを思い出しました。そして、私は同じコンセプトに従いました。
エディターから継承するクラスを定義し、依存関係プロパティを追加して、最初Text
はnew
. しかし、明らかにそれはロング ショットであり、私のプロパティは使用されませんでした。基本プロパティが直接呼び出されていました。
それが失敗したら、 という新しいプロパティを定義しましたDocumentText
。私はそれを wrapbase.Text
にし、それを使用してバインディングを定義し、それに応じて一方向のバインディングが機能するようにしました。それはモデルからコントロールまでです。しかし、私が見つけたものから、バインディングを他の方向に動作させる最良の方法はoverride
、OnTextChanged
イベント (または同等のもの) にプロパティ変更通知を発生させることです。問題は、奇妙に聞こえるかもしれませんが、コントロールにそのようなイベントがないことです。
これで、テキストを変更する可能性のあるすべてのアクション (入力、ドラッグ & ドロップ、貼り付けなど) を処理できるように、おそらく他のイベント (OnKeyUp、OnMouseClick など) の束をオーバーライドできますが、それもあまりないようです。実用的であり、後でバインドすることに関心がある可能性のある他のプロパティには再現できない可能性があります。そして、時間を見つけて数日間オンラインで検索した後でも、他のアイデアを見つけるにはまだ近づいていません. それで、コントロール自体のコードに飛び込む以外に、私の問題に対する適切な解決策はありますか? (おそらく、ライセンスによってソースコードにアクセスできるようになりますが、それを直接変更することは避けたいと思います)。
探しているものがこの特定のコントロールに依存しないと感じたため、質問のタイトルとタグで QWhale エディターを指定することは避けました。間違っている場合は修正してください。
別のコンピューターを使用しているため、現時点ではテスト コードを提供できませんが、必要であると思われる場合は、メモを残してください。追加します。
更新: これがコードです。問題を明確に説明できたかどうか確信が持てないためです。
class ExtenEdit : TextEditor
{
public static DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(ExtenEdit),
new PropertyMetadata((obj, args) =>
{
TextEditor target = (TextEditor)obj;
target.DocumentText = (string)args.NewValue;
})
);
public new string Text
{
get { return base.Text; }
set
{
if (base.Text != value)
{
base.Text = value;
}
}
}
}
の値を変更すると機能しViewModel
ますが、エディターに入力すると、プロパティがバイパスされ、基本プロパティが直接呼び出されます。次のようなものを追加すると機能します。
protected override void OnKeyUp(System.Windows.Input.KeyEventArgs e)
{
SetCurrentValue(TextProperty, base.Text);
base.OnKeyUp(e);
}
しかし、上で述べたように、それを有効な「クリーンな」ソリューションとは考えられません。
そして、これが私の XAML の関連部分です (私が AvalonDock でも遊んでいることがわかります)。
名前空間:
<Window x:Class="AvalonDockQWhale.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:avalonDock="http://avalondock.codeplex.com"
xmlns:converter="clr-namespace:AvalonDockQWhale.Converter"
xmlns:pane="clr-namespace:AvalonDockQWhale.View.Pane"
xmlns:editor="clr-namespace:QWhale.Editor.Wpf;assembly=QWhale.Editor.Wpf"
xmlns:control="clr-namespace:AvalonDockQWhale.Control"
xmlns:controlHelper="clr-namespace:AvalonDockQWhale.ControlHelper"
x:Name="mainWindow"
Title="MainWindow" Height="600" Width="800">
そして、私の最初の試みのバインディング:
<control:ExtenEdit Text="{Binding Path=ScriptText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
DHN のソリューションで試したバインディング:
<editor:TextEditor controlHelper:AttachedProperties.Text="{Binding ScriptText}" />
と
<editor:TextEditor controlHelper:AttachedProperties.Text="{Binding Path=ScriptText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
最終的な詳細: DHN からの回答を受け入れましたが、私の特定のケースでは機能しませんが、同様の問題に対する適切な解決策と思われるためです。