【问题标题】:WPF DataGrid: Blank Row MissingWPF DataGrid:缺少空白行
【发布时间】:2010-11-30 19:37:38
【问题描述】:

我正在创建一个带有DataGrid 的 WPF 窗口,并且我想在网格底部显示空白的“新项目”行,以便向网格添加新项目。出于某种原因,空白行未显示在我窗口的网格上。这是我用来创建DataGrid 的标记:

<toolkit:DataGrid  x:Name="ProjectTasksDataGrid" 
                   DockPanel.Dock="Top" 
                   Style="{DynamicResource {x:Static res:SharedResources.FsBlueGridKey}}"
                   AutoGenerateColumns="False" 
                   ItemsSource="{Binding SelectedProject.Tasks}" 
                   RowHeaderWidth="0" 
                   MouseMove="OnStartDrag" 
                   DragEnter="OnCheckDropTarget" 
                   DragOver="OnCheckDropTarget" 
                   DragLeave="OnCheckDropTarget" 
                   Drop="OnDrop" 
                   InitializingNewItem="ProjectTasksDataGrid_InitializingNewItem">
    <toolkit:DataGrid.Columns>
        <toolkit:DataGridCheckBoxColumn HeaderTemplate="{DynamicResource {x:Static res:SharedResources.CheckmarkHeaderKey}}" Width="25" Binding="{Binding Completed}" IsReadOnly="false"/>
        <toolkit:DataGridTextColumn Header="Days" Width="75" Binding="{Binding NumDays}" IsReadOnly="false"/>
        <toolkit:DataGridTextColumn Header="Due Date" Width="75" Binding="{Binding DueDate, Converter={StaticResource standardDateConverter}}" IsReadOnly="false"/>
        <toolkit:DataGridTextColumn Header="Description" Width="*" Binding="{Binding Description}" IsReadOnly="false"/>
    </toolkit:DataGrid.Columns>
</toolkit:DataGrid>

我不明白为什么没有显示空白行。我已经尝试了明显的东西(IsReadOnly="false"CanUserAddRows="True"),但没有运气。知道为什么空白行被禁用吗?感谢您的帮助。

