【发布时间】:2019-07-18 08:55:39
【问题描述】:
我目前在 WPF 中遇到问题,在重新实例化绑定的 ObservableCollection 时,DataGrid 的水平 ScrollViewer 会捕捉到可能滚动空间的右侧(显示 DataGrid 的最右侧内容)。
即使我在调用绑定事件时触发手动将 HorizontalOffset 设置为 0 的行为,并在重新绑定列表后立即调用该事件,0 也会被忽略,并且 snap 再次转到右侧。我认为这与 ScrollViewer 中的操作顺序和命令队列有关。
这似乎应该是默认行为(我不确定为什么您希望滚动条在填充数据时默认对齐到右侧)。有人知道这个问题的解决方法吗?
根据要求,我的复制项目中的代码文件。
MainWindow.xaml
<Window x:Class="WpfScrollViewer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfScrollViewer"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button Content="Rebind" Command="{Binding RebindCommand}"/>
<Button Content="Clear and Set" Command="{Binding ClearCommand}"/>
</StackPanel>
<DataGrid ItemsSource="{Binding People}" Grid.Row="1" HorizontalScrollBarVisibility="Visible" FontSize="30">
</DataGrid>
</Grid>
Person.cs
namespace WpfScrollViewer
{
public class Person
{
public string FirstNames { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public string PostCode { get; set; }
public string PhoneNumber { get; set; }
}
}
DelegateCommand.cs
using System;
using System.Windows.Input;
namespace WpfScrollViewer
{
public class DelegateCommand : ICommand
{
private readonly Action _fn;
private readonly Func<bool> _canExecute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action fn, Func<bool> canExecute = null)
{
_fn = fn;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute();
}
public void Execute(object parameter)
{
_fn();
}
}
}
MainViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
namespace WpfScrollViewer
{
public class MainViewModel : INotifyPropertyChanged
{
private readonly Random _random = new Random();
private ObservableCollection<Person> _people;
public ObservableCollection<Person> People
{
get => _people;
set
{
if (_people == value)
{
return;
}
_people = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(People)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public ICommand RebindCommand { get; }
public ICommand ClearCommand { get; }
public MainViewModel()
{
RebindCommand = new DelegateCommand(RebindPeople);
ClearCommand = new DelegateCommand(ClearAndSetPeople);
}
private void RebindPeople()
{
People = new ObservableCollection<Person>(GetPeople());
}
private void ClearAndSetPeople()
{
var people = GetPeople();
People.Clear();
foreach (var person in people)
{
People.Add(person);
}
}
private List<Person> GetPeople()
{
var people = new List<Person>
{
new Person
{
FirstNames = "John",
LastName = "Doe",
Address = "17 Random Street",
PostCode = "RN32 2JR",
Age = 31,
PhoneNumber = "07647123456"
},
new Person
{
FirstNames = "Jane",
LastName = "Doe",
Address = "17 Random Street",
PostCode = "RN32 2JR",
Age = 30
},
new Person
{
FirstNames = "Jack",
LastName = "Freens",
Address = "37 Badboi Lane",
Age = 30
},
new Person
{
FirstNames = "Richard",
LastName = "Brodget",
Address = "69 Meme Street",
Age = 31
},
new Person
{
FirstNames = "Sam",
LastName = "Orfitt",
Address = "16 Withernsea Road",
Age = 29
},
new Person
{
FirstNames = "Tom",
LastName = "Orfitt",
Address = "16 Withernsea",
Age = 27
}
};
var rmCount = _random.Next(1, 4);
for (var i = 0; i < rmCount; i++)
{
people.RemoveAt(_random.Next(people.Count));
}
return people;
}
}
}
使用“重新绑定”按钮显示我上面描述的行为。确保您稍微向右滚动,水平滚动条将在重新绑定时向右对齐。如果条完全在左侧,水平滚动条将正确地向左对齐,就像我希望它在所有情况下一样。
干杯
【问题讨论】:
-
请分享您的代码和其他问题详情
-
我添加了一些示例代码。