【问题标题】:Style DataGridTemplateColumn to Match DataGridComboBoxColumn样式 DataGridTemplateColumn 以匹配 DataGridComboBoxColumn
【发布时间】:2017-01-28 11:06:36
【问题描述】:

编辑(澄清要求)

我有一个DataGrid,如下所示。 “存储旧 EmpNo 的字段名称”列中的值会根据“新 EmpNo 规则”列中选择的值而变化。为了适应这种情况,DataGridItemsSource 中的每个项目都有自己的TableNameForOldDataCollection。我需要绑定到这个 TableNameForOldDataCollection 而不是不能更改的静态属性。

如果在使用DataGridComboBoxTemplate 时有办法进行此绑定,我会更喜欢。如果没有,我想知道是否可以将DataGridTemplateColumn/ComboBox 模板化为与DataGridComboBoxTemplate 匹配的模板

OP

我有一个场景,我将DataGridComboBoxColumn 用于DataGrid 列之一。在另一列中,我需要使用DataGridTemplateColumnComboBox 来正确绑定到VM 中的动态ItemSource。

DataGridComboBoxColumn(“新 EmpNo 规则”)的样式与 DataGridTemplateColumn 不同,ComboBox(“存储旧 EmpNo 的字段名称”)如下所示:

如何设置DataGridTemplateColumn/ComboBox 的样式以匹配DataGridComboBoxColumn,尤其是在未选择实际单元格时如何隐藏组合框(如“New EmpNo Rule”的第二行)。

编辑(添加DataGrid 代码):

   <UserControl.Resources>
        <ResourceDictionary>
             <CollectionViewSource x:Key="StaticEmpNoRuleCollection" Source="{Binding EmpNoRuleCollection}" />                
        </ResourceDictionary>        
    </UserControl.Resources>

....

                <DataGrid Name="DataGrid_MultiCompanyInfo"
                          ItemsSource="{Binding Model.EmpNoOptionsCollection}"
                          SelectedItem="{Binding SelectedEmpNoOptions}"
                          AutoGenerateColumns="False"
                          CanUserAddRows="False"
                          CanUserDeleteRows="False">
                    <DataGrid.Columns>

                        <!-- Company -->
                        <DataGridTextColumn Header="Company" 
                                            Binding="{Binding Company}"
                                            IsReadOnly="True" />

                        <!-- New EmpNo Rule -->
                        <DataGridComboBoxColumn Header="New EmpNo Rule"
                                                Width="200"
                                                ItemsSource="{Binding Source={StaticResource StaticEmpNoRuleCollection}}"
                                                DisplayMemberPath="Description"
                                                SelectedValueBinding="{Binding SelectedEmpNoRule, UpdateSourceTrigger=PropertyChanged}"/>

                        <!-- Field Name To Store Old EmpNo -->
                        <DataGridTemplateColumn Header="Field Name To&#x0a;Store Old EmpNo"
                                                Width="150" >
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <ComboBox Name="OldEmpNo_ComboBox"
                                              Margin="-5,0,0,0"
                                              ItemsSource="{Binding TableNameForOldDataCollection}"
                                              SelectedValue="{Binding TableNameForOldData, UpdateSourceTrigger=PropertyChanged}" />
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>

                        ...

                    </DataGrid.Columns>
                </DataGrid>

【问题讨论】:

  • 能否请您发布您的 DataGridTemplateColumn 代码?
  • @Kirenenko 请参阅对 OP 的编辑。
  • 我认为正确的方法是在“Old EmpNo”上使用DataGridComboBoxColumn,但你应该正确绑定,使用RelativeSource="{RelativeSource AncestorType={x:Type DataGrid}}"
  • @Kirenenko 我最初走的这条路线行不通。根据我发现的许多不同的文章,你不能按照你的建议去做,因为 DataGridComboBoxColumn 不是可视化树的一部分(stackoverflow.com/questions/3659970/…)。这就是我必须使用 DataGridTemplateColumn 的原因。此特定列的可选值会根据其他列的选定值而变化。

标签: wpf combobox datagrid datagridcomboboxcolumn datagridtemplatecolumn


【解决方案1】:

请记住,DataGridComboBoxColumn 不在同一个可视化树中,您可以使用BindingProxy

public class BindingProxy : Freezable
{
    #region Overrides of Freezable

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}

XAML 资源:

<Window.Resources>
    <local:BindingProxy x:Key="proxy" Data="{Binding}" />
</Window.Resources>

XAML 绑定(不在可视化树上):

<DataGridComboBoxColumn ItemsSource="{Binding Data.TableNameForOldDataCollection, Source={StaticResource proxy}}"/>

更新

完全不同的解决方案...看起来有点老套,但我已经测试过它可以工作:

<DataGridComboBoxColumn Header="Field Name To&#x0a;Store Old EmpNo" Width="150"
SelectedItemBinding="{Binding TableNameForOldData, UpdateSourceTrigger=PropertyChanged}>
    <DataGridComboBoxColumn.ElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding TableNameForOldDataCollection}"/>
            <Setter Property="IsReadOnly" Value="True"/>
        </Style>
    </DataGridComboBoxColumn.ElementStyle>
    <DataGridComboBoxColumn.EditingElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding TableNameForOldDataCollection}"/>
        </Style>
    </DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>

我也认为是duplicate,所以我会标记它。

【讨论】:

  • 虽然我喜欢这种提供可绑定集合的选项,但它不适用于我的场景(请参阅 OP 中的附加要求)。它似乎绑定到 DataGrid 本身的集合,而不是 EmpNoOptionsCollection 中每个项目的属性。如果我遗漏了一些东西并且这可以满足要求,请您进一步解释一下吗?
  • 我认为您的 TableNameForOldDataCollection 在您的主 DataContext/ViewModel 上。只要告诉我要绑定的对象在哪里,因为您必须将代理“数据”指向它。
  • TableNameForOldDataCollection 位于Model.EmpNoOptionsCollection 中的每个单独项目上。 DataGrid 中的每个项目都有自己的TableNameForOldDataCollection 副本,因为值可以根据StaticEmpNoRuleCollection 的值而改变
  • 哇...现在我明白了...这是某种ItemsourceBindIngCeption。让我检查一下我是否可以做某事,但不太确定...
猜你喜欢
  • 2021-10-07
  • 2013-03-04
  • 2011-11-11
  • 2015-01-25
  • 1970-01-01
  • 2019-11-17
  • 2018-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多