根据所选项目的类型显示XAML元素

时间:2015-12-07 14:58:01

标签: c# wpf xaml

在我的WPF应用程序中,我有一个Observable抽象基类Test集合,实际上它的衍生类SqlTestConfigTest已经完整。

我有一个组合框,允许用户从可观察集合中选择一个项目,并且根据所选测试的类型我想要不同的控件。

我尝试过使用DataTemplates但是还没有设法让它们在列表以外的任何地方工作。

test.cs中

public abstract class Test
{
    public string Number { get; set; } // A string as test numbers can contain multiple decimal points depending on the section

    public string Description { get; set; }

    public string Condition { get; set; }

    public string Result { get; set; }
}

查看模型

public class MainWindowViewModel : INotifyPropertyChanged
{
    public ObservableCollection<Test> Tests { get; set; } = new ObservableCollection<Test>();

    public Test SelectedTest
    {
        get { return _selectedTest; }
        set
        {
            _selectedTest = value;
            OnPropertyChanged("SelectedTest");
        }
    }

    private Test _selectedTest;

    public MainWindowViewModel()
    {
        Tests.Add(new SqlTest("Change Me", "Check Me", "2", "A Test", "Condition", "Result"));
        Tests.Add(new ConfigTest("key", "value", "orig", "1.10", "Test2", "this is a result", "or is it?"));
        Tests.Add(new SqlTest("Change Me", "Check Me", "2", "A Test", "Condition", "Result"));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

我的xaml

<ComboBox Grid.Row="0" ItemsSource="{Binding Tests}" SelectedItem="{Binding SelectedTest}" IsSynchronizedWithCurrentItem="True" SelectedIndex="0">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock><Run Text="{Binding Number}" /><Run Text=" "/><Run Text="-" /><Run Text=" "/><Run Text="{Binding Description}" /></TextBlock>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

<!-- The Conditions of the test -->
<TextBlock Grid.Row="1" Margin="0, 5, 0, 0" Text="{Binding SelectedTest.Condition}" TextWrapping="Wrap" />

<!-- The Result of the test -->
<TextBlock Grid.Row="2" Margin="0, 5, 0, 0" Text="{Binding SelectedTest.Result}" TextWrapping="Wrap" />

1 个答案:

答案 0 :(得分:2)

这是一个非常简单的例子,我会在几分钟内为你准备好。

MainWindowVm是主窗口的视图模型。它有2个属性,第一个是Thing的列表,第二个是选定的Thing。主窗口将组合框​​绑定到ThingsSelectedThingSelectedItemContentControl也绑定了SelctedThing,其资源中定义了2 DataTemplatesDataType会自动使用模板的ContentControl属性,并在SelectedThing更改时与其内容类型进行比较。模板内部的任何标记都显示在组合框下方。

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:WpfApplication1"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Title="MainWindow"
        Width="525"
        Height="350"
        mc:Ignorable="d">
    <Window.DataContext>
        <local:MainWindowVm />
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <ComboBox Grid.Row="0"
                  ItemsSource="{Binding Path=Things}"
                  SelectedItem="{Binding Path=SelectedThing}" />
        <ContentControl Grid.Row="1" Content="{Binding Path=SelectedThing}">
            <ContentControl.Resources>
                <DataTemplate DataType="{x:Type local:Thing1}">
                    <StackPanel>
                        <TextBlock Text="This Is the template for Thing1" />
                        <Button Content="This is a button!" />
                    </StackPanel>
                </DataTemplate>
                <DataTemplate DataType="{x:Type local:Thing2}">
                    <StackPanel>
                        <TextBlock Text="This Is the template for Thing2" />
                        <TextBox Text="Enter some text" />
                    </StackPanel>
                </DataTemplate>
            </ContentControl.Resources>
        </ContentControl>
    </Grid>
</Window>

MainWindowVm.cs:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WpfApplication1
{
    class MainWindowVm : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public MainWindowVm()
        {
            Things = new ObservableCollection<object>();
            Things.Add(new Thing1());
            Things.Add(new Thing2());
        }

        public ObservableCollection<Object> Things { get; set; }

        private Object _selectedThing;
        public Object SelectedThing
        {
            get
            {
                return _selectedThing;
            }
            set
            {
                if (value != _selectedThing)
                {
                    _selectedThing = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedThing)));
                }
            }
        }
    }
}

Thing1Thing2只是空类。