【问题讨论】:

    标签: wpf datagrid wpfdatagrid


    【解决方案1】:

    Vincent Sibal 发布了article describing what is required for adding new rows to a DataGrid。有很多可能性,其中大部分取决于您为SelectedProject.Tasks 使用的集合类型。

    我建议确保“Tasks”不是只读集合,并且它支持所需的接口之一(在上一个链接中提到)以允许使用 DataGrid 正确添加新项目。

    【讨论】:

    • 其实Tasks是一个ObservableCollection。我做了一个将数据网格绑定到同一种集合的测试项目,空白行出现在网格的底部。 Vincent 的博客文章不错,但他听起来好像您必须实现 IEditableObject,但事实并非如此。绑定到 ObservableCollection 的普通普通 DataGrid 应该显示空白行。见codeproject.com/KB/WPF/MVVM_DataGrid.aspx
    • 非常感谢您的帮助。真诚的。
    【解决方案2】:

    这发生在我身上,我忘了更新实例,这对我来说是一场噩梦。一旦我在 onviewloaded 中创建了集合的实例,它就解决了。

    `observablecollection<T> _newvariable = new observablecollection<T>();`
    

    这解决了我的问题。希望它可以帮助别人

    【讨论】:

      【解决方案3】:

      对我来说,实现可编辑异步 DataGrid 的最佳方式如下:

      查看模型:

       public class UserTextMainViewModel : ViewModelBase
      { 
          private bool _isBusy;
          public bool IsBusy
          {
              get { return _isBusy; }
              set
              {
                  this._isBusy = value;
                  OnPropertyChanged();
              }
          }
      
      
      
      
          private bool _isSearchActive;
          private bool _isLoading;
      
      
          private string _searchInput;
          public string SearchInput
          {
              get { return _searchInput; }
              set
              {
                  _searchInput = value;
                  OnPropertyChanged();
      
                  _isSearchActive = !string.IsNullOrEmpty(value);
                  ApplySearch();
              }
          }
      
          private ListCollectionView _translationsView;
          public ListCollectionView TranslationsView
          {
              get
              {
                  if (_translationsView == null)
                  {
                      OnRefreshRequired();
                  }
      
                  return _translationsView;
              }
              set
              {
                  _translationsView = value;
                  OnPropertyChanged();
              }
          }
      
      
          private void ApplySearch()
          {
              var view = TranslationsView;
      
              if (view == null) return;
      
              if (!_isSearchActive)
              {
                  view.Filter = null;
              }
              else if (view.Filter == null)
              {
                  view.Filter = FilterUserText;
              }
              else
              {
                  view.Refresh();
              }
          }
      
          private bool FilterUserText(object o)
          {
              if (!_isSearchActive) return true;
      
              var item = (UserTextViewModel)o;
      
              return item.Key.Contains(_searchInput, StringComparison.InvariantCultureIgnoreCase) ||
                     item.Value.Contains(_searchInput, StringComparison.InvariantCultureIgnoreCase);
          }
      
      
      
      
          private ICommand _clearSearchCommand;
          public ICommand ClearSearchCommand
          {
              get
              {
                  return _clearSearchCommand ??
                         (_clearSearchCommand =
                          new DelegateCommand((param) =>
                          {
                              this.SearchInput = string.Empty;
      
                          }, (p) => !string.IsNullOrEmpty(this.SearchInput)));
              }
          }
      
          private async void OnRefreshRequired()
          {
              if (_isLoading) return;
      
              _isLoading = true;
              IsBusy = true;
              try
              {
                  var result = await LoadDefinitions();
                  TranslationsView = new ListCollectionView(result);
              }
              catch (Exception ex)
              {
                  //ex.HandleError();//TODO: Needs to create properly error handling
              }
      
              _isLoading = false;
              IsBusy = false;
          }
      
      
          private async Task<IList> LoadDefinitions()
          {
              var translatioViewModels = await Task.Run(() => TranslationRepository.Instance.AllTranslationsCache
              .Select(model => new UserTextViewModel(model)).ToList());
              return translatioViewModels;
          }
      
      
      }
      

      XAML

      <UserControl x:Class="UCM.WFDesigner.Views.UserTextMainView"
               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
               xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
               xmlns:model="clr-namespace:Cellebrite.Diagnostics.Model.Entities;assembly=Cellebrite.Diagnostics.Model"
               xmlns:System="clr-namespace:System;assembly=mscorlib"
               xmlns:converters1="clr-namespace:UCM.Infra.Converters;assembly=UCM.Infra"
               xmlns:core="clr-namespace:UCM.WFDesigner.Core"
               mc:Ignorable="d"
               d:DesignHeight="300"
               d:DesignWidth="300">
      
      
      <DockPanel>
          <StackPanel Orientation="Horizontal"
                      DockPanel.Dock="Top"
                      HorizontalAlignment="Left">
      
      
              <DockPanel>
      
                  <TextBlock Text="Search:"
                             DockPanel.Dock="Left"
                             VerticalAlignment="Center"
                             FontWeight="Bold"
                             Margin="0,0,5,0" />
      
                  <Button Style="{StaticResource StyleButtonDeleteCommon}"
                          Height="20"
                          Width="20"
                          DockPanel.Dock="Right"
                          ToolTip="Clear Filter"
                          Command="{Binding ClearSearchCommand}" />
      
                  <TextBox Text="{Binding SearchInput, UpdateSourceTrigger=PropertyChanged}"
                           Width="500"
                           VerticalContentAlignment="Center"
                           Margin="0,0,2,0"
                           FontSize="13" />
      
              </DockPanel>
          </StackPanel>
          <Grid>
              <DataGrid ItemsSource="{Binding Path=TranslationsView}"
                        AutoGenerateColumns="False"
                        SelectionMode="Single"
                        CanUserAddRows="True">
                  <DataGrid.Columns>
                    <!-- your columns definition is here-->
                  </DataGrid.Columns>
              </DataGrid>
              <!-- your "busy indicator", that shows to user a message instead of stuck data grid-->
              <Border Visibility="{Binding IsBusy,Converter={converters1:BooleanToSomethingConverter TrueValue='Visible', FalseValue='Collapsed'}}"
                      Background="#50000000">
                  <TextBlock Foreground="White"
                             VerticalAlignment="Center"
                             HorizontalAlignment="Center"
                             Text="Loading. . ."
                             FontSize="16" />
              </Border>
          </Grid>
      </DockPanel>
      

      这种模式允许以非常简单的方式使用数据网格,代码也非常简单。 不要忘记为代表您的数据源的类创建默认构造函数。

      【讨论】:

        【解决方案4】:

        在我看来,这是 DataGrid 中的一个错误。 Mike Blandford's link 帮助我最终意识到问题所在:DataGrid 在绑定了真实对象之前无法识别行的类型。编辑行没有出现 b/c 数据网格不知道列类型。你会认为绑定一个强类型的集合会起作用,但事实并非如此。

        要扩展 Mike Blandford 的答案,您必须首先分配空集合,然后添加和删除一行。例如,

            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                // data binding
                dataGridUsers.ItemsSource = GetMembershipUsers();
                EntRefUserDataSet.EntRefUserDataTable dt = (EntRefUserDataSet.EntRefUserDataTable)dataGridUsers.ItemsSource;
                // hack to force edit row to appear for empty collections
                if (dt.Rows.Count == 0)
                {
                    dt.AddEntRefUserRow("", "", false, false);
                    dt.Rows[0].Delete();
                }
            }
        

        【讨论】:

          【解决方案5】:

          向您的 ItemsSource 添加一个空项目,然后将其删除。执行此操作后,您可能必须将 CanUserAddRows 设置回 true。我读了这个解决方案here:(Jarrey 和 Rick Roen 的帖子)

          当我将 ItemsSource 设置为 DataTable 的 DefaultView 并且视图为空时,我遇到了这个问题。列已定义,因此它应该能够获取它们。呵呵。

          【讨论】:

          • 呃。谢谢。这一直让我发疯。我最终放弃了实体,转而使用类型化数据集,甚至 that 都失败了。诀窍是先分配集合,然后然后通过添加和删除对象来操作它。
          【解决方案6】:

          终于回到了这个。我不会更改接受的答案(绿色复选标记),但这是问题的原因:

          My View Model 包装域类以提供 WPF 所需的基础结构。我在我使用的 wrap 方法上写了一个CodeProject article,其中包括一个有两个类型参数的集合类:

          VmCollection<VM, DM>
          

          其中 DM 是一个封装的域类,DM 是封装它的 WPF 类。

          事实证明,出于某种奇怪的原因,在集合类中具有第二个类型参数会导致 WPF DataGrid 变得不可编辑。解决方法是消除第二个类型参数。

          不能说为什么会这样,只能说是这样。希望它可以帮助其他人。

          【讨论】:

            【解决方案7】:

            您还必须对集合中的类型有一个默认构造函数。

            【讨论】:

            • 这是应该检查的答案>。
            • 是的,这是我遇到的同样问题的答案。
            • 如果集合是接口类型怎么办? ObservableCollection&lt;IThing&gt;
            • 我错过了这个正确答案,因为它在 bootom 上,没有代码。
            • 还要注意构造函数必须是public。似乎 DataGrid 没有考虑 internalprivate 构造函数。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-12-13
            • 2014-07-03
            • 2014-05-08
            • 1970-01-01
            • 1970-01-01
            • 2013-08-15
            • 1970-01-01
            相关资源
            最近更新 更多