2010-03-04 108 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