【问题标题】:Selected Datagrid row shows black box around first cell instead of blue highlighting选定的 Datagrid 行在第一个单元格周围显示黑框,而不是蓝色突出显示
【发布时间】:2017-02-01 18:23:29
【问题描述】:

我的 Datagrid 的 Itemsource 更新导致 selectedItem 设置为 null 的问题已经有一段时间了。我一直在疯狂地搜索,终于找到了所需行保持选中状态的东西,但是我在行的第一个单元格周围出现了一个黑框,而不是突出显示了整行。单击向上/向下箭头键将更改所选行,并且新行将按预期突出显示。

这是我的 XAML:

    <DataGrid ItemsSource="{Binding Path=FilteredSimResults}" ColumnWidth="*" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" IsReadOnly="True"
              SelectedItem="{Binding Path=SelectedPdf}" SelectionMode="Single" SelectionUnit="FullRow" AlternatingRowBackground="LightGray"
              Visibility="{Binding Path=IsNotPopulating}" Margin="5,0" Name="PdfList"
              AutoGeneratingColumn="OnAutoGeneratingColumn">
        <DataGrid.Resources>
            <Style TargetType="{x:Type DataGridRow}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsBold}" Value="True">
                        <Setter Property="FontWeight" Value="Bold" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.Resources>
        <DataGrid.ItemContainerStyle>
            <Style TargetType="DataGridRow">
                <EventSetter Event="Selected" Handler="OnRowSelected"/>
            </Style>
        </DataGrid.ItemContainerStyle>
    </DataGrid>

这是我的代码:

    public SimulationGrid()
    {
        InitializeComponent();
        CollectionView myCollectionView = (CollectionView)CollectionViewSource.GetDefaultView(PdfList.Items);
        ((INotifyCollectionChanged)myCollectionView).CollectionChanged += OnItemSourceChanged;
    }

    private void OnItemSourceChanged(object sender, EventArgs e)
    {
        if (_index == null) return;
        object item = _index;
        Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
        {
            PdfList.SelectedItem = item;
            PdfList.ScrollIntoView(item);
            DataGridRow row = (DataGridRow)PdfList.ItemContainerGenerator.ContainerFromItem(item);
            row.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
        }));
    }

    private void OnRowSelected(object sender, RoutedEventArgs e)
    {
        _index = ((DataGridRow)sender).Item;
    }

编辑: 我对此有约束力:

    public List<SimResult> FilteredSimResults
    {
        get
        {
            List<SimResult> filteredResults = new List<SimResult>();
            if (!Populating && SimResults != null)
            {
                foreach (SimResult result in SimResults)
                {
                    if ((string.IsNullOrEmpty(FilterKey) || result.PatientId.ToLower().Contains(FilterKey.ToLower()))
                        && (ShowingHiddenSims != result.IsVisible))
                    {
                        filteredResults.Add(result);
                    }
                }
            }
            return SimSortDirection == ListSortDirection.Descending
                ? filteredResults.OrderByDescending(o => o.GetType().GetProperty(SimSortColumn).GetValue(o)).ToList()
                : filteredResults.OrderBy(o => o.GetType().GetProperty(SimSortColumn).GetValue(o)).ToList();
        }
    }

完整的列表保存在内存中(SimResults),但它有几个可以修改列表的东西,所以只有修改后的列表被发送到绑定。所以,每次修改,都会修改完整的列表。

【问题讨论】:

  • 很难说没有看到 DataGrid 绑定到什么。您没有对 FilteredSimResults 的代码隐藏引用,它是 DataGrid 的 ItemsSource。那是 ObservableCollection 吗?还有数据是如何被编辑的?您是否替换了网格中的所有值。你要替换被选中的那个吗?您是否将对象留在列表中并仅编辑属性等?
  • 我添加了有关我要绑定的内容的详细信息。

标签: c# wpf datagrid


【解决方案1】:

问题是每次更新都会完全替换您的项目列表。

当 FilteredSimResults 返回时,它每次都返回一个完全不同的 List 对象,这不是处理这类事情的好方法。

如果您想在代码后面或 ViewModel 中更新数据(如果您使用 MVVM),您应该使用 ObservableCollection,这正是它的用途。

public ObservableCollection<SimResult> SimResults { get; set; } = new ObservableCollection<SimResult>();

在您的 XAML 中绑定到它是这样的:

<DataGrid x:Name="dataGrid" HorizontalAlignment="Left" VerticalAlignment="Top" Height="319" Width="517" ItemsSource="{Binding SimResults}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="PatientId" Binding="{Binding PatientId}"/>
    </DataGrid.Columns>
</DataGrid>

一旦您对 ObservableCollection 所做的任何更改都将反映在 Grid 中。需要注意的一件事是您的 SimsResults 类必须实现 INotifyPropertyChanged 事件。

如果您删除或完全删除项目,您仍然会遇到此问题,但您永远不应该删除项目,只需更改它的属性。

【讨论】:

  • 我并没有真正看到如何让 ObservableCollection 执行我当前实现所做的任何过滤或排序。
  • 用于过滤、排序和分组您想要的是 CollectionViewSource。 msdn.microsoft.com/en-us/library/… 因此,您将集合设为 ObservableCollection,然后将其输入 CollectionViewSource 并将您的 View 绑定到 CollectionViewSource。然后你可以过滤、排序、分组任何你想要的。
猜你喜欢
  • 2015-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-27
  • 2015-12-04
  • 2023-03-26
  • 2016-06-13
  • 2013-12-20
相关资源
最近更新 更多