2009-11-24 7 views
3

내 ViewModel에 바인딩 된 소프트웨어 용 사용자 지정 출력 창을 만들려고합니다. 보통 과거에는 항상 TextBox를 사용하고 appendText() 메서드를 사용하여 출력 창에 작성했습니다. 물론 ViewModel을 사용하여 Textbox에 바인딩하려고하면 Text 속성에만 바인딩 할 수 있습니다. 아래는 내가 할 노력하고 무엇 :WPF 바인딩 사용자 지정 출력 창

XAML : 텍스트가 관찰 가능한 컬렉션에 할당 할 수 없기 때문에 물론

<TextBox Text="{Binding Output}"></TextBox> 

C#

public class ViewModel : DependencyObject 
    { 
     public static readonly DependencyProperty OutputProperty = DependencyProperty.Register("Output", typeof(ObservableCollection<string>), typeof(MVVMTestViewModel), new UIPropertyMetadata(null)); 

     public ObservableCollection<string> Output 
     { 
      get 
      { 
       return (ObservableCollection<string>)GetValue(OutputProperty); 
      } 
      set 
      { 
       SetValue(OutputProperty, value); 
      } 
     } 

     public ViewModel() 
     { 
      Output = new ObservableCollection<string>(); 
     } 

     public void OutputMessage(string message) 
     { 
      Output.Add(message); 
     } 
    } 

이 가능하지 않습니다.

참고 : 참고 : ListView 또는 ListBox를 사용하고 관찰 가능한 컬렉션을 사용할 수 있습니다. 그러나 나는 선택 모드를 좋아하지 않는다. TextBox의 텍스트를 강조 표시하여 복사하여 Window 밖으로 붙여 넣을 수 있습니다. isReadOnly 속성을 사용하면이 작업을 매우 쉽게 처리 할 수 ​​있습니다.

쉬운 방법이 있나요? 또 다른 컨트롤 내가 어쩌면 아니지만?

답변

3

내가 뭘 토마스가 말한 것은 당신이 당신의 윈도우의 코드 숨김에서 다음을 가질 수 있다고 생각 Window 클래스는 Output 컬렉션에 추가 된 텍스트를 자동으로 추가합니다. (이 순수 MVVM을 고려하지 않을 수 있지만)

또 다른 방법은 다음과 같이 인터페이스를 사용하는 것입니다 그것을 할 수 있습니다 :

주요 응용 프로그램에서 다음
public interface IAppendOutput 
{ 
    void Append(string text); 
} 

public partial class MyWindow : Window, IAppendOutput 
{ 
    public MyWindow() 
    { 
     InitializeComponent(); 
    } 

    public void Append(string text) 
    { 
     outputTextBox.AppendText(text); 
    } 
} 

public class ViewModel 
{ 
    IAppendOutput _outputter; 
    public ViewModel(IAppendOutput outputter) 
    { 
     _outputter = outputter; 
    } 

    public void AppendOutput(string text) 
    { 
     _outputter.Append(text); 
    } 
} 

:

... 
MyWindow window = new MyWindow(); 
ViewModel vm = new ViewModel(window); 
window.DataContext = vm; 
window.Show(); 
vm.AppendOutput("This is a test."); 
... 

이 방법으로 할 수있다 가장 좋은 방법은 아니지만 다른 상황에서 빠른 덕트 테이프 코드를 작성하는 데 유용 할 수 있습니다. ViewModel은 창 자체에 대한 지식이 없기 때문에 단위 테스트가 가능합니다. 인터페이스 만 있습니다. IAppendOutput 인터페이스를 구현할 수 있도록 모든 종류의 객체를 사용자 정의 할 수 있으므로 여전히 유연합니다.

1

당신은 문자열로 컬렉션을 변환하는 변환기를 사용할 수 있습니다

public partial class MyWindow : Window 
{ 
    ViewModel _vm; 

    public MyWindow(ViewModel vm) 
    { 
     InitializeComponent(); 
     _vm = vm; 
     _vm.Output.CollectionChanged += Output_CollectionChanged; 
    } 

    void Output_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     foreach(object item in e.NewItems) 
     { 
      outputTextBox.AppendText(item.ToString()); 
     } 
    } 
} 

이를 :

public class ListToStringConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     IEnumerable lst = value as IEnumerable; 
     if (lst != null) 
     { 
      StringBuilder sb = new StringBuilder(); 
      foreach(var item in lst) 
      { 
       sb.AppendLine(item.ToString()); 
      } 
      return sb.ToString(); 
     } 
     return null; 
    } 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 

} 
+0

가끔 내 출력이 수천 줄에 (드물게) 있습니다.하지만 그렇다면 새 문자열을 추가 할 때마다 전체 ObservableCollection을 다시 출력하지 않습니까? – jsmith

+0

예 ... 그건 정말로 문제입니다. 바인딩을 통해 쉽게 처리 할 수 ​​있다고 생각하지 않습니다. 아마도 콜렉션에 대한 이벤트 핸들러를 구현해야합니다. –

+0

좋은 링크 또는 이것을 수행하는 방법에 대한 예제를 줄 수 있습니까? 나는 바인딩에 섞인 이벤트 핸들러에 익숙하지 않다. – jsmith

관련 문제