2016-01-26 5 views
0

Для школьного проекта мне нужен выборочный шаблон для объекта вопроса. В зависимости от его типа я должен показать другой тип (типы: открытый, множественный выбор и закрытые)Условный DataTemplate возвращает объект

Я определил шаблон как следует

<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 с сеттерами. Основываясь на другом примере, показанном здесь в 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; } } 
} 

Am я что-то не так? Как я могу это исправить?

Обновление: Решено. Данный пример работает правильно. Данные из базы данных были неверными, которые вызывают ошибку.

+0

Можете ли вы [изменить] ваш вопрос, чтобы включить код для объекта данных, к которому вы привязываетесь? – Rachel

+0

Я подозреваю, что проблема связана с вашим DataContext, поскольку 'System.Data.Entity.DynamicProxies' звучит так, как будто это часть Entity Framework, а не пользовательский элемент управления, который вы создали. – Rachel

+0

Правильно, вопросы задаются сущностью. но как это проблема? и что еще важнее, как я могу обойти это? – IMarks

ответ

0

Как type Недвижимость добавлена? И можете ли вы проверить, какие значения вы ожидаете?

На основе объектной модели и вашего утверждения, что работает привязка к QuestionContent, похоже, что вы правильно настроили иерархию DataContext, поэтому наиболее вероятной причиной является сама информация.

Я также заметил, что вы не реализуете INotifyPropertyChanged на объектной модели, поэтому, если он установлен после привязки объекта, пользовательский интерфейс не будет знать, что он нуждается в обновлении.

+0

1/2 Я привязка к моей модели вопроса, который выглядит как этот 'общественного класс Вопрос { общественного вопрос() { this.Answers = новый ObservableCollection (); } [Key] public virtual int Id {get; задавать; } public String QuestionContent {get; задавать; } public string OpenAnswer {get; задавать; } открытый тип строки {get; задавать; } public virtual ObservableCollection Ответы {get; задавать; } public virtual Questionaire Questionaire {get; задавать; } } ' – IMarks

+0

2/2 Есть ли в любом случае я могу получить текстовое поле для открытых вопросов, радио для закрытых и checkbox для multipleChoice с текущим форматом? – IMarks

+0

@IMarks На основе объектной модели и вашего утверждения, что привязка к 'QuestionContent' работает, похоже, что вы правильно настроили иерархию DataContext.Как устанавливается свойство 'type'? Я замечаю, что вы не реализуете 'INotifyPropertyChanged' в объектной модели, поэтому, если он установлен после привязки объекта, пользовательский интерфейс не будет знать, что он должен обновляться. И что касается вашего второго вопроса, я думаю, что у XAML у вас сейчас все нормально. Вы привязываетесь к коллекции объектов и используете «DataTrigger» для проверки свойства и определения того, как рисовать каждый объект, как я это делал. – Rachel

0

DataTemplates предназначены для использования с типами ... как в System.Type. Это простые способы обмена элементами пользовательского интерфейса, которые предназначены для взаимодействия с определенным типом. Вы, наверное, злоупотребляете этим. Вот почему.

Для того, чтобы использовать 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 закрыт. Никакой триггер данных не забивается между ним и его закрывающим тегом.

Теперь, конечно, правильный способ сделать то, что вы пытаетесь сделать является использование IValueConverter для преобразования type (я надеюсь, что это перечисление в приложении) в строковое представление. Реализация для этого будет семь или восемь строк и довольно кровавые тривиальные. Здесь вы можете найти множество примеров, поэтому я оставлю это для вас.

Тогда все, что вам будет нужно сделать, это

<!-- up in your window's or app's Resources --> 
<converters:MerTestTyerpCernverter x:Name="Duh" /> 

и в вашем ItemsControl.ItemTemplate (избавиться от всего, что другой ерунды)

<Label Content="{Binding type, converter={StaticResource Duh}}"/> 

WPF довольно легко, как только вы понять закономерности. Если вы сбились с кроличьей дыры, остановитесь и передумайте, что вы делаете - возможно, это более простой способ.

+0

Я использую сущность framework и тип не модель/объект, а свойство. Есть ли другой способ использовать данный пример, потому что поворот типа в объект невозможен в пределах оставшегося временного пространства из-за его использования в остальной части приложения, что приведет к разрыву множества функций. Я знаю, что ваш пример будет замечательным, поскольку я видел его раньше, но я не вижу способа использовать его прямо сейчас, если только не существует способа использовать свойство вместо типа для типа данных. – IMarks

+0

@ Я не уверен, что понимаю, почему вы думаете, что это злоупотребление DataTemplate. Почему мы не должны использовать DataTriggers для условной проверки связанного значения и установки ContentTemplate на другой DataTemplate в зависимости от значения? Я делаю это иногда, когда это необходимо. – Rachel

+0

@ Rachel Учитывая, что он, вероятно, нуждается (IValueConverter), это своего рода злоупотребление. Как пытаться узнать, как использовать токарный станок для укусов. – Will