2017-01-05 6 views
1

Я создаю программу, в которой будет отображаться вопросник. Анкета разделена по категориям (Cat 1, Cat 2 и т. Д.). Каждая категория может содержать много вопросов, и каждый вопрос может иметь много ответов с несколькими вариантами ответов. Я построил этот вопросник, используя DataGrid (objDatagrid) с другим DataGrid (objInnerDatagrid), вложенным внутри RowDetailsTemplate. Я пытаюсь настроить его, чтобы все вопросы и все ответы отображались при загрузке программы. Это означает, что по умолчанию ничто не рушится. Я выполняю это, установив внешний DataGrid на: RowDetailsVisibilityMode = "Visible"Данные привязки WPF к RowDetailsTemplate

К сожалению, из-за моего кода ответы по каждому вопросу теперь все одинаковы в зависимости от того, какой вопрос является текущим. Когда я впервые установил это, я не использовал RowDetailsVisibilityMode = «Visible». Таким образом, действие по умолчанию состояло в том, чтобы свернуть все вопросы, которые не были выбраны. Но, как я сказал, это не мой намеченный дизайн.

Я уверен, что ошибка в моем коде находится во внутренней сетке (objInnerDataGrid) ItemsSource binding. Но я не знаю, к чему это изменить.

Примечание: я удалил некоторые ненужную код с участием настройки фильтра I

Благодарю вас всех.

XAML:

<Grid> 
    <StackPanel> 
     <TextBox Controls:TextBoxHelper.Watermark="enter search term" Name="TxtFilter" Margin="10" TextChanged="TxtFilter_TextChanged" Height="25" MinWidth="250" HorizontalAlignment="Stretch"/> 
     <DataGrid x:Name="objDatagrid" ItemsSource="{Binding DataView}" IsReadOnly="True" CanUserAddRows="False" CanUserDeleteRows="False" Loaded="objDatagrid_Loaded" AutoGenerateColumns="False" 
       HeadersVisibility="None" ScrollViewer.VerticalScrollBarVisibility="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RowDetailsVisibilityMode="Visible"> 
      <DataGrid.RowDetailsTemplate> 
       <DataTemplate> 
        <DataGrid x:Name="objInnerDatagrid" ItemsSource="{Binding ElementName=objDatagrid, Path=SelectedItem.Answers}" CanUserAddRows="False" IsReadOnly="True" CanUserDeleteRows="False" 
           HeadersVisibility="None" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> 
         <DataGrid.Columns> 
          <DataGridCheckBoxColumn ElementStyle="{DynamicResource MetroDataGridCheckBox}" 
                EditingElementStyle="{DynamicResource MetroDataGridCheckBox}" 
                Binding="{Binding Answers.AnswerText}"/> 
         </DataGrid.Columns> 
        </DataGrid> 
       </DataTemplate> 
      </DataGrid.RowDetailsTemplate> 

      <DataGrid.Columns> 
       <DataGridTextColumn Width="Auto" Binding="{Binding QuestionText}" IsReadOnly="True"/> 
      </DataGrid.Columns> 
      <DataGrid.GroupStyle> 
       <GroupStyle> 
        <GroupStyle.HeaderTemplate> 
         <DataTemplate> 
          <StackPanel> 
           <TextBlock Text="{Binding Path=Name}" /> 
          </StackPanel> 
         </DataTemplate> 
        </GroupStyle.HeaderTemplate> 
        <GroupStyle.ContainerStyle> 
         <Style TargetType="{x:Type GroupItem}"> 
          <Setter Property="Template"> 
           <Setter.Value> 
            <ControlTemplate TargetType="{x:Type GroupItem}"> 
             <Expander Margin="15 0 15 0" Header="{Binding Path=Name}" IsExpanded="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"> 
              <ItemsPresenter VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/> 
             </Expander> 
            </ControlTemplate> 
           </Setter.Value> 
          </Setter> 
         </Style> 
        </GroupStyle.ContainerStyle> 
       </GroupStyle> 
      </DataGrid.GroupStyle> 
     </DataGrid> 
    </StackPanel> 
</Grid> 

C#:

