2009-11-18 20 views
3

我目前有一個WPF項目,它有一個主窗口和許多UserControl,它們是此窗口的子項。這個窗口中的許多孩子都是Tabs。我用一個用戶控件成功地替換了我的主窗口,該用戶控件實現了與主窗口幾乎完全相同的功能。如何查找UserControl而不是窗口的子項 - 替換Window.FindName

用UserControl替換窗口引入了一個問題 - 目前我們的應用程序使用下面顯示的Window.FindName方法確定基於父窗口顯示哪個編程選項卡。因此,我需要用我的主要用戶控件的適當說明替換Application.Current.MainWindow。請參閱下面的錯誤C#方法和wpf實例化標籤以進行說明。

注:關於Window.FindName()方法 - 爲什麼在我有用戶控件取代它,它不工作的原因是因爲在可視化樹,as described here向上FindName方法的搜索。

有誰知道如何找到基於x:Name的用戶控件,類似於Application.Current.MainWindow?另外,是否有更好的方法來查找UserControl,而不是尋找x:Name字符串以防重命名?

我們如何找到目前的主窗口 - 需要現在發現MainUserControl:

(C#) 
private static void SetCurrentProgram(int num) 
    { 
     Window window = Application.Current.MainWindow; 
     ProgrammingTab programmingTab1 = window.FindName("ProgrammingTab1") as ProgrammingTab; 
     ProgrammingTab programmingTab2 = window.FindName("ProgrammingTab2") as ProgrammingTab; 

     programmingTab1.Visibility = num == 1 ? Visibility.Visible : Visibility.Collapsed; 
     programmingTab2.Visibility = num == 2 ? Visibility.Visible : Visibility.Collapsed; 

    } 

編程標籤的實例化。

(xaml) 
<Grid> 
<ProgrammingControl:ProgrammingTab x:Name="ProgrammingTab1" Program="1" IsVisibleChanged="ProgrammingTab_IsVisibleChanged" /> 
<ProgrammingControl:ProgrammingTab x:Name="ProgrammingTab2" Program="2" IsVisibleChanged="ProgrammingTab_IsVisibleChanged" /> 
</Grid> 

回答

0

我想出了一個解決這個問題的方法:我創建了一個基於另一個StackOverflow用戶算法的新算法,該算法遞歸地發現了DependencyObject的任何子節點。找到my solution here。如果您在public static class UIHelper {}聲明FindChild()方法在我的其他職位然後你可以通過這樣解決問題:

ProgrammingTab programmingTab1 = UIHelper.FindChild<ProgrammingTab>(Application.Current.MainWindow, "ProgrammingTab1"); 
    ProgrammingTab programmingTab2 = UIHelper.FindChild<ProgrammingTab>(Application.Current.MainWindow, "ProgrammingTab2"); 

這仍然使用的程序代碼,而不是聲明XAML爲綁定像RayBurns建議。如果它有效,他的解決方案將更加高效,因爲它不會遍歷整棵樹,而只是改變基於轉換器的選項卡的可見性。我現在將測試該解決方案,看看它是如何結果。

爲什麼FindName()不能正常工作的原因在post here中描述。

2

這聽起來像你的應用程序是在一個非常WinForms風格的開發。要堅持這種風格,簡單地回答你的問題,你可以FindName()來找到用戶控件,並再次找到ProgrammingTab,就像這樣:

var userControl = (MyUserControl)Application.Current.MainWindow.FindName("userControlName"); 
var programmingTab1 = (ProgrammingTab)userControl.FindName("ProgrammingTab1"); 
var programmingTab2 = (ProgrammingTab)userControl.FindName("ProgrammingTab2"); 
... 

不過我建議你考慮使用WPF的先進功能,如數據綁定。您可以在由靜態屬性引用的單例對象上擁有DependencyProperty「CurrentProgram」,並使用轉換器簡單地將Visiblity數據綁定到它。

<ProgrammingTab Visibilty="{Binding CurrentProgram, 
    Source={x:Static MyState.Instance}, 
    Converter={x:Static VisibleIfEqualConverter}, 
    ConverterParameter=1}" ...> 
    ... 

隨着這一變化,您SetCurrentProgram變得簡單:

public void SetCurrentProgram(int num) 
{ 
    MyState.Instance.CurrentProgram = num; 
} 

這種技術的優點是,任何ProgrammingTab在您的應用程序會自動出現或消失每次MyState.Instance.CurrentProgram的vaulue變化的任何地方,無需使用FindName()或其他方式查找它們。

+0

我感激你的洞察力 - 我會檢查你的WPF的建議。但是,我發現行 * var userControl =(MyUserControl)Application.Current.MainWindow.FindName(「userControlName」); * 最終返回null。我確認了x:Name是正確的。我創建了一個新的主窗口,並在窗口的網格中實例化了用戶控件。有什麼建議麼?如有必要,我可以提供更多信息。 – CrimsonX 2009-11-18 21:17:22

+0

進一步研究 - 我認爲這個問題與以下兩件事之一有關: 1)*(MyUserControl)Application.Current.MainWindow.FindName(「userControlName」); *以某種方式存在於錯誤的NameScope中(請參閱http ://msdn.microsoft.com/en-us/library/ms746659.aspx有關更多信息) 或 2)我要走錯了路,我應該使用VisualTreeHelper: http:// stackoverflow。 com/questions/636383/wpf-ways-to-find-controls – CrimsonX 2009-11-18 22:31:30

+0

你說你「在窗口的網格中實例化用戶控件」。你是否在代碼中這樣做?如果是這樣,你記得打電話給RegisterName()嗎?這不是爲你做的。如果你在XAML中做過,是否有任何有自己的NameScope的中介對象? – 2009-11-18 23:36:38

相關問題