WPF动态GUI元素

时间:2010-03-04 21:04:18

标签: wpf user-interface dynamic

在WinForms中,在运行时为其他面板交换面板相对容易。在WPF中,这似乎相当复杂(特别是来自XAML)。

任何人都可以提供有关在运行时交换gui元素的“最佳实践”方式的明确指导(在向导类型情况下考虑页面)。

非常感谢。

5 个答案:

答案 0 :(得分:5)

可以使用datatemplates和/或触发器在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>

两个选项只会根据需要加载每个页面的控件,因此您不会在窗口中“加载但隐藏”所有控件。

答案 1 :(得分:1)

WinFomrs和WPF的基本概念是不同的。在WPF中,不建议直接使用UIElements(Controls)。使用DataBinding / DataContexts并只对数据进行操作,然后UI将相应地运行。这个概念都是关于WPF MVVM模式的。您可以查看一些MVVM示例并在执行更复杂的WPF项目之前尝试它。

一个简单的例子,假设您需要在ListBox中动态显示多个项目,执行此操作的典型winform方法是创建Items并直接添加到ListBox。但是在WPF中,您创建了一个ObservableCollection<Customer>并将其绑定到ListBox.ItemsSource。然后为客户数据类型定义DataTemplate,这可确保WPF系统了解如何在应用程序中显示客户集合。因此,当您向集合添加新的客户实例时,奇怪的是您的ListBox将更新一个项目。看起来非常简单,而且数据和视图的耦合方式非常松散吗? 祝你WPF学习愉快。 -

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

因此,您的问题的高级线索是,对数据进行适当的查看,以及何时发生数据/属性更改,WPF将负责更改面板/控件。因此,当您从数据和视图中感知时,它比WinForms方式非常简单。

答案 2 :(得分:0)

我想到了几种选择。如果您将组件创建为UserControls,并使用数据绑定,那么您应该能够轻松地完成所需的操作。

选项一是将每个组件加载到父容器(网格,画布,等等)中,使用Visibility =“Collapsed”,然后根据需要显示和隐藏它们。这样做的好处是可以在XAML中以声明方式执行此操作。

另一个选项是根据需要加载组件,因此在按钮的事件处理程序或其他UI元素中。在这种情况下,您可能希望从主机组件的Children集合中删除当前显示项,然后实例化下一个控件,设置DataContext(这就是绑定很重要的原因),并将其添加到Children集合中。 / p>

免责声明:这是基于我在Silverlight 3.0中基本上所做的经验,所以可能会有一些我不知道的WPF怪癖。)

答案 3 :(得分:0)

这里的MVVM建议都很好。但是,如果您正在设计一个需要导航的面向页面的UI,那么您也可以使用Structured Navigation

答案 4 :(得分:0)

我不知道这是否被视为良好做法,但我们在其中一个项目上所做的非常简单。我们定义了彼此重叠的面板,并且只需在需要时将可见性设置为隐藏或可见。