问题描述
我正在尝试使 Avalon MVVM 在我的 WPF 应用程序中兼容.通过谷歌搜索,我发现 AvalonEdit 不是 MVVM 友好,我需要导出AvalonEdit 的状态通过创建一个从 TextEditor 派生的类然后添加必要的依赖属性.恐怕我完全迷失在格伦瓦尔德先生的回答这里:
I'm trying to make Avalon MVVM compatible in my WPF application. From googling, I found out that AvalonEdit is not MVVM friendly and I need to export the state of AvalonEdit by making a class derived from TextEditor then adding the necessary dependency properties. I'm afraid that I'm quite lost in Herr Grunwald's answer here:
如果你真的需要使用 MVVM 导出编辑器的状态,那么我建议你创建一个派生自 TextEditor 的类,它添加必要的依赖属性并将它们与 AvalonEdit 中的实际属性同步.
有没有人有关于如何实现这一目标的示例或好的建议?
Does anyone have an example or have good suggestions on how to achieve this?
推荐答案
Herr Grunwald 正在谈论用 ,以便您可以绑定到它们.基本思想是这样的(例如使用 CaretOffset 属性):
Herr Grunwald is talking about wrapping the TextEditor
properties with dependency properties, so that you can bind to them. The basic idea is like this (using the CaretOffset property for example):
public class MvvmTextEditor : TextEditor, INotifyPropertyChanged
{
public static DependencyProperty CaretOffsetProperty =
DependencyProperty.Register("CaretOffset", typeof(int), typeof(MvvmTextEditor),
// binding changed callback: set value of underlying property
new PropertyMetadata((obj, args) =>
{
MvvmTextEditor target = (MvvmTextEditor)obj;
target.CaretOffset = (int)args.NewValue;
})
);
public new string Text
{
get { return base.Text; }
set { base.Text = value; }
}
public new int CaretOffset
{
get { return base.CaretOffset; }
set { base.CaretOffset = value; }
}
public int Length { get { return base.Text.Length; } }
protected override void OnTextChanged(EventArgs e)
{
RaisePropertyChanged("Length");
base.OnTextChanged(e);
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
既然 CaretOffset
已经被包裹在一个 DependencyProperty 中,你可以将它绑定到一个属性,比如在你的视图模型中的 Offset
.例如,将 Slider
控件的值绑定到相同的视图模型属性 Offset
,并看到当您移动 Slider 时,Avalon 编辑器的光标位置会更新:
Now that the CaretOffset
has been wrapped in a DependencyProperty, you can bind it to a property, say Offset
in your View Model. For illustration, bind a Slider
control's value to the same View Model property Offset
, and see that when you move the Slider, the Avalon editor's cursor position gets updated:
<Window x:Class="AvalonDemo.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
xmlns:avalonExt="clr-namespace:WpfTest.AvalonExt"
DataContext="{Binding RelativeSource={RelativeSource Self},Path=ViewModel}">
<StackPanel>
<avalonExt:MvvmTextEditor Text="Hello World" CaretOffset="{Binding Offset}" x:Name="editor" />
<Slider Minimum="0" Maximum="{Binding ElementName=editor,Path=Length,Mode=OneWay}"
Value="{Binding Offset}" />
<TextBlock Text="{Binding Path=Offset,StringFormat='Caret Position is {0}'}" />
<TextBlock Text="{Binding Path=Length,ElementName=editor,StringFormat='Length is {0}'}" />
</StackPanel>
</Window>
测试代码隐藏
namespace AvalonDemo
{
public partial class TestWindow : Window
{
public AvalonTestModel ViewModel { get; set; }
public TestWindow()
{
ViewModel = new AvalonTestModel();
InitializeComponent();
}
}
}
测试视图模型
public class AvalonTestModel : INotifyPropertyChanged
{
private int _offset;
public int Offset
{
get { return _offset; }
set
{
_offset = value;
RaisePropertyChanged("Offset");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
这篇关于使 AvalonEdit MVVM 兼容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!