1

我正在嘗試在我的下一個WP7應用程序(用Vb.NET編寫)中改進我的MVVM功能。我有一個文本框已被給予焦點,並顯示WP7鍵盤。我正在使用命令綁定和xyzzer的可綁定應用程序欄(這非常出色)。WP7 MVVM如何從ViewModel調用me.setfocus()?

http://bindableapplicationb.codeplex.com/

我希望能夠從視圖模型取消TextBox的焦點,通過表單上設置焦點。通常情況下(非MVVM)我想通過調用做到這一點從表格中:

Me.Focus() 

但我不能從視圖模型做到這一點(我不應該)。目前,我正在從ViewModel中提取一個事件並將其捕獲到表單上,但它的討厭。有MVVM友好的方式嗎?就vb.net中有限的例子而言,我還沒有使用Toolkit。

我一直在使用命令綁定。

回答

0

使用Pedros例如,我在我的應用程序之前已經實施的其他服務我總結了以下解決方案在vb.net:

創建一個IFocus接口,該接口可以通過焦點服務或模擬實現

Public Interface IFocusInterface 
    Sub Focus() 
End Interface 

創建一個IFocusable接口。這將由ViewModel實現並接受實現IFocusInterface的對象。

Public Interface IFocusable 
    Property FocusService As IFocusInterface 
End Interface 

與Singleton模式

Imports Microsoft.Phone.Controls 

Public NotInheritable Class FocusService 
    Implements IFocusInterface 

    Private Sub New() 
    End Sub 

    Private Shared ReadOnly m_instance As New FocusService 
    Public Shared ReadOnly Property Instance() As FocusService 
     Get 
      Return m_instance 
     End Get 
    End Property 

    Public Sub Focus() Implements IFocusInterface.Focus 
     Dim rootFrame = TryCast(Application.Current.RootVisual, PhoneApplicationFrame) 
     If Not rootFrame Is Nothing Then 

      Dim page = TryCast(rootFrame.Content, PhoneApplicationPage) 

      If Not page Is Nothing Then 
       page.Focus() 
      Else 
       Throw New Exception("Unable to Cast the Root Frame Content into an Application Page") 
      End If 

     Else 
      Throw New Exception("Unable to Cast the RootVisual into a PhoneApplicationFrame") 
     End If 

    End Sub 

End Class 

在您的視圖模型實現的焦點接口實現IFocusable,並確保您在福克斯服務辛格爾頓傳遞到視圖模型視圖模型建成後。

Public Class MyViewModel 
    Implements INotifyPropertyChanged 
    Implements IFocusable 

    ' Property for the Focus Service 
    <Xml.Serialization.XmlIgnore()> Public Property FocusService As IFocusInterface Implements IFocusable.FocusService 

    Public Sub Focus() 
     If Not FocusService Is Nothing Then 
      FocusService.Focus() 
     Else 
      Throw New Exception("ViewModel hasn't been passed a Focus Service") 
     End If 
    End Sub 

End Class 

Dim tMyViewModel as New MyViewModel 
tMyViewModel.FocusService = Vacation_Calc_Model.FocusService.Instance 
+0

關於使用行爲的好處是能夠將它附加到其他控件上,以便通過簡單的綁定實際設置焦點,並且不依賴於只關注於某個服務的服務這一頁。 – 2012-04-27 20:03:45

2

讓我猜測:問題是,當您單擊ApplicationBarIconButton時,TextBox尚未更新ViewModel上的綁定屬性,是否正確?

使用ApplicationBarBehavior從Cimbalino Windows Phone Toolkit(你可以從NuGet也得到它),用於處理在內部 - 所以前ApplicationBarIconButton單擊事件得到執行,它已經更新了TextBox.Text綁定屬性!

檢查sample code in GitHub,你都準備好使用它!

編輯:

如果你想要的是將焦點設置在頁面上(並因此關閉鍵盤文本框失去焦點後),我會用一個外部類去完成這項工作,然後在視圖模型,像這樣使用它:

