简体   繁体   中英

Retrieve list of visible items in datagrid

I keep a list of current alarms and events in a basic datagrid, the user can scroll through the list. The user can select one item and acknowledge that specific alarm. This works.

The user should also be aloud to acknowledge all visible items. This is where im stuck. Is it possible to retrieve a list of currentcollectionshown from a datagrid?

Part of 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>

Part of 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);
        }


    }

Also, I want to run the single acknowledge command if the user double clicks an item. What is the "MVVM Way" of responding to a double click on a datagrid?

To observe the currently visible items in a DataGrid I have written the following attached-property:

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;
    }
}

And in the xaml in the definition of your DataGrid you have to write the following:

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

And in your ViewModel you will have a property like:

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

And every time you scroll the VisiblePersons will be updated.

In your case you have to changed the type of the List inside the attached-propertay to match your requirements.

  1. You can use MyDataGrid.Items collection to filter out.

  2. You can also apply filtering in your MyDataGrid. But don't show filtered items. How to filter DataGrid

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM