【问题标题】:Retrieve list of visible items in datagrid检索数据网格中可见项目的列表
【发布时间】:2016-03-29 09:40:33
【问题描述】:

我在基本数据网格中保留了当前警报和事件的列表,用户可以滚动浏览列表。用户可以选择一项并确认该特定警报。这行得通。

用户还应该大声确认所有可见项目。这就是我卡住的地方。 是否可以从数据网格中检索 currentcollectionshown 的列表?

XAML 的一部分

<Grid Background="DarkGray">
    <StackPanel Orientation="Horizontal">
        <StackPanel Orientation="Vertical">
            <Button Content="Ack visible" Command="{Binding AcknowledgeVisibleCommand}"/>
            <Button Content="Ack selected" Command="{Binding AcknowledgeSelectedCommand}"/>
        </StackPanel>    
        <DataGrid ItemsSource="{Binding AlarmAndEventList}"  SelectedItem="{Binding SelectedAlarmItem}" Background="DarkGray" IsReadOnly="True">
        </DataGrid>
    </StackPanel>
</Grid>

ViewModel 的一部分

public ObservableCollection<AlarmItem> AlarmAndEventList { get { return  _AlarmAndEventList; } }

    private void AcknowledgeVisible()
    {
        //Do something with a list of visible items in datagrid
    }

    private void AcknowledgeSelected()
    {
        if (SelectedAlarmItem != null)
        {
            AlarmAndEventInstance.updateAlarmItem(SelectedAlarmItem);
        }


    }

另外,如果用户双击一个项目,我想运行单个确认命令。响应双击数据网格的“MVVM方式”是什么?

【问题讨论】:

  • 如何在数据网格中隐藏项目(或通过绑定集合)?
  • 当您说“可见”项目时,您是指那些未被过滤掉的项目,还是指那些当前在 UI 上的可视空间中的项目。第一个当然是在你自己的控制之下,所以我假设你的意思是后者,但想检查一下......
  • 是的,我的意思是用户界面上当前可见的项目必须滚动才能看到更多项目。
  • 可以绑定到“SelectedItem”属性。应该可以“CurrentlyVisibleItems”吗?

标签: c# wpf mvvm datagrid observablecollection


【解决方案1】:
  1. 可以使用MyDataGrid.Items集合过滤掉。

  2. 您还可以在 MyDataGrid 中应用过滤。但不要显示过滤的项目。 How to filter DataGrid

【讨论】:

  • 我目前正在寻找可以绑定到我的视图模型中的属性的东西,该属性可以保存 datagridview 中当前的可见项。由于集合大于视图,因此存在滚动条。假设集合中有 20 个项目,datagridview 仅显示其中 4 个,我想将属性绑定到当前显示/对用户可见的四个项目。
  • @Snovva1 rest 16 存在,但需要滚动才能查看?
【解决方案2】:

为了观察DataGrid 中当前可见的项目,我编写了以下附加属性:

public class DataGridExtensions
{
    public static readonly DependencyProperty ObserveVisiblePersonsProperty = DependencyProperty.RegisterAttached(
        "ObserveVisiblePersons", typeof(bool), typeof(DataGridExtensions),
        new PropertyMetadata(false, OnObserveVisiblePersonsChanged));

    public static readonly DependencyProperty VisiblePersonsProperty = DependencyProperty.RegisterAttached(
        "VisiblePersons", typeof(List<Person>), typeof(DataGridExtensions),
        new PropertyMetadata(null));

    private static readonly DependencyProperty SenderDataGridProperty = DependencyProperty.RegisterAttached(
        "SenderDataGrid", typeof(DataGrid), typeof(DataGridExtensions), new PropertyMetadata(default(DataGrid)));

    private static void OnObserveVisiblePersonsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        DataGrid dataGrid = d as DataGrid;
        if (dataGrid == null)
            return;
        dataGrid.Loaded += DataGridLoaded;
    }

    private static void DataGridLoaded(object sender, RoutedEventArgs routedEventArgs)
    {
        DataGrid dataGrid = (DataGrid) sender;
        dataGrid.Loaded -= DataGridLoaded;
        ScrollViewer scrollViewer = FindChildren<ScrollViewer>(dataGrid).FirstOrDefault();
        if (scrollViewer != null)
        {
            SetSenderDataGrid(scrollViewer, dataGrid);
            scrollViewer.ScrollChanged += ScrollViewerOnScrollChanged;
        }
    }

    public static void SetObserveVisiblePersons(DependencyObject element, bool value)
    {
        element.SetValue(ObserveVisiblePersonsProperty, value);
    }

    public static bool GetObserveVisiblePersons(DependencyObject element)
    {
        return (bool) element.GetValue(ObserveVisiblePersonsProperty);
    }

    private static void SetSenderDataGrid(DependencyObject element, DataGrid value)
    {
        element.SetValue(SenderDataGridProperty, value);
    }

    private static DataGrid GetSenderDataGrid(DependencyObject element)
    {
        return (DataGrid) element.GetValue(SenderDataGridProperty);
    }

    private static void ScrollViewerOnScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        ScrollViewer scrollViewer = sender as ScrollViewer;
        if (scrollViewer == null)
            return;

        ScrollBar verticalScrollBar =
            FindChildren<ScrollBar>(scrollViewer).FirstOrDefault(s => s.Orientation == Orientation.Vertical);
        if (verticalScrollBar != null)
        {
            DataGrid dataGrid = GetSenderDataGrid(scrollViewer);

            int totalCount = dataGrid.Items.Count;
            int firstVisible = (int) verticalScrollBar.Value;
            int lastVisible = (int) (firstVisible + totalCount - verticalScrollBar.Maximum);

            List<Person> visiblePersons = new List<Person>();
            for (int i = firstVisible; i <= lastVisible; i++)
            {
                visiblePersons.Add((Person) dataGrid.Items[i]);
            }
            SetVisiblePersons(dataGrid, visiblePersons);
        }
    }

    public static void SetVisiblePersons(DependencyObject element, List<Person> value)
    {
        element.SetValue(VisiblePersonsProperty, value);
    }

    public static List<Person> GetVisiblePersons(DependencyObject element)
    {
        return (List<Person>) element.GetValue(VisiblePersonsProperty);
    }

    private static IList<T> FindChildren<T>(DependencyObject element) where T : FrameworkElement
    {
        List<T> retval = new List<T>();
        for (int counter = 0; counter < VisualTreeHelper.GetChildrenCount(element); counter++)
        {
            FrameworkElement toadd = VisualTreeHelper.GetChild(element, counter) as FrameworkElement;
            if (toadd != null)
            {
                T correctlyTyped = toadd as T;
                if (correctlyTyped != null)
                {
                    retval.Add(correctlyTyped);
                }
                else
                {
                    retval.AddRange(FindChildren<T>(toadd));
                }
            }
        }
        return retval;
    }
}

并且在DataGrid 的定义中的xaml 中,您必须编写以下内容:

nameSpaceOfAttachedProperty:DataGridExtensions.ObserveVisiblePersons="True"
nameSpaceOfAttachedProperty:DataGridExtensions.VisiblePersons="{Binding VisiblePersons, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

在您的 ViewModel 中,您将拥有如下属性:

private List<Person> visiblePersons;
public List<Person> VisiblePersons
{
    get { return visiblePersons; }
    set
    {
        visiblePersons = value;
        OnPropertyChanged();
    }
}

每次滚动时,VisiblePersons 都会更新。

在您的情况下,您必须更改附加属性中的列表类型以满足您的要求。

【讨论】:

    猜你喜欢
    • 2023-03-22
    • 1970-01-01
    • 2018-12-20
    • 2016-08-24
    • 2010-12-23
    • 2011-10-13
    • 2018-05-03
    • 2015-04-18
    • 1970-01-01
    相关资源
    最近更新 更多