【问题标题】:WPF disable interacting with DataGrid's TemplateColumn for new rows before they are addedWPF 在添加新行之前禁用与 DataGrid 的 TemplateColumn 交互
【发布时间】:2019-03-20 21:33:03
【问题描述】:

例如,考虑 WPF DataGridDataGridTemplateColumn(s) 并允许用户启动添加 CanUserAddRows="True"

<DataGrid AutoGenerateColumns="False" CanUserAddRows="True" ItemsSource="{Binding Options}">
    <DataGrid.Columns>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <RadioButton IsChecked="{Binding IsChecked}" GroupName="OptionsRad"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="Option" Binding="{Binding OptionName}"/>
    </DataGrid.Columns>
</DataGrid>

由于托管DataGridTemplateColumnRadioButton 可以在不进入 CellEditingMode 的情况下进行交互,这是预期和期望的。
然而,有一个问题是,在最后一个“添加新选项”,行类型 RadioButton 可以与 甚至在添加新选项之前进行交互(即将添加名称已输入)。可能选择不存在的选项并将焦点转移到其他地方。

如何在将新行添加到绑定集合之前禁用与模板列的交互?

【问题讨论】:

  • 有一个属性DataGridRow.IsNewItem,您可以将其与相对源绑定(like this)。表示您可以在单元格模板 (like this) 中使用 datatrigger 来隐藏RadioButton
  • @Sinatr 几乎 - 但是它永远保持禁用状态。无法选择任何新选项。似乎DataGridRow.IsNewItem 在所有新项目上都是正确的,而不仅仅是添加新行。 (与Binding = "{Binding IsNewItem, RelativeSource = {RelativeSource Mode = FindAncestor, AncestorType = DataGridRow}}"
  • 看起来像issue,是的。尝试使用像this 这样的事件来调查是否有办法将现有项目的IsNewItem 更改为false 或与CollectionView.NewItemPlaceholder 进行比较以确定它是否是最后一行并可能设置附加属性值你can bind 触发而不是IsNewItem

标签: c# wpf wpfdatagrid


【解决方案1】:

你也可以和NewItemPlaceholderpurely in XAML比较:

<DataTemplate>
    <RadioButton x:Name="Radio" IsChecked="{Binding IsChecked}" GroupName="OptionsRad" />
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Item, RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridRow}}"
                     Value="{x:Static CollectionView.NewItemPlaceholder}">
            <Setter TargetName="Radio" Property="IsEnabled" Value="False" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

【讨论】:

    【解决方案2】:

    您可以使用转换器来实现您想要做的事情。

    我假设您有一个类或数据类型来表示您的 Option 数据,而 Options 是这些项目的集合。

    您可以将IsEnabled 上的RadioButton 设置为:

    IsEnabled="{Binding Path=Item, RelativeSource={RelativeSource AncestorType=DataGridRow"}, Converter={StaticResource DataToEnabledConverter}}"
    

    而且,转换器代码如下所示:

    public class DataToEnabledConverter : IValueConverter
    {
         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
         {
             return value is Option;
         }
    
         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
             throw new NotImplementedException();
         }
    }
    

    您的完整 XAML 如下所示:

        <DataGrid AutoGenerateColumns="False" CanUserAddRows="True" ItemsSource="{Binding Options}">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <RadioButton IsChecked="{Binding IsChecked}" GroupName="OptionsRad" 
                                         IsEnabled="{Binding Path=Item, RelativeSource={RelativeSource AncestorType=DataGridRow"}, Converter={StaticResource DataToEnabledConverter}}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Header="Option" Binding="{Binding OptionName}"/>
            </DataGrid.Columns>
        </DataGrid>
    

    之所以有效,是因为 DataGridRow 上新行的 Item 属性将是 NamedObject 类型,而不是您的数据类型。

    【讨论】:

    • 这是我最终得到的解决方案,尽管与 CollectionView.NewItemPlaceholder 相比,有更通用的转换器来完成这项工作,如 cmets 中所述。
    猜你喜欢
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2011-08-27
    • 2015-04-06
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    • 2012-08-06
    相关资源
    最近更新 更多