c# – 使用MVVM在WPF中绑定失败

我创建了一个继承自AvalonEdit的自定义TextEditor控件.我这样做是为了方便使用这个编辑器控件来使用MVVM和Caliburn Micro. [为了显示目的而减少] MvvTextEditor类是

public class MvvmTextEditor : TextEditor, INotifyPropertyChanged
{
    public MvvmTextEditor()
    {
        TextArea.SelectionChanged += TextArea_SelectionChanged;
    }

    void TextArea_SelectionChanged(object sender, EventArgs e)
    {
        this.SelectionStart = SelectionStart;
        this.SelectionLength = SelectionLength;
    }

    public static readonly DependencyProperty SelectionLengthProperty =
         DependencyProperty.Register("SelectionLength", typeof(int), typeof(MvvmTextEditor),
         new PropertyMetadata((obj, args) =>
             {
                 MvvmTextEditor target = (MvvmTextEditor)obj;
                 target.SelectionLength = (int)args.NewValue;
             }));

    public new int SelectionLength
    {
        get { return base.SelectionLength; }
        set { SetValue(SelectionLengthProperty, value); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void RaisePropertyChanged([CallerMemberName] string caller = null)
    {
        var handler = PropertyChanged;
        if (handler != null)
            PropertyChanged(this, new PropertyChangedEventArgs(caller));
    }
}

现在,在持有此控件的视图中,我有以下XAML:

    <Controls:MvvmTextEditor 
        Caliburn:Message.Attach="[Event TextChanged] = [Action DocumentChanged()]"
        TextLocation="{Binding TextLocation, Mode=TwoWay}"
        SyntaxHighlighting="{Binding HighlightingDefinition}" 
        SelectionLength="{Binding SelectionLength, 
                                  Mode=TwoWay, 
                                  NotifyOnSourceUpdated=True, 
                                  NotifyOnTargetUpdated=True}" 
        Document="{Binding Document, Mode=TwoWay}"/>

我的问题是SelectionLength(和SelectionStart,但我们只考虑现在的长度,因为问题是相同的).如果我用鼠标选择了某些东西,从View到View模型的绑定效果很好.现在,我编写了一个find和replace实用程序,我想从后面的代码中设置SelectionLength(在TextEditor控件中可以获取和设置).在我的View Model中,我只是设置SelectionLength = 50,我在View Model中实现了这个

private int selectionLength;
public int SelectionLength
{
    get { return selectionLength; }
    set
    {
        if (selectionLength == value)
            return;
        selectionLength = value;
        Console.WriteLine(String.Format("Selection Length = {0}", selectionLength));
        NotifyOfPropertyChange(() => SelectionLength);
    }
}

当我设置SelectionLength = 50时,DependencyProperty SelectionLengthProperty不会在MvvmTextEditor类中更新,就像对我的控件的TwoWay绑定失败但使用Snoop没有任何迹象.我认为这只会通过绑定工作,但似乎并非如此.

有什么简单的我缺少,或者我必须在MvvmTextEditor类中设置和事件处理程序,它监听我的视图模型中的更改并更新DP本身[这表明它自己的问题]?

谢谢你的时间.

最佳答案 这是因为DependencyProperty中的Getter和Setter只是一个.NET Wrapper.框架将使用GetValue和SetValue本身.

您可以尝试从DependencyProperty访问PropertyChangedCallback并设置正确的值.

 public int SelectionLength
        {
            get { return (int)GetValue(SelectionLengthProperty); }
            set { SetValue(SelectionLengthProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectionLength.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectionLengthProperty =
            DependencyProperty.Register("SelectionLength", typeof(int), typeof(MvvmTextEditor), new PropertyMetadata(0,SelectionLengthPropertyChanged));


        private static void SelectionLengthPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var textEditor = obj as MvvmTextEditor;

            textEditor.SelectionLength = e.NewValue;
        }
点赞