2010-07-23 61 views
2

我正在嘗試使用MVVM,但我無法完全理解它。在這種情況下推薦最佳方法

我有一個視圖(窗口),有幾個重複的控制。

比方說,我有4個文本框 - 按鈕對。他們的行爲應該是相同的,按下按鈕配對文本框後說:「Hello World!」

我嘗試了好幾種選擇,我能想到的:

  1. 一個視圖模型,4個字符串屬性綁定到文本框,1個命令
    • 當我每個按鈕綁定到相同的命令我不能告訴哪些屬性需要設置。
    • 將枚舉傳遞給CommandParameter會感到尷尬。
  2. 一個ViewModel和UserControl承載一個文本框和一個按鈕重複4次。
    • 現在我需要公開像Command,CommandParameter,Text等所有屬性。似乎很多工作。
    • 仍然不能說點擊後需要更新哪些屬性。
  3. 每個用戶控件都有一個ViewModel
    • 這解決了點擊按鈕和設置屬性,但現在我不知道如何提取從嵌套的ViewModels文本到窗口視圖模型。

有沒有其他辦法?我懷疑DataTemplates可能有用,但我不知道如何。

回答

2

你所描述的是這樣一個抽象的和人爲的想法,它不保證MVVM。你在談論TextBox es和Buttons,這些都是'查看',而不是MVVM的思維方式。你幾乎總是從一個模型開始。

儘管這裏沒有'模型'您的規格是從字面上設置TextBox的值爲Button點擊。看似隨機的'4'項目(從無處拾取)和看似無用的TextBox沒有任何意義。

把那一邊,假設你有一組4個業務實體,每個與他們一個字段是用戶可編輯的,並且用戶可以觸發一個動作,你可以這樣做:

  • 創建一個視圖模型類來表示一個項目 - 如MyItemModel
  • 創建一個視圖模型類來表示一組項目(有可能將只返回第一的集合) - 例如:AllMyItemsListModel

那麼對於查看:

  • 創建ItemsControl,與ItemsSource綁定到第二ViewModel類
  • 對於每個ItemTemplate的「集合」的一個實例,有一個模板或UserControl每個項目
  • 在模板或UserControl,將TextBox的Text屬性綁定到第一類的相應屬性
  • ButtonCommand屬性綁定到第一個類的屬性,返回ICommand - 使用RelayCommand例如

我不知道你的意思「從嵌套的ViewModels到窗口視圖模型提取文本」是什麼 - 這是什麼意思,你爲什麼要這麼做?

希望有所幫助。

+0

+1表示良好的答案。但我不認爲創建ViewModel類來表示模型項的說法是正確的。相反,僅根據視圖和視圖創建ViewModel類。如果視圖需要某些模型數據,那麼ViewModel將使用模型中的特定屬性來滿足視圖的需要。因此,第一個ViewModel可以包含文本文本(如果需要,可以從Model獲得),Icommand和第二個可以包含'Collection ' – Amsakanna 2010-07-23 22:46:58

+0

感謝您的評論,但我暗示你永遠不會啓動* app *(而不是視圖模型)與視圖;你永遠不會寫一個應用程序'把文本放在方框中',你可以用真正的實體來寫一些真正的目的。所以你需要一個Model來開始。我相信我的答案已經表明,第一類將包含文本和ICommand的屬性,第二類也將是一個集合。 – 2010-07-24 07:25:07

+0

你是對的我在這裏弄錯了方法。我現在看到它。但我同意ViewModels應該基於視圖而不是Model來創建。 無論如何,在我的情況下,我沒有一個集合的固定數量的重複控件,應該在我的模型中表示固定數量的字符串。 – Kugel 2010-07-24 13:43:53

1

Number 3.除了只有一個UserControl和viewmodel,然後是Main頁面,該頁面上會有多個UserControl實例。如果主窗口需要來自UserControl的信息,則可以通過事件傳遞它,或者使用類似MVVM Light和它的Messenger類。

1

沒有必要爲具有如此簡單行爲的可重用控件創建單獨的ViewModel。只需在簡單的UserControl中添加一些DependencyProperties和一個事件處理程序,您就可以重用邏輯並僅設置每個實例上實際不同的屬性。對於UserControl XAML,您只需將TextBox連接到DependencyProperty並將Button連接到Click處理程序。

<DockPanel> 
    <Button Content="Reset" Click="Button_Click"/> 
    <TextBox Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=Text}"/> 
</DockPanel> 

UserControl的代碼只需要定義可以在外部綁定的屬性以及用於重置文本的處理程序。

public partial class ResetTextBox : UserControl 
{ 
    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
     "Text", 
     typeof(string), 
     typeof(ResetTextBox), 
     new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); 

    public string Text 
    { 
     get { return (string)GetValue(TextProperty); } 
     set { SetValue(TextProperty, value); } 
    } 

    public static readonly DependencyProperty ResetTextProperty = DependencyProperty.Register(
     "ResetText", 
     typeof(string), 
     typeof(ResetTextBox), 
     new UIPropertyMetadata(String.Empty)); 

    public string ResetText 
    { 
     get { return (string)GetValue(ResetTextProperty); } 
     set { SetValue(ResetTextProperty, value); } 
    } 

    public ResetTextBox() 
    { 
     InitializeComponent(); 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     Text = ResetText; 
    } 
} 

然後用你只需要綁定到您的視圖模型字符串屬性和設置,應該在這既可以在這裏硬編碼,或綁定到其他VM屬性重置應用的默認文本的控制。

<StackPanel> 
    <local:ResetTextBox ResetText="One" Text="{Binding Name1}"/> 
    <local:ResetTextBox ResetText="Two" Text="{Binding Name2}"/> 
    <local:ResetTextBox ResetText="Three" Text="{Binding Name3}"/> 
</StackPanel> 
+0

這是我的appreach#2。在你的情況下,你只有兩個暴露的屬性。在我的情況下,我有4或5,這似乎很多工作,只是暴露屬性。 – Kugel 2010-07-24 13:39:24

+0

這不是你在#2中描述的。您的方法需要額外的屬性,因爲您依賴於ViewModel來完成UserControl在此處執行的工作。如果使用此方法,則沒有所有命令函數的額外屬性,因爲它們不是通過ViewModel中的傳遞命令來執行,而是由UserControl在內部處理。 – 2010-07-24 16:03:25

+0

你是對的。我喜歡你的答案,因爲它很實用。但它不是可測試的。但我想小型UserControls可以。 – Kugel 2010-07-28 13:16:16

相關問題