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



我到处找了,找不到答案。使用绑定到Web API的WPF数据网格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);
});
}
}

谢谢!

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

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

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

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>

我想如果你只设置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>

最新更新