使AvalonEdit MVVM兼容

l46*_*kok 18 .net c# wpf mvvm avalonedit

我正在尝试在我的WPF应用程序中使Avalon MVVM兼容.从谷歌搜索,我发现AvalonEdit不是MVVM友好的,我需要通过创建一个派生自TextEditor的类然后添加必要的依赖属性来导出AvalonEdit的状态.我担心Herr Grunwald 在这里的回答让我很失落:

如果你真的需要使用MVVM导出编辑器的状态,那么我建议你创建一个派生自TextEditor的类,它添加必要的依赖属性并将它们与AvalonEdit中的实际属性同步.

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

McG*_*gle 27

Herr Grunwald正在谈论TextEditor依赖属性包装属性,以便您可以绑定它们.基本思想是这样的(例如使用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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在CaretOffset已经将它包装在DependencyProperty中,您可以将它绑定到属性,例如Offset在View Model中.为了说明,将Slider控件的值绑定到相同的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>
Run Code Online (Sandbox Code Playgroud)

测试代码落后

namespace AvalonDemo
{
    public partial class TestWindow : Window
    {
        public AvalonTestModel ViewModel { get; set; }

        public TestWindow()
        {
            ViewModel = new AvalonTestModel();
            InitializeComponent();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

测试视图模型

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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 编写一个不支持MVVM的WPF控件似乎很天真.也许更好的方法是让每个人都告诉作者这个,并鼓励他写出更好的组件? (3认同)

Fre*_*ric 6

您可以使用编辑器中的Document属性并将其绑定到ViewModel的属性.

以下是视图的代码:

<Window x:Class="AvalonEditIntegration.UI.View"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:AvalonEdit="clr-namespace:ICSharpCode.AvalonEdit;assembly=ICSharpCode.AvalonEdit"
        Title="Window1"
        WindowStartupLocation="CenterScreen"
        Width="500"
        Height="500">
    <DockPanel>
        <Button Content="Show code"
                Command="{Binding ShowCode}"
                Height="50"
                DockPanel.Dock="Bottom" />
        <AvalonEdit:TextEditor ShowLineNumbers="True"
                               Document="{Binding Path=Document}"
                               FontFamily="Consolas"
                               FontSize="10pt" />
    </DockPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)

以及ViewModel的代码:

namespace AvalonEditIntegration.UI
{
    using System.Windows;
    using System.Windows.Input;
    using ICSharpCode.AvalonEdit.Document;

    public class ViewModel
    {
        public ViewModel()
        {
            ShowCode = new DelegatingCommand(Show);
            Document = new TextDocument();
        }

        public ICommand ShowCode { get; private set; }
        public TextDocument Document { get; set; }

        private void Show()
        {
            MessageBox.Show(Document.Text);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

来源:博客nawrem.reverse

  • 我很感激回答的努力,但请阅读我在赏金中写的描述.我知道你可以绑定Document属性,但是我需要AvalonEdit的整个状态(否则,我必须从textview,textarea,document,visuallines等开始绑定很多东西) (4认同)