2010-03-04 105 views
4

在WinForms中,在運行時爲其他面板交換面板相對容易。在WPF中,這似乎更復雜(特別是來自XAML)。WPF動態GUI元素

任何人都可以提供有關在運行時交換gui元素的'最佳實踐'方式的明確指導(思考嚮導類型情況下的頁面)。

非常感謝。

回答

1

WinFomrs和WPF的基本概念是不同的。在WPF中,不建議直接使用UIElements(Controls)。使用DataBinding/DataContexts並對數據進行操作,然後UI將相應地運行。這個概念全是關於WPF MVVM模式的。您可以查看一些MVVM示例並在執行更復雜的WPF項目之前嘗試使用它。

一個簡單的例子,假設你需要動態顯示列表框中的多個項目,典型的winform方法是創建項目並直接添加到列表框中。但在WPF中,您創建了一個ObservableCollection<Customer>並將其綁定到ListBox.ItemsSource。然後爲Customer Data Type定義一個DataTemplate,這將確保WPF系統瞭解如何在應用程序中顯示客戶集合。所以,當你添加一個新的客戶實例到集合中時,奇妙的是你的ListBox將會更新一個項目。看起來非常直截了當,數據和視圖非常鬆散耦合的方式是對的? 祝你WPF學習。 -

http://www.bing.com/search?q=WPF+MVVM

所以高水平線索您的問題,請查看適當的數據,並在數據/屬性發生了變化,WPF將改變面板/控制的照顧。因此,當您從數據和視圖看待時,它比WinForms更簡單。

+0

謝謝,mvvm是我需要開始一些良好搜索的關鍵字。我還沒有完全掌握動畫轉換,但我很高興地說,事情終於變得更有意義了。 – Duncan 2010-03-13 12:06:35

0

一些選項浮現在腦海。如果您將組件創建爲UserControls並使用數據綁定,那麼您應該能夠以最小的麻煩做到您所需要的。

選項一是將每個組件加載到包含Visibility =「Collapsed」的父容器(網格,畫布,其他)中,然後根據需要顯示並隱藏它們。這具有可以在XAML中以聲明方式執行此操作的優點。

另一種選擇是根據需要加載組件,以便在按鈕的事件處理程序或其他某個UI元素中加載。在這種情況下,您可能希望從主機組件的Children集合中刪除當前顯示的項目,然後實例化下一個控件,設置DataContext(這就是爲什麼綁定很重要),並將其添加到Children集合中。這是基於我的經驗做基本上你在Silverlight 3.0中所要求的,所以可能會有一些WPF怪癖,我不知道)。

5

這可以通過使用數據類型和/或觸發器在XAML中找到。例如,如果嚮導中的每個頁面在底層模型中都被表示爲一個單獨的類或對象,則可以使用以下兩個選項之一......兩者均使用ContentControl,這是內容變化時的完美控制在相同數據的不同視圖之間很大程度上。

請注意,綁定的目的是僞代碼的例子,只是爲了傳達意圖!

的DataTemplate爲主,使用不同類型的每一頁:基於

<Grid> 
    <Grid.Resources> 
    <DataTemplate DataType="{x:Type WizardPageOne}"> 
     <!-- page 1 layout here --> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type WizardPageTwo}"> 
     <!-- page 2 layout here --> 
    </DataTemplate> 
    <!-- ... etc --> 
    </Grid.Resources> 

    <ContentControl Content="{Binding CurrentPageModel, Source=Wizardmodel}" /> 
</Grid> 

或者觸發,使用表示當前頁面的屬性:

<ContentControl Content="{Binding WizardModel}"> 
    <ContentControl.Style> 
     <Style> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding CurrentPageIndex} Value="1"> 
        <Setter Property="Template"> 
         <Setter.Value> 
         <ControlTemplate> 
          <!-- page 1 layout here --> 
         </ControlTemplate> 
         </Setter.Value> 
        </Setter> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding CurrentPageIndex} Value="2"> 
        <Setter Property="Template"> 
         <Setter.Value> 
         <ControlTemplate> 
          <!-- page 2 layout here --> 
         </ControlTemplate> 
         </Setter.Value> 
        </Setter> 
       </DataTrigger> 
       <!-- .... etc --> 
      </Style.Triggers> 
     </Style> 
    </ContentControl.Style> 
</ContentControl> 

兩個選項會只在需要的時候才加載每個頁面的控件,因此您沒有在窗口中「加載但隱藏」所有控件。

+0

我也應該提到這些模板的內容可以被重構以分離資源和/或文件,這也可以使您的標記更短更整齊。 – 2010-03-04 21:16:59

+0

謝謝。這對我來說很有意思。唯一的障礙是我看不到如何對轉換進行動畫處理。 不過,動態更改用戶界面元素的更一般情況仍然是開放的... – Duncan 2010-03-05 08:17:05

0

這裏的MVVM建議都很好。但是,如果您正在設計需要導航的面向頁面的用戶界面,則也可以使用Structured Navigation

0

我不知道這是否被認爲是很好的做法,但我們在我們的項目中做了什麼很簡單。我們定義了所有相互重疊的面板,只需在需要時將可見性設置爲隱藏或可見。

+0

一直以來都沒有把整個視覺保持在VisualTree中的好習慣。如果使用DataTemplate方法調用另一個可視化(UserControl),WPF將更加有趣和快速。 – 2010-03-13 21:33:06