2009-07-24 162 views
45

我有一個視圖,它有一個單獨的TextBox和一對Button s。當窗口加載時,我希望TextBox有重點。WPF MVVM加載焦點域

如果我不使用MVVM,我會在Loaded事件中調用TextBox.Focus()。然而,我的ViewModel不知道我的視圖,所以如何在不將代碼放入視圖的代碼隱藏的情況下完成此任務?

編輯: 閱讀的答案後,我決定把這個代碼視圖中的XAML

<DockPanel FocusManager.FocusedElement="{Binding ElementName=MessageTextBox}">  
    <TextBox Name="MessageTextBox" Text="{Binding Message}"/> 
</DockPanel> 

如果這不是初始頁面的焦點其他我可能會建議喬恩·加洛韋的答案,因爲它可以從控制什麼ViewModel。

回答

14

在這種情況下,我認爲可以將代碼放入視圖中。將焦點設置爲控件會影響用戶界面的行爲而不是應用程序的邏輯,因此是視圖的責任。

+1

這是什麼樣的我想。每次考慮將代碼添加到視圖時,我都覺得有點骯髒。在這種情況下,它似乎是有道理的。 – 2009-07-24 15:41:14

+14

我想,一旦我改變了我的MVVM理念從「無代碼背後」到「最小和相關的代碼背後的」我的生活變得輕鬆了許多。我沒有聽說安德森艾姆斯已經提到的附加屬性,這聽起來像一個很好的解決了低級趣味的代碼背後給你,但不要害怕把*合法*,非邏輯的代碼在UI。 – 2009-07-24 15:45:10

+4

我很同意你的意見。我認爲從視圖中消除代碼是有道理的。重要的是視圖中的代碼應該與UI相關。虛擬機中的代碼包含與模型相關的狀態和其他邏輯。石蕊測試是代碼是否可以/應該被測試。視圖中的代碼不能被測試。 – 2010-10-08 14:44:10

4

我認爲焦點控制非常「只有視覺」,所以在代碼背後沒有任何問題。

虛擬機的想法是將邏輯從視圖中移開,併爲要綁定的視圖提供數據綁定友好版本的模型。這並不一定意味着所有的代碼都應該存在於虛擬機中,只是邏輯代碼和任何不直接綁定到UI的東西。

8

其實,是不是焦點關注UI? MVVM是關於分離問題的 - 模型屬於模型,屬於視圖的屬於視圖,並且模型和視圖一起綁定在ViewModel中(這當然是過於簡單的描述)。

這意味着,UI邏輯保留在視圖中 - 在我看來,TextBox.Focus()是適當的方式來實現這一點。

10
  1. 在您的ViewModel中有一個屬性,它指示哪個是當前焦點元素。
  2. 使用FocusManager綁定到該屬性。

    <Window FocusManager.FocusedElement="{Binding ElementName=ViewModel.FocusedItem}"/> 
    

您的視圖模型是存在只是爲了給View提供的信息,這樣你就可以添加任何信息到虛擬機的瀏覽需要的功能翻譯。

2

經過「WPF初始聚焦夢魘」並基於堆棧上的一些答案,以下證明對我來說是最好的解決方案。

首先,添加您的應用程序。XAML OnStartup()以下內容:

EventManager.RegisterClassHandler(typeof(Window), Window.LoadedEvent, 
      new RoutedEventHandler(WindowLoaded)); 

然後還加了「WindowLoaded」事件中的App.xaml:

void WindowLoaded(object sender, RoutedEventArgs e) 
    { 
     var window = e.Source as Window; 
     System.Threading.Thread.Sleep(100); 
     window.Dispatcher.Invoke(
     new Action(() => 
     { 
      window.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); 

     })); 
    } 

線程問題必須用作WPF最初的重點主要是由於某種框架競賽條件。

我發現下面的最佳解決方案,因爲它是全球範圍內用於整個應用程序。

希望它可以幫助...

奧蘭