2014-05-23 1 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 ( getsetTextEditor 컨트롤에서 사용 가능)을 설정하려고합니다. 내보기 모델에서 단순히 SelectionLength = 50을 설정하고, 나는 TwoWay 내 컨트롤에 바인딩 것처럼, 나는이 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); 
    } 
} 

DependencyProperty SelectionLengthPropertyMvvmTextEditor 클래스에 업데이트되지 않습니다처럼보기 모델이 구현 실패하고 있지만 스눕을 사용하면 이에 대한 징후가 없습니다. 나는 이것이 구속력을 통해서만 작동 할 것이라고 생각했지만, 이것은 그렇게 보이지 않습니다.

누락 된 간단한 것이 있습니까, 아니면 내보기 모델의 변경 사항을 수신하고 자체적으로 문제가되는 DP 자체를 업데이트하는 MvvmTextEditor 클래스의 이벤트 처리기를 설정해야합니까?

감사합니다.

답변

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 래퍼 일뿐입니다. 프레임 워크는 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 종속성 속성의 변경 이벤트를 구독 한 다음 이벤트 처리기에서 원하는 작업을 수행하는 것입니다.아래

샘플 코드 :

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>