C# WPF DataGrid SelectedItem奇怪的行为
我们在DataGrid中看到围绕SelectedItem属性的一些奇怪行为。一些背景资料: DataGrid向我们的数据库显示查询结果。 有一个按钮允许用户手动刷新DataGrid中的结果。有一种自动刷新机制,结果将每30秒自动刷新一次 我们看到的是,当自动刷新发生时,SelectedItem属性将始终成为Datagrid的ItemsSource的索引0。但我们希望当前选定的行在刷新后保持为选定的行。但是,如果用户手动单击“刷新”,则所选行在刷新后保持不变,这很奇怪,因为刷新逻辑正在运行相同的代码。是的,我们的代码可以记住当前选择的项目,然后在刷新完成后再次设置 以下是一些相关代码:C# WPF DataGrid SelectedItem奇怪的行为,c#,wpf,datagrid,C#,Wpf,Datagrid,我们在DataGrid中看到围绕SelectedItem属性的一些奇怪行为。一些背景资料: DataGrid向我们的数据库显示查询结果。 有一个按钮允许用户手动刷新DataGrid中的结果。有一种自动刷新机制,结果将每30秒自动刷新一次 我们看到的是,当自动刷新发生时,SelectedItem属性将始终成为Datagrid的ItemsSource的索引0。但我们希望当前选定的行在刷新后保持为选定的行。但是,如果用户手动单击“刷新”,则所选行在刷新后保持不变,这很奇怪,因为刷新逻辑正在运行相同的代
<UserControl.Resources>
<CollectionViewSource Source="{Binding DataGridResults}" x:Key="ReferralItemsSource"/>
</UserControl.Resources>
<customControls:CustomDataGrid x:Name="GridControl"
ItemsSource="{Binding Source={StaticResource ReferralItemsSource}}"
SelectedItem="{Binding DataContext.SelectedReferral, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
IsReadOnly="False"
IsSynchronizedWithCurrentItem="True"
SelectionMode="Single">
如前所述,RefreshWorklist由通过以下命令调用的手动刷新调用:
或通过使用计时器自动:
有人知道为什么会发生这种行为吗?这和计时器有关吗?我理解这不是一个简单的问题,因此请询问更多信息。您需要在UI线程上分配与UI绑定的属性 调用RefreshWorklist时,请使用Dispatcher.Invoke或Dispatcher.BeginInvoke替换计时器,或在现有计时器回调中使用Dispatcher.Invoke或Dispatcher.BeginInvoke 通过按下按钮,您已经在UI线程上,但计时器有自己的线程,与UI线程不同。
而是在UI线程上调用Dispatchermer回调您是否尝试过:SelectedItem={Binding DataContext.SelectedReferal,RelativeSource={RelativeSource AncestorType={x:Type UserControl},Mode=TwoWay}?@NawedNabiZada是的,我尝试过,似乎没有影响它。
private async void RefreshWorklist(bool invokedByAutoRefresh = false)
{
try
{
if (Initialising || ShowSpinner || IsProcessing || ShowRefreshSpinner || IsCurrentWorklistDeleted || !_sessionData.IsActive()) return;
IsProcessing = true;
RefreshWorklistCommand.RaiseCanExecuteChanged();
if (CurrentWorklistId != null)
{
var selectedReferralId = SelectedReferral.pk_Referral_ID;
if (invokedByAutoRefresh)
{
// Refresh has been invoked by _timer, so show spinner on the results page only
ShowRefreshSpinner = true;
}
else
{
// User has manually clicked refresh button so show app wide spinner
ShowSpinner = true;
if (_timer != null)
{
SetupWorklistRefreshTimer(); // Setup _timer again so that it will refresh again at an appropriate time
}
}
Referrals = await _referralRepository.GetReferralsFromWorklistAsync(CurrentWorklistId.Value, invokedByAutoRefresh);
if (Filters.Count > 0)
{
var listOfReferralPks = ReferralFiltering.GetFilteredResults(Referrals, Filters.Where(f => f.HasBeenApplied).ToList());
var filteredResults = Referrals.Where(r => listOfReferralPks.Contains(r.pk_Referral_ID)).ToList();
DataGridResults = MapReferralLookupItemsToReferralLookupItemViewModels(filteredResults);
}
else
{
DataGridResults = MapReferralLookupItemsToReferralLookupItemViewModels(Referrals);
}
SelectedReferral = DataGridResults.FirstOrDefault(r => r.pk_Referral_ID == selectedReferralId);
}
}
catch (Exception e)
{
_errorHandler.DisplayError(e);
}
}
private void Execute_RefreshWorklist()
{
RefreshWorklist();
}
private void SetupWorklistRefreshTimer()
{
_timer?.Dispose();
var refreshInterval = _userSettingsRepository.GetIntegerSystemSetting("ReferralsWorklistRefreshInterval");
if (refreshInterval <= 0) return; // If this is 0 or below then the refresh should be disabled
if (refreshInterval < 10) // If it is less than 10 then set it to 10 to avoid too many MT calls
{
refreshInterval = 10;
}
var timeUntilFirstTick = refreshInterval * 1000;
_timer = new Timer((s) => RefreshWorklist(true), null, timeUntilFirstTick, refreshInterval * 1000);
}
public ReferralLookupItemViewModel SelectedReferral
{
get { return _selectedReferral; }
set
{
if (_selectedReferral != value)
{
_selectedReferral = value;
OnPropertyChanged();
}
}
}