public partial class DataEmbed : UserControl 
{ 
    DataTable dt = new DataTable(); 

    public DataEmbed() 
    { 
     InitializeComponent(); 

     DataContext = this; 

     _dataView = new ListCollectionView(new ObservableCollection<Question>(Populate())); 
     _dataView.GroupDescriptions.Add(new PropertyGroupDescription("CategoryString")); 

     CollectionView cv = (CollectionView)CollectionViewSource.GetDefaultView(DataView); 
     cv.Filter = CustomFilter; 
    } 
    private List<Question> Populate() 
    { 
     return new List<Question>() 
     { 
      new Question() 
      { 
       CategoryString = "Cat 1", 
       QuestionText = "Question 1", 
       Answers = new ObservableCollection<Answer> 
       { 
        new Answer {AnswerText = "Answer 1"}, 
        new Answer {AnswerText = "Answer 2"}, 
        new Answer {AnswerText = "Answer 3"}, 
        new Answer {AnswerText = "Answer 4"} 
       } 
      }, 

      new Question() 
      { 
       CategoryString = "Cat 1", 
       QuestionText = "Question 2", 
       Answers = new ObservableCollection<Answer> 
       { 
        new Answer {AnswerText = "Answer 5"}, 
        new Answer {AnswerText = "Answer 6"}, 
        new Answer {AnswerText = "Answer 7"}, 
        new Answer {AnswerText = "Answer 8"}, 
       } 
      }, 

      new Question() 
      { 
       CategoryString = "Cat 2", 
       QuestionText = "Question 1", 
       Answers = new ObservableCollection<Answer> 
       { 
        new Answer {AnswerText = "Answer 9"}, 
        new Answer {AnswerText = "Answer 10"}, 
        new Answer {AnswerText = "Answer 11"}, 
        new Answer {AnswerText = "Answer 12"}, 
       } 
      } 

     }; 
    } 

    private ListCollectionView _dataView; 
    public ListCollectionView DataView 
    { 
     get { return _dataView; } 
     set { _dataView = value; } 
    } 

    private void objDatagrid_Loaded(object sender, RoutedEventArgs e) 
    { 

    } 
} 

Классы:

public class Question 
    { 
     public string CategoryString { get; set; } 
     public bool IsCategoryExpanded { get; set; } 
     public string QuestionText { get; set; } 
     public ObservableCollection<Answer> Answers { get; set; } 
    } 

    public class Answer 
    { 
     public string AnswerText { get; set; } 
    } 
+0

В качестве альтернативы нужно использовать 'ObservableCollection', если вы динамически добавляете или удаляете элементы во время выполнения и должны использовать это конкретное уведомление о событиях. В противном случае использование 'List ' отлично работает при привязке к сеткам/спискам. – OmegaMan

ответ

1

Ваше предположение о внутренней сетке связывания является правильным, для вас есть явные бинди ng к выбранной в настоящий момент строке, которая по сути выходит из текущего элемента и связывает его для всех строк.

<DataGrid x:Name="objInnerDatagrid" 
      ItemsSource="{Binding ElementName=objDatagrid, Path=SelectedItem.Answers}" 

Связывание вы хотите, для всех строк, является относительным связывания на основе родителя текущего элемента DataContext, такие как

<DataGrid x:Name="objInnerDatagrid" 
      ItemsSource="{Binding Answers}" 

Вы, возможно, придется указать DataContext в явном виде, если это использовать это:

<DataGrid x:Name="objInnerDatagrid" 
      ItemsSource="{Binding DataContext.Answers}" 

Помните, что привязка в конечном счете является отражением кода на основе obj ects datacontext, который в большинстве случаев наследуется от родителя, поэтому в этих ситуациях думают о родительском и привязывают соответственно.

+0

Это отлично работало. Я знал, что искал в нужном месте. Но ты помог мне запечатать сделку. Спасибо огромное! – PatH

+0

@PatH Если он ответил на ваш вопрос, тогда отметьте мое сообщение как ответ, пожалуйста. – OmegaMan

+0

Я сделал, но мой представитель слишком низок для того, чтобы его приняли только с моим голосованием. Извини за это! – PatH

Смежные вопросы