Как сохранить фокус на строке после перезагрузки данных в DataGrid WPF MVVM - PullRequest
0 голосов
/ 29 ноября 2018

Я искал везде и не могу найти ответ на этот вопрос.Использование WPF DataGrid, привязанного к веб-API http://localhost:3000/api/profiles,, и как сохранить фокус на строке после перезагрузки данных?

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 голосов
/ 29 ноября 2018

Я думаю, вы обнаружите, что не возвращаете фокус на строку сетки данных, если просто установите selecteditem.Вам нужно поведение или код позади.Вот что я использую:

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>
0 голосов
/ 29 ноября 2018

Добавьте в ViewModel свойство для выбранного элемента:

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

Расширение лямбды (Equals() должно быть реализовано для Profile):

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

И связать CurrentProfile с DataGrid.SelectedItem в XAML:

<DataGrid ItemsSource="{Binding Profiles}" SelectionMode="Single" SelectedItem="{Binding CurrentProfile, Mode=TwoWay}">
</DataGrid>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...