根据选择在运行时加载控件

时间:2014-01-02 23:34:02

标签: wpf silverlight xaml

我是XAML的新手,我有一个案例需要根据带有模板的组合框选择更改控件。

例如,假设用户选择的模板需要一周中的某一天以及某些内容可用的时间范围。我希望在选择的那一刻,所需信息的控件可以在屏幕上构建,并且绑定也可以正常工作。

有人可以给我一个提示或指出一篇优雅的文章吗?

提前致谢。

1 个答案:

答案 0 :(得分:2)

您正在寻找的解决方案是ContentControl和DataTemplates。您可以使用ComboBox的选定项来更改Content Control的ContentTemplate。

你质疑提到绑定,所以我假设你理解MVVM模式。

例如,让我们使用MyModel1作为模型

public class MyModel1
{
    private Collection<string> values;
    public Collection<string> Values { get { return values ?? (values = new Collection<string> { "One", "Two" }); } }
    public string Field1 { get; set; }

    public string Field2 { get; set; }
}

MyViewModel作为ViewModel

public class MyViewModel
{
    public MyViewModel()
    {
        Model = new MyModel1();
    }
    public MyModel1 Model { get; set; }
}

后面的代码除了实例化ViewModel之外什么都不做。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        ViewModel = new MyViewModel();
        InitializeComponent();
    }

    public MyViewModel ViewModel { get; set; }
}

这三个都是非常简单的课程。有趣的是Xaml

<Window x:Class="StackOverflow._20893945.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib"
        xmlns:this="clr-namespace:StackOverflow._20893945" 
        DataContext="{Binding RelativeSource={RelativeSource Self}, Path=ViewModel}"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate x:Key="MyModel1Template1" DataType="{x:Type this:MyModel1}">
            <StackPanel>
                <TextBlock Text="Template 1"></TextBlock>
                <ComboBox ItemsSource="{Binding Path=Values}" SelectedItem="{Binding Path=Field1}" />
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Key="MyModel1Template2" DataType="{x:Type this:MyModel1}">
            <StackPanel>
                <TextBlock Text="Template 2"></TextBlock>
                <TextBox Text="{Binding Path=Field2}" />
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    <DockPanel>
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Margin="2">
            <ComboBox x:Name="TypeSelector">
                <system:String>Template 1</system:String>
                <system:String>Template 2</system:String>
            </ComboBox>
        </StackPanel>
        <ContentControl Content="{Binding Path=Model}">
            <ContentControl.Style>
                <Style TargetType="{x:Type ContentControl}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ElementName=TypeSelector, Path=SelectedItem}" Value="Template 2">
                            <Setter Property="ContentTemplate" Value="{StaticResource MyModel1Template2}" />
                        </DataTrigger>
                    </Style.Triggers>
                    <Setter Property="ContentTemplate" Value="{StaticResource MyModel1Template1}" />
                </Style>
            </ContentControl.Style>
        </ContentControl>
    </DockPanel>
</Window>

该观点的显着点是

  1. DataContext在Window元素上初始化,允许在我们的绑定表达式上自动完成
  2. 2个模板的定义,用于显示2个不同的数据视图。
  3. ComboBox中填充了一个字符串列表,并且默认选择了第一个元素。
  4. ContentControl的内容绑定到通过ViewModel公开的模型
  5. 默认的DataTemplate是第一个带有ComboBox的模板。
  6. 如果ComboBox的SelectedItem更改为“模板2”,则ContentControl样式中的触发器将更改ContentTemplate
  7. 隐含的事实

    1. 如果SelectedItem更改回“模板1”,则样式会将ContentTemplate恢复为默认值,即MyModel1Template1
    2. 如果需要3个单独的显示,请创建另一个DataTemplate,将一个字符串添加到ComboBox并添加另一个DataTrigger。
    3. 注意:这是我的示例的完整源代码。使用相同的类创建一个新的C#/ WPF项目并将代码输入。它应该可以工作。

      我希望这会有所帮助。