【问题标题】:Modifying user control in WPF DataGrid on edit在编辑时修改 WPF DataGrid 中的用户控件
【发布时间】:2014-05-15 22:26:38
【问题描述】:

我是 WPF 的新手,在尝试解决一个看似简单的问题时遇到了困难。

我需要设计一个数据表并允许用户对其进行编辑。当用户开始编辑单元格时,我需要在最右边的列 [OK] 和 [Cancel] 中显示一组按钮来接受或取消更改。当用户不编辑单元格时,应显示 [Delete] 按钮供用户删除行。

我编写了一个自定义控件,该控件将根据自定义 IsInEditMode 属性显示 [OK][Cancel] 或单个 [Delete] 按钮。

public partial class RowEditControl : UserControl
{
    public static DependencyProperty
            IsInEditModeProperty = DependencyProperty.Register( "IsInEditMode", 
                                                                    typeof(bool), 
                                                                    typeof(RowEditControl),
                                                                    new FrameworkPropertyMetadata(OnEditModeChanged));

    private static void OnEditModeChanged(DependencyObject aD, DependencyPropertyChangedEventArgs aE)
    {
        //depending on the value show [Delete] or [Ok][Cancel] buttons
    }
}

当用户开始编辑单元格时,我需要以某种方式设置 IsInEditMode。我一直在寻找整个 msdn 和这个论坛的示例/方法,但找不到任何东西。

我像这样以编程方式将自定义控件添加到最后一列:

        {
        mwTagList.Columns[1].Width = new DataGridLength(1, DataGridLengthUnitType.Star);

        var fRowEditTemplate = new FrameworkElementFactory(typeof (RowEditControl));

        fRowEditTemplate.AddHandler(
                                   RowEditControl.DeleteClickedEvent,
                                   new RoutedEventHandler(OnDeleteRowBtn)
            );

        fRowEditTemplate.AddHandler(
                                 RowEditControl.OkClickedEvent,
                                 new RoutedEventHandler(OnRowEditOk));

        fRowEditTemplate.AddHandler(
                                 RowEditControl.CancelClickedEvent,
                                 new RoutedEventHandler(OnRowEditCancel));

        mwTagList.Columns.Add(
                              new DataGridTemplateColumn()
                              {
                                  Header = "Delete Row",
                                  CellTemplate = new DataTemplate() {VisualTree = fRowEditTemplate}
                              }
            );
    }

非常感谢您提供的任何信息和提示!

【问题讨论】:

    标签: wpf wpfdatagrid


    【解决方案1】:

    我使用样式解决了这个问题:

    <Style x:Key="MwControlCellStyle" TargetType="{x:Type notesList:RowEditControl}">
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <!-- find DataGridRow parent object and trigger if it is in editing mode -->
                        <Condition Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=IsEditing}" Value="True"></Condition>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="IsInEditMode" Value="True"></Setter>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    

    【讨论】:

      【解决方案2】:

      DataGridRow 上有一个 IsEditing 依赖属性,因此您可以使用 XAML 和几个转换器来执行此操作。 XAML 的主要部分如下所示

      <Window.Resources>
      <viewModel:BooleanVisibleConverter x:Key="boolVisConv"/>
      <viewModel:InverseBooleanVisibleConverter x:Key="invBoolVisConv"/>
      
      <DataTemplate x:Key="DataGridButtonsTemplate">
          <StackPanel >
              <Button Content="Delete" Visibility ="{Binding IsEditing, Mode=OneWay, Converter={StaticResource invBoolVisConv}, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}}"/>
              <Button Content="OK"  Visibility="{Binding IsEditing, Mode=OneWay, Converter={StaticResource boolVisConv},RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}}"/>
              <Button Content="Cancel"  Visibility="{Binding IsEditing, Mode=OneWay, Converter={StaticResource boolVisConv},RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}}"/>
          </StackPanel>
      </DataTemplate>
      </Window.Resources>
      
      <DataGrid Grid.Row="1" ItemsSource="{Binding MyData}" AutoGenerateColumns="False">
          <DataGrid.Columns>
              <DataGridTextColumn Binding="{Binding FirstField}" Header="First Property"></DataGridTextColumn>
              <DataGridTextColumn Binding="{Binding SecondField}" Header="Second Property"></DataGridTextColumn>
              <DataGridTextColumn Binding="{Binding ThirdField}" Header="Third Property"></DataGridTextColumn>
              <DataGridTemplateColumn Header="Control" CellTemplate="{StaticResource DataGridButtonsTemplate}"></DataGridTemplateColumn>
          </DataGrid.Columns>
      </DataGrid>
      

      这里有一个示例转换器,显然你需要其中两个,第二个将返回值反转

          [ValueConversion(typeof(bool), typeof(Visibility))]
      public class BooleanVisibleConverter : IValueConverter
      {
          public object Convert(object value, Type targetType, object parameter,
              System.Globalization.CultureInfo culture)
          {
              if (targetType != typeof(Visibility))
                  throw new InvalidOperationException("The target must be a System.Windows.Visibility");
      
              return ((bool)value)? Visibility.Visible : Visibility.Collapsed;
          }
      
          public object ConvertBack(object value, Type targetType, object parameter,
              System.Globalization.CultureInfo culture)
          {
              throw new NotSupportedException();
          }
      }
      

      您需要确定按下的是哪个按钮,因为每行都有一个。这里有一些关于如何做到这一点的想法

      WPF DataGrid - Button in a column, getting the row from which it came on the Click event handler

      【讨论】:

      • 谢谢!我使用上述样式解决了这个问题,但这看起来也很酷。这也是如何使用转换器的一个很好的例子,我是 WPF 新手,从未使用过它们。
      猜你喜欢
      • 2019-12-04
      • 2014-07-21
      • 1970-01-01
      • 2021-11-25
      • 1970-01-01
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      • 2013-07-30
      相关资源
      最近更新 更多