2015-02-09 103 views
1

在我的程序中,我試圖設計一個輸出窗口來顯示日誌信息。對於現在我結合爲一個字符串,並儘快日誌數據進入更新信息在viewmodel中創建控件實例

例:

<FlowDocument> 
    <Paragraph> 
     <Run DataContext="{Binding}" Text="{Binding OutputText}"/> 
    </Paragraph> 
</FlowDocument> 

(流文件是一個豐富的文本框內)

在我的視圖模型,這是我如何更新我的outputText

OutputText += loggingInfoString; 

的問題是,字符串是不可變的數據類型,我不喜歡創建一個新的字符串,每一次新的大的想法ta進來。這是一個不必要的開銷。

RichTextBox中有一個名爲AppendText通過方法,我認爲將使用類似一個StringBuilder,以添加到字符串。我遇到的問題是能夠訪問ViewModel中的AppendText。

我想過讓視圖模型內的RichTextBox的實例,並結合在RichTextBox到一個在視圖模型。我認爲這違反了MVVM,但我不完全確定。還有另外一種方法可以解決這個問題嗎?或者我應該在ViewModel中創建RichTextBox實例?

例: //視圖模型

RichTextBox Output; 

//更新方法

Output.AppendText(loggerInfoText); 

// XAML中

<RichTextBox DataContext="{Binding Output}" /> 
提前

謝謝!

回答

2

創建像這樣

interface IAppender{ 
    void Append(string appendText); 
} 

可以注入該接口到您的視圖模型的接口,你實現它在您的觀點。 這意味着,在您的視圖模型的代碼,你根本就

appender.Append(loggerInfoText); 

而且在你看來,你通過添加文本到富文本實現的接口。 根據您的視圖和視圖模型的實現,根據視圖模型的創建位置,您可以在視圖模型中注入接口。假設視圖模型在視圖中創建你得到的東西是這樣的:

class View : UserControl, IAppender{ 
    View(){ 
     InitializeComponent(); 
     DataContext = new YourViewModel(this); 
    } 
    void Append(string appendText){ 
     //add text to richttext 
    } 
} 

public class YourViewModel : ViewModelBase{ 
    private IAppender _appender; 
    public YourViewModel(IAppender appender){ 
     _appender = appender; 
    } 
} 

這應該讓你開始,我希望 注意,這是僞代碼,沒有測試甚至不通過編譯器運行它。 將richttext傳遞給viewmodel確實不是MVVM。這個想法是有關的分離。通過我的界面方法,這不會被違反。

+0

太棒了!感謝您的迅速回復。我不相信我甚至沒有想到這一點。有時候作爲程序員,我們忽略了最簡單的事情。再次感謝:) – CodingMadeEasy 2015-02-09 21:04:17

+0

我有一個快速的問題。如果我在viewmodel中有一個事件處理程序。將appendtext添加到視圖模型的事件處理程序是否是不好的做法? – CodingMadeEasy 2015-02-10 15:40:49

+0

取決於你的意思。調用從注入到視圖模型的接口追加,並在事件處理程序中執行,這不是問題。事件處理程序本身不應附加到WPF組件事件。使用命令,甚至行爲。但這已經是MVVM的更高級了。很難看到你需要從這一端;-) – 2015-02-10 17:40:16

-1

以替代注射這是由你的控制來實現的依賴(這即使脫鉤,使注塑的觀點在屁股痛):

首先,你可以使用StringBuilder內部建立自己的字符串。

public class MyViewModel : ViewModelBase 
{ 
    private StringBuilder sb; 
    private string Content 
    { 
     return sb.ToString(); 
    } 
    protected Append(string text) { 
     sb.Append(text); 
     PropertyChanged("Content"); 
    } 
} 

然後將Content屬性綁定到您的XAML元素。這樣,您的ViewModel中就不會有分配/解除分配,並且您無需爲DI將視圖/控件注入ViewModel(即使它被界面抽象化)而煩惱。

但是,這裏假定你要避免這種分配。如果您只希望在特定類型的應用程序(即Windows應用商店應用程序)中使用它,但不想在您的ASP.NET或桌面應用程序中使用,則第二種選擇可能更具吸引力(尤其適用於其他類似場景):

您可以使用自定義行爲來實現此目的,如this question中的答案所示。行爲是可重用的,你不需要在ViewModel中做這樣的決定,從而允許你按平臺或甚至每個View不同地處理這種決定。

它簡化了您的視圖模型,你就不必費心如何注入實現了IAppender到您的視圖模型視圖(可能會導致查看優先的方法,其中查看被國際奧委會和得到解決煩惱注入視圖的ViewModel設置爲DataContext)

+0

如果我使用StringBuilder,它與使用字符串沒有區別,但實際上會更糟糕。每次追加字符串生成器時,我都會將其轉換爲字符串。所以基本上我會追加一個字符串生成器,然後生成一個字符串,這正是我想要避免的。 – CodingMadeEasy 2015-02-11 15:14:41