Ctrl キーを同時に押した場合にのみ、データグリッドをマウス ホイールでスクロールさせたいのですが、それ以外の場合はページをスクロールしたいと考えています。 私は、アプリケーションで使用するパターンである wpf と mvvm を初めて使用します。
これは、データグリッドを含むページです。
<Page x:Class="Projectname.ChapterPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-
compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Projectname"
xmlns:core="clr-namespace:Projectname.Core;assembly=Projectname.Core"
mc:Ignorable="d"
d:DesignHeight="700" d:DesignWidth="900"
Title="ChapterPage">
<StackPanel>
<TextBlock Grid.Column="0"
Grid.ColumnSpan="2"
Text="Kapitel"
Style="{StaticResource HeaderText}"
Foreground="{StaticResource
ForegroundVeryLightBrush}"
FontSize="{StaticResource FontSizeLarge}"
FontWeight="Bold"
Margin="50 -45 50 15"/>
<Border Background="{StaticResource BlueBrush}"
CornerRadius="10"
Margin="10"
MinHeight="45"
Padding="2">
<StackPanel HorizontalAlignment="Center"
Orientation="Horizontal">
<Button Command="{Binding SaveCommand}"
Style="{StaticResource IconGrowButton}"
ToolTip="Speichern"
Margin="10 0"
MaxHeight="30"
MinWidth="30"
Cursor="Hand">
<Image Source="../Images/Icons/Save.png" />
</Button>
<Button Command="{Binding DeleteCommand}"
Style="{StaticResource IconGrowButton}"
ToolTip="Löschen"
MaxHeight="30"
MinWidth="30"
Margin="10 0 80 0"
Cursor="Hand">
<Image Source="../Images/Icons/Delete.png" />
</Button>
<Button Command="{Binding ResetCommand}"
Style="{StaticResource IconGrowButton}"
ToolTip="Zurücksetzen"
MaxHeight="30"
MinWidth="30"
Margin="10 0"
Cursor="Hand">
<Image Source="../Images/Icons/Reset.png" />
</Button>
</StackPanel>
</Border>
<DataGrid Margin="15 10"
HorizontalAlignment="Stretch"
ItemsSource="{Binding Chapters,
UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding ChaptersVisibility,
Converter={local:BooleanToVisibilityConverter}}"
SelectedItem="{Binding SelectedChapter}"/>
</StackPanel>
</Page>
私のページはウィンドウにロードされ、コンテンツをスクロールするためのスクロールビューアがウィンドウ内にあります。
それが窓です:
<Grid>
<StackPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Background="{StaticResource RedBrush}">
<Button Command="{Binding NavMenuCommand}"
Style="{StaticResource SystemIconButton}"
Cursor="Hand"
HorizontalAlignment="Left">
<Button.Content>
<Image Source="../Images/Icons/burger-
menue.png"
Height="25"/>
</Button.Content>
</Button>
</Border>
</Grid>
<local:ChapterPage
Padding="8 0"/>
</StackPanel>
<local:NavMenu Margin="0,41,628,0"/>
</Grid>
</ScrollViewer>
これを実現する方法はまったくわかりませんが、できることなら xaml.cs を使いたくありません。
異なるスクロール動作が必要な理由は、データ グリッドとヘッダー領域の間に大きなユーザー コントロールがあるためです。これはページの分割図です。
質問を編集しました。もう私の言うことが分かりましたか?
– BuBBles29042020 年 9 月 3 日 9:25
ありがとうございます。次に、2 つの ScrollViewer が必要になります。1 つはコンテンツとしてページを持ち、もう 1 つはコンテンツとして DataGrid を持ちます。デフォルトでは、直接マウスオーバー入力を受信した ScrollViewer が優先されます。マウスオーバーの制約なしでスクロールできるようにすることが目的の場合は、マウス入力を処理する必要があります。d 両方のコントロールの共通の親でビューアをスクロールします。これを含む UserControl。完全なコンテキスト (スクロール ビューアとその親の両方) を示していただけますか?
– バイオニックコード2020 年 9 月 3 日 9:29
ページのコードとウィンドウのコードを追加しました。
– BuBBles29042020 年 9 月 3 日 9:42
DataGrid をスクロールしてもよろしいですか?表示されていない場合、つまり以前にスクロールされて表示されなくなった場合。ユーザーの観点から見ると、望ましい動作は何の価値も追加しない可能性があります。なぜ彼はデフォルトのスクロール動作を次のように変更したいのでしょうか。スクロール バーを直接ドラッグしますか、それとも通常どおりマウス ホイールを使用しますか?あなたのアプリケーションを使用していて、DataGrid をスクロールしたいのに、代わりにページ全体をスクロールする場合、これは非常に煩わしく、邪魔になると思います。ユーザー エクスペリエンスに大幅な価値を追加しない限り、既知の受け入れられている/予期されるデフォルトの動作をそのままにしておく必要があります。
– バイオニックコード2020 年 9 月 3 日 9:42
実際には、境界線とデータグリッドの間に、いくつかのテキスト ボックスを持つユーザー コントロールを含む別のグリッドがあります。このグリッドには多くのスペースが必要です。
– BuBBles29042020 年 9 月 3 日 9:46
参加している ScrollViewer の両方またはすべての共通の親によって PreviewMouseWheel イベントを処理する必要があります。
MainWindow.xaml 簡略化されたビュー:
<Window PreviewMouseWheel="HandleScroll_OnPreviewMouseWheel">
<ScrollViewer x:Name="RootScrollViewer">
<DataGrid x:Name="DataGridToScrollOnKeyPress" />
</ScrollViewer>
</Window>
MainWindow.xaml.cs
private ScrollViewer DataGridScrollViewer { get; set; }
private void OnLoaded(object sender, RoutedEventArgs e)
{
// Find DataGrid by name (in case of multiple DataGrids)
if (TryFindVisualChildElement(this.Root, "DataGridToScrollOnKeyPress", out DataGrid dataGrid))
{
// And get its ScrollViewer (by type)
if (TryFindVisualChildElement(dataGrid, string.Empty, out ScrollViewer scrollViewer))
{
this.DataGridScrollViewer = scrollViewer;
}
}
}
private void HandleScroll_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
// Give the main scroll viewer chance to handle its own scroll,
// if it is the scroll source (preserve default behavior)
if (e.Source == this.Root
&& !Keyboard.IsKeyDown(Key.LeftCtrl)
&& !Keyboard.IsKeyDown(Key.RightCtrl))
{
return;
}
e.Handled = true;
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{
if (e.Delta < 0)
{
this.DataGridScrollViewer?.LineDown();
}
else
{
this.DataGridScrollViewer?.LineUp();
}
}
else // Some other control is scroll source => scroll main scroll viewer
{
if (e.Delta < 0)
{
this.RootScrollViewer.LineDown();
}
else
{
this.RootScrollViewer.LineUp();
}
}
}
// If the 'childElementName' parameter is NULL, an empty string or whitespace it will be ignored (only the type will be relevant)
public bool TryFindVisualChildElement<TChild>(DependencyObject parent, string childElementName, out TChild childElement)
where TChild : FrameworkElement
{
childElement = null;
if (parent == null)
{
return false;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is TChild resultElement
&& (string.IsNullOrWhiteSpace(childElementName) || resultElement.Name.Equals(childElementName, StringComparison.Ordinal)))
{
childElement = resultElement;
return true;
}
if (TryFindVisualChildElement(child, childElementName, out childElement))
{
return true;
}
}
return false;
}
5
コンテンツのスクロール ビューアとデータグリッドは同じ xaml 内にありません。どうすれば入手できますか?
– BuBBles29042020 年 9 月 3 日 11:30
TryFindVisualChildElement メソッドを使用します。上記のコードを参照して、親 (この例では DataGridToScrollOnKeyPress) をメイン スクロール ビューアのインスタンスに置き換えます。これにより、DataGrid が見つかり、ScrollViewer にドリルダウンされるはずです。
– バイオニックコード2020 年 9 月 3 日 11:49
例 (OnLoaded() と TryFindVisualChildElement()) を更新しました。 DataGrid の名前を調整するだけです。
– バイオニックコード2020 年 9 月 3 日 15:12
取得しようとするとデータグリッドからのスクロールビューアは null を返します。いくつかのデバッグの後、VisualTreeHelper.GetChild(dataGrid, i) が 0 を返すことがわかりました。
– BuBBles29042020 年 9 月 4 日 5:53
ビジュアル ツリーにアクセスする前に、DatGrid がロードされていることが重要です。 DataGridScrollViewer プロパティを静的にすることができます。次に、Loaded イベント ハンドラーを DataGrid にアタッチし、上記の TryFindVisualChildElement を使用して ScrollViewer を取得し、それを静的 DataGridScrollViewer に割り当てます。DataGridScrollViewer にアクセスする前に、HandleScroll_OnPreviewMouseWheel に NULL チェックを追加することをお勧めします: 例: DataGridScrollViewer?...LineDown();
– バイオニックコード2020 年 9 月 4 日 10:14