【问题标题】:WPF binding data to RowDetailsTemplateWPF 将数据绑定到 RowDetailsTemplate
【发布时间】:2017-01-05 22:14:28
【问题描述】:

我正在创建一个显示调查问卷的程序。问卷按类别(第 1 类、第 2 类等)划分。每个类别可以包含许多问题,每个问题可以有许多选择题答案。我使用 DataGrid (objDatagrid) 和嵌套在 RowDetailsTemplate 中的另一个 DataGrid (objInnerDatagrid) 构建了这份问卷。我正在尝试对其进行设置,以便在程序加载时显示所有问题和所有答案。这意味着默认情况下不会折叠任何内容。我通过将外部 DataGrid 设置为:RowDetailsVisibilityMode="Visible"

来完成此操作

不幸的是,由于我的代码,每个问题的答案现在都是相同的,基于当前选择的问题。当我第一次设置它时,我没有使用 RowDetailsVisibilityMode="Visible"。因此,默认操作是折叠所有未选择的问题。但正如我所说,这不是我的预期设计。

我很确定我的代码中的错误是在内部网格 (objInnerDataGrid) ItemsSource 绑定中。但我不知道要改成什么。


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; }
    }

【问题讨论】:

  • 顺便说一句,如果一个人在运行时动态添加或删除项目并且需要使用特定的事件通知,则只需要使用ObservableCollection。否则,在绑定到网格/列表时使用 List&lt;t&gt; 效果很好。

标签: c# wpf xaml datagrid


【解决方案1】:

你关于内部网格绑定的假设是正确的,因为你有一个明确的绑定到当前选定的行,它实际上是从当前项目中跳出并为所有行绑定它 /强>。

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

对于所有行,您想要的绑定是基于当前项的父数据上下文的相对绑定,例如

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

您可能必须明确指定DataContext,如果是这样,请使用:

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

请记住,绑定最终是基于对象数据上下文的代码反射,在大多数情况下是从父级继承的,因此在这些情况下,请考虑父级并进行相应的绑定。

【讨论】:

  • 这很好用。我知道我找对地方了。但你帮我敲定了交易。非常感谢!
  • @PatH 如果它回答了你的问题,请把我的帖子标记为答案。
  • 我做到了,但我的代表太低了,仅凭我的投票就无法接受。很抱歉!
  • @PatH 再试一次。无论代表如何,您仍然可以将问题标记为answered;这与赞成票不同。先标记为已回答,然后尝试投票。
  • 好的。我想我明白了。我一直是这个网站的潜伏者,但通常可以通过搜索找到我正在寻找的东西。这是我不得不问自己问题的几次。
猜你喜欢
  • 2010-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 2011-03-13
  • 2011-05-28
  • 2011-01-31
相关资源
最近更新 更多