【问题标题】:Load controls on runtime based on selection根据选择在运行时加载控件
【发布时间】:2014-01-03 09:38:12
【问题描述】:

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

例如,假设用户选择了一个模板,该模板需要一周中的某一天和一个可用的时间范围。我希望,在选择的那一刻,带有所需信息的控件会在屏幕上构建,并且绑定也能正常工作。

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

提前致谢。

【问题讨论】:

    标签: wpf silverlight xaml


    【解决方案1】:

    您正在寻找的解决方案是 ContentControl 和 DataTemplates。您使用 ComboBox 的选定项来更改内容控件的 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

    隐含的事实是

    1. 如果 SelectedItem 变回“模板 1”,样式会将 ContentTemplate 恢复为默认值,即 MyModel1Template1
    2. 如果需要 3 个单独的显示,请创建另一个 DataTemplate,向 ComboBox 添加一个字符串并添加另一个 DataTrigger。

    注意:这是我的示例的完整来源。使用相同的类创建一个新的 C#/WPF 项目并将代码粘贴进去。它应该可以工作。

    我希望这会有所帮助。

    【讨论】:

    • 看来正是我所需要的,马克,我要试试。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    • 2019-04-01
    • 1970-01-01
    • 2020-03-24
    相关资源
    最近更新 更多