2014-05-23 88 views
4

我创建了一个自定义的从AvalonEdit继承的TextEditor控件。我这样做是为了方便使用此编辑器控件来使用MVVM和Caliburn Micro。 [剪切下来用于显示目的] MvvTextEditor类是使用MVVM在WPF中绑定失败

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但让由于问题是相同的,我们只考虑现在的长度)。如果我用鼠标选择了一些东西,从视图到我的视图模型的绑定效果很好。现在,我已经编写了一个查找和替换实用程序,并且我想从后面的代码中设置SelectionLength(其中getset可用于TextEditor控件)。在我的视图模型,我简单地设置SelectionLength = 50,我在视图模型实现这个像

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本身[呈现它自身的问题]

谢谢你的时间。

回答

0

这是我这究竟是怎么...

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

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

对不起,浪费的任何时间。我希望这可以帮助别人...

1

这是因为来自DependencyPropertyGetterSetter只是一个.NET Wrapper。该框架将使用GetValueSetValue本身。

你可以尝试的是从你的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; 
     } 
+0

我现在就试试这个,送还给你。感谢您的时间... – MoonKnight

+0

您是否在构造函数中注册'SelectionLengthPropertyChanged'? – MoonKnight

+0

不,我很抱歉。您正在将其注册到'Dependencyproperty''元数据'中。在我的例子中忘了这个。另外:尝试直接设置值到控制。这将是我猜测的最佳方式。 –

1

如果你仍然开放,这是另一个答案。由于SelectionLength已经被定义为基类的依赖属性,而不是创建派生类(或者将已经存在的属性添加到派生类),所以我会使用附加属性来实现相同的功能。

关键是要使用System.ComponentModel.DependencyPropertyDescriptor来订阅已存在的SelectionLength依赖项属性的change事件,然后在事件处理程序中执行所需的操作。

示例代码如下:

public class SomeBehavior 
{ 
    public static readonly DependencyProperty IsEnabledProperty 
     = DependencyProperty.RegisterAttached("IsEnabled", 
     typeof(bool), typeof(SomeBehavior), new PropertyMetadata(OnIsEnabledChanged)); 

    public static void SetIsEnabled(DependencyObject dpo, bool value) 
    { 
     dpo.SetValue(IsEnabledProperty, value); 
    } 

    public static bool GetIsEnabled(DependencyObject dpo) 
    { 
     return (bool)dpo.GetValue(IsEnabledProperty); 
    } 

    private static void OnIsEnabledChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs args) 
    { 
     var editor = dpo as TextEditor; 
     if (editor == null) 
      return; 

     var dpDescriptor = System.ComponentModel.DependencyPropertyDescriptor.FromProperty(TextEditor.SelectionLengthProperty,editor.GetType()); 
     dpDescriptor.AddValueChanged(editor, OnSelectionLengthChanged); 
    } 

    private static void OnSelectionLengthChanged(object sender, EventArgs e) 
    { 
     var editor = (TextEditor)sender; 
     editor.Select(editor.SelectionStart, editor.SelectionLength); 
    } 
} 

下面的XAML:

<Controls:TextEditor Behaviors:SomeBehavior.IsEnabled="True"> 
    </Controls:TextEditor>