ログ メッセージを表示するItemsControl
内にを含むアプリケーションのビューがあります。ScrollViewer
メッセージである文字列のコレクションはObservableCollection<string>
、ビューモデル内にあります。
新しいメッセージが追加さScrollViewer
れると、チェックボックスがチェックされているかどうかに応じて、リストの一番下までスクロールする必要があります。これを完全にビューで処理したいと思います。まともな解決策を見つけました(here)。このチェックボックスは、最初はデフォルトでオンになっています。
ただし、奇妙な動作が見られます。
- メッセージが追加される前に、チェックボックスをオフにしてリストにメッセージを追加すると、リストはスクロールしません (正しい動作)。
- チェックボックスをオンのままにしてメッセージを追加すると、リストがスクロールします (正しい動作)。
- リストにいくつかのメッセージを追加してから、ボックスのチェックを外してからリストに追加すると、リストはスクロールします (不正な動作)。
以下に示す問題を示す非常に単純な WPF アプリケーションに要約しました。
何が原因で、どうすれば修正できますか?
XAML:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="229" Width="551">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<CheckBox Grid.Row="0" Content="Autoscroll?" Name="AutoscrollCheckBox" IsChecked="True" />
<Button Grid.Row="1" Content="Add a message" Name="AddMessageButton" Click="AddMessageButton_Click" />
<ScrollViewer Name="MessagesScrollViewer" Grid.Row="2">
<ItemsControl Name="MessagesList" ItemsSource="{Binding Messages}" />
</ScrollViewer>
</Grid>
</Window>
そして背後にあるコード:
public partial class MainWindow : Window, INotifyPropertyChanged {
public MainWindow() {
InitializeComponent();
DataContext = this;
((INotifyCollectionChanged)MessagesList.Items).CollectionChanged += Messages_CollectionChanged;
}
private void Messages_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
Console.WriteLine((bool)AutoscrollCheckBox.IsChecked);
if (AutoscrollCheckBox.IsChecked.HasValue && (bool)AutoscrollCheckBox.IsChecked && (e.Action == NotifyCollectionChangedAction.Add))
MessagesScrollViewer.ScrollToBottom();
}
private ObservableCollection<string> m_Messages = new ObservableCollection<string>();
public ObservableCollection<string> Messages {
get { return m_Messages; }
set { m_Messages = value; NotifyPropertyChanged("Messages"); }
}
private int _msgNumber = 0;
private void AddMessageButton_Click(object sender, RoutedEventArgs e) {
Messages.Add(String.Format("Message #{0}", _msgNumber++));
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string name) {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}