条件DataTemplate返回对象

时间:2016-01-26 17:54:24

标签: wpf mvvm binding itemscontrol datatrigger

对于学校项目,我需要一个问题对象的选择性模板。根据其类型,我必须显示不同的类型(类型是:打开,多选和关闭)

我将模板定义为

<ResourceDictionary>
    <UserControl.Resources>
        <DataTemplate x:Key="Open" >
            <WrapPanel>
                <Label Content="Open"/>
            </WrapPanel>
        </DataTemplate>
        <DataTemplate x:Key="multipleChoice" >
            <WrapPanel>
                <Label Content="multipleChoice"/>
            </WrapPanel>
        </DataTemplate>
        <DataTemplate x:Key="Closed" >
            <WrapPanel>
                <Label Content="Closed"/>
            </WrapPanel>
        </DataTemplate>
    </ResourceDictionary>
</UserControl.Resources>

正如您所看到的,它现在只包含一个测试标签。 为了显示我使用ItemsControl与setter。基于StackOverflow上显示的另一个示例。但是,此示例为我返回System.Data.Entity.DynamicProxies,我不知道为什么。注释的代码正在运行,因此可以访问属性。

<ItemsControl ItemsSource="{Binding SelectedInspection.Questionaire.Questions}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <ContentControl Content="{Binding}">
                    <ContentControl.Style>
                        <Style TargetType="ContentControl">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding type}" Value="Open">
                                    <Setter Property="ContentTemplate"
                                            Value="{StaticResource Open}" />
                                </DataTrigger>
                                <DataTrigger Binding="{Binding type}" Value="multipleChoice">
                                    <Setter Property="ContentTemplate"
                                            Value="{StaticResource multipleChoice}" />
                                </DataTrigger>
                                <DataTrigger Binding="{Binding type}" Value="Closed">
                                    <Setter Property="ContentTemplate"
                                            Value="{StaticResource Closed}" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </ContentControl.Style>
                </ContentControl>
            </DataTemplate>
            <!--
            <DataTemplate>
                <WrapPanel>
                    <Label Content="{Binding Path=QuestionContent}" />
                </WrapPanel>
            </DataTemplate>
            -->
        </ItemsControl.ItemTemplate>
    </ItemsControl>

我绑定到我的问题模型,看起来像这样

public class Question 
{
    public Question() 
    {
        this.Answers = new ObservableCollection<Answer>(); 
    } 

    [Key] 
    public virtual int Id { get; set; } 
    public String QuestionContent { get; set; } 
    public string OpenAnswer { get; set; } 
    public string type { get; set; } 
    public virtual ObservableCollection<Answer> Answers { get; set; } 
    public virtual Questionaire Questionaire { get; set; } }
}

我做错了吗?我该如何解决这个问题?

更新:它已经解决了。给定的示例工作正确。数据库给定的数据不正确,导致错误。

2 个答案:

答案 0 :(得分:0)

DataTemplates旨在与System.Type中的类型一起使用。它们是交换UI元素的简单方法,用于与特定类型进行交互。你正在做的可能是滥用这个。这就是原因。

为了以这种方式使用DataTemplates,你必须重构这个(我认为你有)

enum TestType { open, multiplechoice, closed }
class Mahveurmerder // view model
{
    public TestType type {get;set;} 
    // snip
}

但是,为了正确使用DataTemplates,您必须将测试类型表示为实际类型。这就是我的意思:

// describes a type of test
abstract class TestType { }
// implementations of this type
class OpenBookTest : TestType {}
class ClosedBookTest : TestType {}
class MultipleTypeTest : TestType {}

您必须通过视图模型的属性公开此类型的实例

class Mahveurmerder
{
  public TestType type {get;set;}
}

在模板上指定数据类型后:

<DataTemplate 
    xmlns:models="clr-namespace:ermagerdmerassinmernt.models"
    DataType="{x:Type OpenBookTest:}" >
    <WrapPanel>
        <Label Content="Open"/>
    </WrapPanel>
</DataTemplate>

ItemsControl将自动接收它们(是的,就这么简单)

<ItemsControl ItemsSource="{Binding SelectedInspection.Questionaire.Questions}" />

注意,ItemsControl元素已关闭。没有数据触发BS塞在它和它的结束标记之间。

现在,当然,正确的方式来执行您尝试做的事情是使用IValueConverter来转换{{1 (我希望你的应用程序中的枚举)是一个字符串表示。这个实现将是七八行,非常琐碎。你可以在这里找到很多例子,所以我会让你发现。

然后,您需要做的就是

type

并在你的ItemsControl.ItemTemplate中(摆脱所有其他废话)

<!-- up in your window's or app's Resources -->
<converters:MerTestTyerpCernverter x:Name="Duh" />
一旦你理解了模式,WPF就很容易了。如果你在兔子洞里停下来,停下来并重新考虑你正在做的事情 - 这可能是一种更容易的方法。

答案 1 :(得分:0)

如何设置type属性?您能否验证这些值是否符合预期?

根据对象模型和您对QuestionContent的绑定有效的声明,看起来您正确设置了DataContext层次结构,因此最可能的问题原因是数据本身。

我还注意到你没有在对象模型上实现INotifyPropertyChanged,所以如果在绑定对象后设置它,那么UI就不知道它需要刷新。