2009-11-24 153 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的文本,以便我可以将它复制并粘贴到窗口外面。 isReadOnly属性允许我很容易地做到这一点。

有没有简单的方法来做到这一点?另一种控制我可能没有看到?

回答

3

我认为托马斯的意思是,你可以在你的窗口的代码隐藏以下内容:

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()); 
     } 
    } 
} 

这方式,窗口类将自动附加添加到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 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