在DataGrid WPF MVVM中重新加载数据后如何保持对行的关注

时间:2018-11-29 06:47:53

标签: c# wpf mvvm datagrid

我到处搜索,找不到答案。使用绑定到Web API http://localhost:3000/api/profiles的WPF DataGrid,以及如何在重新加载数据后继续关注行?

public class ProfilesViewModel : BaseViewModel
    {
private ObservableCollection<Profile> _Items;
        public ObservableCollection<Profile> Profiles { get => _Items; set { _Items = value; OnPropertyChanged(); } }

public PartyProfilesViewModel()
        {
DispatcherTimer dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Tick += dispatcherTimer_Tick;
            dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1, 100);
            dispatcherTimer.Start();

}
private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            var client = new RestClient("http://localhost:3000");

            var reqData = new RestRequest("api/profiles", Method.GET);
            client.ExecuteAsync(reqData, resData =>
            {
                Profiles = JsonConvert.DeserializeObject<ObservableCollection<Profile>>(resData.Content);
            });

        }

}

谢谢!

2 个答案:

答案 0 :(得分:1)

在ViewModel中添加所选项目的属性:

private _currentProfile=null;
public Profile CurrentProfile { get => _currentProfile; set { CurrentProfile = value; OnPropertyChanged(); } }

扩展您的lambda(必须为Equals()实现 Profile

client.ExecuteAsync(reqData, resData =>
{
    var curProf = CurrentProfile;
    Profiles = JsonConvert.DeserializeObject<ObservableCollection<Profile>>(resData.Content);
    CurrentProfile=Profiles.FirstOrDefault((p)=>p.Equals(curProf));
});

并将CurrentProfile绑定到XAML中的DataGrid.SelectedItem

<DataGrid ItemsSource="{Binding Profiles}" SelectionMode="Single" SelectedItem="{Binding CurrentProfile, Mode=TwoWay}">
</DataGrid>

答案 1 :(得分:0)

我想您会发现,如果只设置selecteditem,就不会将注意力集中在datagrid行上。您需要后面的行为或代码。 这是我的用途:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace wpf_EntityFramework
{
    /// <summary>
    ///  Attached Behavior
    ///  Somewhat trickier than a regular behavior because it's to be attached via a style 
    /// </summary>
    class DataGridRowBehavior : Behavior<DataGridRow>
    {
        public static bool GetIsDataGridRowFocussedWhenSelected(DataGridRow dataGridRow)
        {
            return (bool)dataGridRow.GetValue(IsDataGridRowFocussedWhenSelectedProperty);
        }

        public static void SetIsDataGridRowFocussedWhenSelected(
          DataGridRow dataGridRow, bool value)
        {
            dataGridRow.SetValue(IsDataGridRowFocussedWhenSelectedProperty, value);
        }

        public static readonly DependencyProperty IsDataGridRowFocussedWhenSelectedProperty =
            DependencyProperty.RegisterAttached(
            "IsDataGridRowFocussedWhenSelected",
            typeof(bool),
            typeof(DataGridRowBehavior),
            new UIPropertyMetadata(false, OnIsDataGridRowFocussedWhenSelectedChanged));

        static void OnIsDataGridRowFocussedWhenSelectedChanged(
          DependencyObject depObj, DependencyPropertyChangedEventArgs e)
        {
            DataGridRow item = depObj as DataGridRow;
            if (item == null)
                return;

            if (e.NewValue is bool == false)
                return;

            if ((bool)e.NewValue)
                item.Selected += OndataGridRowSelected;
            else
                item.Selected -= OndataGridRowSelected;
        }
        static void OndataGridRowSelected(object sender, RoutedEventArgs e)
        {
            DataGridRow row = e.OriginalSource as DataGridRow;
            // If focus is already on a cell then don't focus back out of it
            if (!(Keyboard.FocusedElement is DataGridCell) && row != null)
            {
                row.Focusable = true;
                Keyboard.Focus(row);
            }
        }

    }
}

using System;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace wpf_EntityFramework
{
    class ScrollDataGridRowIntoView : Behavior<DataGrid>
    {
        protected override void OnAttached()
        {

            base.OnAttached();
            this.AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
        }

        void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (sender is DataGrid)
            {
                DataGrid datagrid = (sender as DataGrid);
                if (datagrid.SelectedItem != null)
                {
                    datagrid.Dispatcher.BeginInvoke((Action)(() =>
                    {
                        datagrid.UpdateLayout();
                        if (datagrid.SelectedItem != null)
                        {
                            datagrid.ScrollIntoView(datagrid.SelectedItem);
                        }
                    }));
                }
            }
        }
        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged;
        }
    }
}

用法

        <DataGrid ....
                  >
            <i:Interaction.Behaviors>
                <local:ScrollDataGridRowIntoView />
            </i:Interaction.Behaviors>
            <DataGrid.RowStyle>
                <Style TargetType="{x:Type DataGridRow}">
                    <Setter Property="local:DataGridRowBehavior.IsDataGridRowFocussedWhenSelected" Value="true"/>
                </Style>
            </DataGrid.RowStyle>