如何在 TemplateSelector 内获取 WPF DataGrid 的活动行

发布于 2024-12-12 17:37:47 字数 4462 浏览 1 评论 0原文

我有一个包含三列的 WPF 数据网格。前两列为 DataGridComboBox 列。第三列是模板列,里面有ContentControl。我想使用此数据网格作为高级搜索的数据输入表单。第一列将与数据库中文档的属性列表绑定(如 DocumentName、OwnerName、DateCreated 等)。第二列是运算符列表(<、<=、!=)。这些运算符将根据从组合框中选择的属性动态更改 单元格[0]。这是在第一个组合框的 SelectionChanged 事件中处理的。

在内容控件内部(在单元格 [2] 中),我需要加载一个 DataTempalte(每个包含不同的 UI 控件,如 autocompleteBox、DatePicker 等),该控件根据第一列中的组合框中选择的属性在窗口的资源中定义。为此,我添加了一个自定义模板选择器。但我无法访问 DataGrid ComboxBox 及其 DataTempalte 选择器代码内第一个单元格的内容。

请注意,我不想将现有数据绑定到数据网格。数据网格将用作数据输入表单。因此,我总是希望仅在编辑模式下保留前几行中选择的值。

请参考我的 UI 和后面的代码中的示例代码:

public class DocumentSearchProperty
{
    public string PropertyName { get; set; }
    public string Operator { get; set; }
    public string PropertyValue { get; set; }
}

这是我设置为数据源的项目源的类。

<DataGrid AutoGenerateColumns="False" Width="Auto" Name="documentPropertyGrid"
                            ItemsSource="{}"
                            SelectionMode="Single" CanUserAddRows="True" CanUserDeleteRows="True" CanUserResizeColumns="True" CanUserSortColumns="True" 
                            CanUserResizeRows="False" FrozenColumnCount="0" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" RowHeaderWidth="0"
                            AlternatingRowBackground="Gainsboro"  AlternationCount="2" VerticalContentAlignment="Stretch" VerticalAlignment="Top" VerticalScrollBarVisibility="Auto">
                            <DataGrid.Columns>
                                <DataGridComboBoxColumn x:Name="columnProperty" ItemsSource="{}" SelectedItemBinding="{Binding Path=Id}" 
                                                 Header="Property" Width="170"/>
                                <DataGridComboBoxColumn x:Name="columnOperator" ItemsSource="{}" SelectedItemBinding="{Binding Path=value}" Header="Operator" Width="170" />
                                <DataGridTemplateColumn x:Name="PropertyValue" Header="Value" Width="100">
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <ContentControl x:Name="CntControl">
                                                <ContentControl.Content>1</ContentControl.Content>
                                            </ContentControl>
                                    </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>
                            </DataGrid.Columns>
                        </DataGrid>

下面的代码用于处理第一个组合框的选择更改事件。在这个选择更改事件中,我可以在单元格[1]中获取组合框。但我无法获取单元格[2]中的ContentControl。有人能建议更好的方法来实现这一目标吗?

DataGridRow row = this.documentPropertyGrid.ItemContainerGenerator.ContainerFromIndex(this.documentPropertyGrid.SelectedIndex) as DataGridRow;
            ComboBox ele = this.documentPropertyGrid.Columns[0].GetCellContent(row) as ComboBox;
            ContentControl contentControl = this.documentPropertyGrid.Columns[2].GetCellContent(row) as ContentControl;

我进行了以下更改,以将网格的第三列作为内容演示者:

ContentPresenter contentPresenter = this.documentPropertyGrid.Columns[2].GetCellContent(row) as ContentPresenter;

在上述更改之后,我现在可以在组合框列(在第一列中)的 SelectionChanged 事件中动态地将数据模板分配给 contentPresenter,如下所示。

DataTemplate dt = new DataTemplate();
                switch (propertyName)
                {
                    case "DocumentName":
                        dt = this.FindResource("AutoCompleteBoxTemplate") as DataTemplate;
                        break;
                    case "DateCreated":
                    case "DateModified":
                    case "DateAccessed":
                        dt = this.FindResource("DatePickerTemplate") as DataTemplate;
                        break;
                    default:
                        dt = this.FindResource("AutoCompleteBoxTemplate") as DataTemplate;
                        break;
                }
                contentPresenter.ContentTemplate  = dt;

但现在在第二列中,我设置的运算符值将替换为所有行中的最新运算符。例如,如果在第一个组合框中选择的属性是 TemplateName,则会出现两个运算符(Equal、NotEqual)的列表。但是,当在第一个组合框中选择 DateCreated 时,第二行中的运算符列应显示(<、<=、>、>=)。但由于我使用comboxColumn(columnOperator) 的名称分配这些运算符,因此第一行中的运算符也更新为DateCreated 的运算符。如何恢复前几行的值?

I have a WPF Datagrid with three columns. The first two columns DataGridComboBox Columns. The third column is the Template column with ContentControl inside. I want to use this Datagrid as Data entry form for an advanced search. The first column will be binded with the list of properties about a document in the databse (like DocumentName, OwnerName, DateCreated etc). The second column will be a list of Operators (<,<=,!=). These operators will be dynamically changed based on the property selected from the combobox in the
cell[0]. This is handled in the SelectionChanged event of the first comboBox.

Inside the content control(In cell[2]),I need to load a DataTempalte(each contains diffetent UI controls like autocompleteBox,DatePicker,etc) defined in the window's Resources based on the property selected in the comboBox in the first colum. I have added a custom template selector for this purpose. But I am unable to access the DataGrid ComboxBox and its content of the first cell inside the DataTempalte selector code.

Please note that I didn't want to bind existing data to the datagrid. The datagrid will be used as data entry form. So I always want to retain the values selected in the previous rows in edit mode only.

Please refer the sample code from my UI and code behind:

public class DocumentSearchProperty
{
    public string PropertyName { get; set; }
    public string Operator { get; set; }
    public string PropertyValue { get; set; }
}

This is the class which I set as a itemsource for my Datasource.

<DataGrid AutoGenerateColumns="False" Width="Auto" Name="documentPropertyGrid"
                            ItemsSource="{}"
                            SelectionMode="Single" CanUserAddRows="True" CanUserDeleteRows="True" CanUserResizeColumns="True" CanUserSortColumns="True" 
                            CanUserResizeRows="False" FrozenColumnCount="0" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" RowHeaderWidth="0"
                            AlternatingRowBackground="Gainsboro"  AlternationCount="2" VerticalContentAlignment="Stretch" VerticalAlignment="Top" VerticalScrollBarVisibility="Auto">
                            <DataGrid.Columns>
                                <DataGridComboBoxColumn x:Name="columnProperty" ItemsSource="{}" SelectedItemBinding="{Binding Path=Id}" 
                                                 Header="Property" Width="170"/>
                                <DataGridComboBoxColumn x:Name="columnOperator" ItemsSource="{}" SelectedItemBinding="{Binding Path=value}" Header="Operator" Width="170" />
                                <DataGridTemplateColumn x:Name="PropertyValue" Header="Value" Width="100">
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <ContentControl x:Name="CntControl">
                                                <ContentControl.Content>1</ContentControl.Content>
                                            </ContentControl>
                                    </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>
                            </DataGrid.Columns>
                        </DataGrid>

The below code is used to handle the selection changed event of the first comboBox. Inside this selection changed event I can get the ComboBox in the cell[1]. But I cannot get the ContentControl in cell[2]. Can anybody suggest a better way to achiveve this?

DataGridRow row = this.documentPropertyGrid.ItemContainerGenerator.ContainerFromIndex(this.documentPropertyGrid.SelectedIndex) as DataGridRow;
            ComboBox ele = this.documentPropertyGrid.Columns[0].GetCellContent(row) as ComboBox;
            ContentControl contentControl = this.documentPropertyGrid.Columns[2].GetCellContent(row) as ContentControl;

I have made following changes for getting the third column of the grid as content presenter:

ContentPresenter contentPresenter = this.documentPropertyGrid.Columns[2].GetCellContent(row) as ContentPresenter;

After the above change I can now assign a datatemplate dynamically to the contentPresenter as follows in the SelectionChanged event of the comboxBox Column(in the first column).

DataTemplate dt = new DataTemplate();
                switch (propertyName)
                {
                    case "DocumentName":
                        dt = this.FindResource("AutoCompleteBoxTemplate") as DataTemplate;
                        break;
                    case "DateCreated":
                    case "DateModified":
                    case "DateAccessed":
                        dt = this.FindResource("DatePickerTemplate") as DataTemplate;
                        break;
                    default:
                        dt = this.FindResource("AutoCompleteBoxTemplate") as DataTemplate;
                        break;
                }
                contentPresenter.ContentTemplate  = dt;

But now in the second column the Operator values which I have set are replaced with the latest operator in all the rows. For e-g If the property selected in the first combo box is TemplateName there will be a list of two operators (Equal,NotEqual). But when the DateCreated is selected in the first comboBox then the operator column in the second row should display (<,<=,>,>=). But since I am assigning these operators by using the name of the comboxColumn(columnOperator), the operators in the first row also updated with operators for DateCreated. How to restore the values in previous rows?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文