我正在尝试使Avalon MVVM在我的WPF应用程序中兼容。通过谷歌搜索,我发现AvalonEdit is not MVVM friendly和我需要通过创建一个从TextEditor派生的类然后添加必要的依赖项属性来导出AvalonEdit的状态。恐怕格伦沃德先生的答案here令我迷失了:



有没有人有一个例子或对如何实现这个目标有好的建议?

最佳答案

Grunwald先生正在谈论用dependency properties包装TextEditor属性,以便可以绑定(bind)它们。基本思想是这样的(例如,使用CaretOffset属性):

修改后的TextEditor类

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中,您可以将其绑定(bind)到属性,例如在View模型中使用Offset。为了说明起见,将Slider控件的值绑定(bind)到相同的View Model属性Offset,然后看到在移动Slider时,Avalon编辑器的光标位置会更新:

测试XAML
<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();
        }
    }
}

测试 View 模型
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));
        }
    }
}

关于c# - 使AvalonEdit MVVM兼容,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12344367/

10-10 02:25