2011-01-25 38 views
0

用戶控件位於Controls \ TabControl中。包含具有2個tabitems的標籤控件(RuleTab和DiagramTab)。MainWindowViewModel中的WPF參考用戶控件代碼

在我MainWindowViewmodel I類有:

private void ShowSaveDialog() 
    { 
     System.Windows.Forms.SaveFileDialog sfd = new System.Windows.Forms.SaveFileDialog(); 
     sfd.Filter = "Text File (*.txt)|*.txt"; 

     bool? saveResult = sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK; 

     if (saveResult == true) 
     { 
      string s = sfd.FileName; 
      filePath = s; 
      SaveFile(s); 
      SetTitle(sfd.FileName); 
      RuleTab.Header = new System.IO.FileInfo(sfd.FileName).Name; 
      RuleTab.Focus(); 
     } 

RuleTab(TabItem的)沒有被發現,因爲它是在用戶控件。我如何在課堂上正確引用它?

TabControl.xaml

  x:Name="TabEditor" x:FieldModifier="public" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="423"> 

<TabControl x:Name="tabControl" x:FieldModifier="public" Width="Auto" Padding="0" Margin="3" DataContext="{Binding}"> 
    <local:CloseableTabItem Header="Diagram" x:Name="DiagramTab" x:FieldModifier="public" Height="25"> 
     <Image Height="Auto" x:Name="ResultImage" x:FieldModifier="public" Stretch="Fill" Width="Auto" /> 
    </local:CloseableTabItem> 
    <local:CloseableTabItem Header="Rulebase" x:Name="RuleTab" x:FieldModifier="public" Height="25" > 
     <Grid> 
      <TextBox Height="Auto" x:Name="RuleText" x:FieldModifier="public" Width="Auto" Text="" AcceptsTab="True" AcceptsReturn="True" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Visible" /> 
     </Grid> 
    </local:CloseableTabItem> 
</TabControl> 

回答

1

有各種可能性,但如果我看你的代碼,例如當時我想,我會一個事件FileSaved添加到您的視圖模型,提高sucessfull後,此事件保存。
從您的MainWindow中,您可以註冊此事件並進行進一步處理,例如聚焦所需的控件。
然而,爲了設置標題,我會在ViewModel中聲明一個屬性並將RuleTabs標頭綁定到它。但顯然你也可以在事件中設置標題,但這有一些不必要的缺點。

更新
如這裏所期望實現的情況下,在你的ViewModel屬性很短的例子。我假設你的ViewModel實現INotifyPropertyChanged。如果不是,但它自DependencyObject派生,定義一個只讀DepencencyProperty爲FileName而不是CLR屬性:

string m_fileName; 
public event EventHandler FileSaved;  

private void ShowSaveDialog() 
    { 
     System.Windows.Forms.SaveFileDialog sfd = 
      new System.Windows.Forms.SaveFileDialog(); 
     sfd.Filter = "Text File (*.txt)|*.txt"; 

     bool? saveResult = sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK; 

     if (saveResult == true) 
     { 
      string s = sfd.FileName; 
      filePath = s; 
      SaveFile(s); 
      FileName=sfd.FileName; 
      OnFileSaved(EventArgs.Empty); 
     } 
} 

protected virtual void OnFileSaved(EventArgs e){ 
    if(null != FileSaved){ 
     FileSaved(this,e); 
    } 
} 

public string FileName{ 
    get{return m_fileName;} 
    private set{ 
     if(value!=m_fileName){ 
      m_fileName=value; 
      OnPropertyChanged(new PropertyChangedEventArgs("FileName")); 
     } 
    } 
} 
+0

你可能給我一個兩個代碼示例?這是我第一次嘗試使用這個模型:0 – 2011-01-25 19:13:28

0

WPF宣佈在UserControl作爲private控制。爲了使您的RuleTabpublic你一個FieldModifier聲明它在:

<TextBox x:FieldModifier="Public" /> 

其中x是XAML命名空間xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

+0

ahh它的小寫「public」......謝謝:) – 2011-01-25 20:10:29

+0

將x:FieldModifier設置爲public後仍然無法在我的MainWindowViewModel類中正確訪問它(RuleTab.Header =新的System.IO.FileInfo(ofd.FileName).Name; ....任何建議也許? – 2011-01-25 20:40:07

0

您使用的是MVVM模式,不是嗎?不要訪問控件的屬性,訪問控件綁定的視圖模型的屬性。

您應該有RuleTab的視圖模型;它需要公開Filename屬性HeaderRuleTab綁定。您的方法然後只設置該屬性。 (當然,這必須以其中一種常用的方式實現更改通知。)

一般來說,任何時候當您嘗試在視圖模型代碼中操縱控件時,您都在做錯了。視圖模型不知道存在控件。在NUnit中爲你的視圖模型編寫單元測試是不太可能的(這是大家談論的但很少人做的事情之一),但你至少應該能夠做到。

另外,顯示文件對話框的方法應該是視圖中的方法,而不是視圖模型。這得到了一點體系結構 - astronauty,但總體思路是視圖模型根本沒有任何UI。處理這個問題的常見方法是讓視圖模型實現一個SaveCommand,它在執行時引發一個事件,以及一個實際保存文件的公共方法。視圖監聽事件,當它被引發時,它顯示對話框,獲取文件名,並在用戶沒有取消時調用視圖模型上的方法。這再一次爲您提供了可以編寫單元測試而不涉及UI的內容。