//This is the service interface 
public interface IPageService 
{ 
    void Focus(); 
} 
//This implements the real service for runtime 
public class PageService : IPageServiceusage 
{ 
    public void Focus() 
    { 
     var rootFrame = Application.Current.RootVisual as PhoneApplicationFrame; 

     if (rootFrame == null) 
      return; 

     var page = rootFrame.Content as PhoneApplicationPage; 

     if (page == null) 
      return; 

     page.Focus(); 
    } 
} 

//This implements the mockup service for testing purpose 
public class PageServiceMockup : IPageService 
{ 
    public void Focus() 
    { 
     System.Diagnostics.Debug.WriteLine("Called IPageService.Focus()"); 
    } 
} 

然後,在您的視圖模型,創建服務的一個實例是這樣的:

public class MyViewModel 
{ 
    private IPageService _pageService; 

    public MyViewModel() 
    { 
#if USE_MOCKUP 
     _pageService = new PageServiceMockup(); 
#else 
     _pageService = new PageService(); 
#endif 
    } 
} 

當你想把重點放在頁面上時,你所要做的就是撥打_pageService.Focus()

這是一個完全MVVM解決問題的方式!

+0

不,我沒有問題,但謝謝您的建議。我想通過按下應用程序欄上的取消按鈕使Wp7鍵盤消失。我知道我可以通過在窗體上調用me.focus()來做到這一點,但我無法從ViewModel中做到這一點。 – JonAlb 2012-04-15 21:44:30

+0

@JonAlb,我剛剛更新了帖子,提供了更多信息:現在您可以看到一個完全可用的MVVM'ed服務,將焦點放在頁面上,如您所請求的! – 2012-04-16 09:22:06

+0

謝謝,我的項目在vb.net。我在工作,但我會稍後嘗試將其轉換爲vb.net。 (除非有人打我) – JonAlb 2012-04-16 12:33:48

2

您可以嘗試使用行爲:在XAML

public class FocusBehavior : Behavior<Control> 
    { 
     protected override void OnAttached() 
     { 
      AssociatedObject.GotFocus += (sender, args) => IsFocused = true; 
      AssociatedObject.LostFocus += (sender, a) => IsFocused = false; 
      AssociatedObject.Loaded += (o, a) => { if (HasInitialFocus || IsFocused) AssociatedObject.Focus(); }; 

      base.OnAttached(); 
     } 

     public static readonly DependencyProperty IsFocusedProperty = 
      DependencyProperty.Register(
       "IsFocused", 
       typeof (bool), 
       typeof (FocusBehavior), 
       new PropertyMetadata(false, (d, e) => { if ((bool) e.NewValue) ((FocusBehavior) d).AssociatedObject.Focus(); })); 

     public bool IsFocused 
     { 
      get { return (bool) GetValue(IsFocusedProperty); } 
      set { SetValue(IsFocusedProperty, value); } 
     } 

     public static readonly DependencyProperty HasInitialFocusProperty = 
      DependencyProperty.Register(
       "HasInitialFocus", 
       typeof (bool), 
       typeof (FocusBehavior), 
       new PropertyMetadata(false, null)); 

     public bool HasInitialFocus 
     { 
      get { return (bool) GetValue(HasInitialFocusProperty); } 
      set { SetValue(HasInitialFocusProperty, value); } 
     } 
    } 

然後:

<TextBox> 
      <i:Interaction.Behaviors> 
       <behaviors:FocusBehavior HasInitialFocus="True" 
             IsFocused="{Binding IsFocused}" /> 
      </i:Interaction.Behaviors> 
     </TextBox> 
+0

我的項目在vb.net。我目前正在工作,但今後晚些時候我會嘗試將其轉換爲vb.net。 (除非有人打我) – JonAlb 2012-04-16 12:32:47

+0

我無法得到這與香草WP7工作,我無法找到香草wp7中的行爲。 – JonAlb 2012-04-26 21:31:15

+0

您需要從Blend SDK中引用System.Windows.Interactivity。 – 2012-04-27 19:54:47

相關問題