質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

3891閲覧

【C#】【MVVM】DataGridの先頭行、最終行への移動をViewModelで実現したい

Morganite

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2021/12/23 02:24

前提・実現したいこと

C#でのMVVM初心者です。
MVVMフレームワークとして、Prismを利用しています。
Clickイベントの動作をViewModelで実現したいです。
ScrollIntoViewの実装方法が知りたいです。
よろしくお願いします。

発生している問題・エラーメッセージ

該当のソースコード

xaml

1<Window x:Class="WPFDataGrid.Views.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:prism="http://prismlibrary.com/" 5 prism:ViewModelLocator.AutoWireViewModel="True" 6 Title="{Binding Title}" Height="600" Width="800" > 7 <Grid> 8 <ContentControl prism:RegionManager.RegionName="ContentRegion" /> 9 <StackPanel 10 Orientation="Vertical"> 11 <DataGrid 12 Name="DataGrid1" 13 Height="450" 14 AutoGenerateColumns="True" 15 HorizontalScrollBarVisibility="Auto" 16 VerticalScrollBarVisibility="Auto" 17 IsReadOnly="True" 18 ItemsSource="{Binding Path=DataSource1.Value}"/> 19 <Button 20 Name="BtnTopLine" 21 Height="50" 22 Click="BtnTopLine_Click"> 23 先頭行へ 24 </Button> 25 <Button 26 Name="BtnLastLine" 27 Height="50" 28 Click="BtnLastLine_Click"> 29 最終行へ 30 </Button> 31 </StackPanel> 32 </Grid> 33</Window>

xamlcs

1using System.Data; 2using System.Windows; 3 4namespace WPFDataGrid.Views 5{ 6 /// <summary> 7 /// Interaction logic for MainWindow.xaml 8 /// </summary> 9 public partial class MainWindow : Window 10 { 11 public MainWindow() 12 { 13 InitializeComponent(); 14 } 15 16 private void BtnTopLine_Click(object sender, RoutedEventArgs e) 17 { 18 this.DataGrid1.Focus(); 19 // 先頭行へ移動 20 this.DataGrid1.ScrollIntoView(this.DataGrid1.Items[0]); 21 } 22 23 private void BtnLastLine_Click(object sender, RoutedEventArgs e) 24 { 25 this.DataGrid1.Focus(); 26 DataTable _dt = ((DataView)this.DataGrid1.ItemsSource).ToTable(); 27 // 最終行へ移動 28 this.DataGrid1.ScrollIntoView(this.DataGrid1.Items[_dt.Rows.Count - 1]); 29 } 30 } 31}

ViewModel

1using Prism.Mvvm; 2using Reactive.Bindings; 3using System.Data; 4 5namespace WPFDataGrid.ViewModels 6{ 7 public class MainWindowViewModel : BindableBase 8 { 9 private string _title = "Prism Application"; 10 public string Title 11 { 12 get { return _title; } 13 set { SetProperty(ref _title, value); } 14 } 15 16 public ReactiveProperty<DataTable> DataSource1 { set; get; } = 17 new ReactiveProperty<DataTable>(); 18 19 public MainWindowViewModel() 20 { 21 // データテーブル 22 int _columnCount = 100; 23 int _rowCount = 100; 24 DataTable _dt = new DataTable(); 25 // 列の生成 26 for (int _i = 0; _i < _columnCount; _i++) 27 { 28 _dt.Columns.Add("Column" + _i.ToString()); 29 } 30 // 行の追加 31 for (int _i = 0; _i < _rowCount; _i++) 32 { 33 DataRow _row = _dt.NewRow(); 34 for (int _k = 0; _k < _columnCount; _k++) 35 { 36 _row[_k] = $"{_i}-{_k}"; 37 } 38 _dt.Rows.Add(_row); 39 } 40 // データテーブルのバインド 41 DataSource1.Value = _dt; 42 } 43 } 44} 45

試したこと

補足情報(FW/ツールのバージョンなど)

Visual Studio Community 2019 ver.16.11.8
Prism.Unity ver.8.1.97
ReactiveProperty ver.8.0.3

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Clickイベントの動作をViewModelで実現したいです。

「ボタンを押したらViewModelの何かの処理をする」ような場合は、コマンド(ICommand)を使います。

Commanding | Prism

MVVM をリアクティブプログラミングで快適に ReactiveProperty オーバービュー 2020 年版 中編 - Qiita

ReactiveCommand(ReactivePropertyのICommand実装)でもほぼ同じですが、現状Reactive要素がまったくないのでDelegateCommand(PrismのICommand実装)でやりました。

しかしこれではViewModelがDataGridに依存しますしテストもしにくく、あまりメリットがない気がします。
こうするぐらいならまだコードビハインドのほうがましだったと(個人的には)感じます。

ScrollIntoViewの実装方法が知りたいです。

実装できていると思うんですが、↑の話を踏まえてMVVMでのよりよい実装って意味ですか?

MVVM絶対主義者(コードビハインドを書いたら負け勢)は、BehaviorとかTriggerActionとかでやるんですかね?(わたしは絶対主義者ではありません)
試しにやってみましたが、xamlが長くなっただけな気もします^^;

xml

1<Window 2 x:Class="Questions375184.Views.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 6 xmlns:prism="http://prismlibrary.com/" 7 xmlns:v="clr-namespace:Questions375184.Views" 8 Title="{Binding Title}" 9 Width="800" 10 Height="600" 11 prism:ViewModelLocator.AutoWireViewModel="True"> 12 <DockPanel> 13 <!--<ContentControl prism:RegionManager.RegionName="ContentRegion" />--> 14 <StackPanel DockPanel.Dock="Bottom" Orientation="Vertical"> 15 <Button Click="BtnTopLine_Click" Content="BtnTopLine_Click" /> 16 <Button Click="BtnLastLine_Click" Content="BtnLastLine_Click" /> 17 18 <Separator /> 19 20 <Button 21 Command="{Binding ScrollTopCommand}" 22 CommandParameter="{Binding ElementName=DataGrid1}" 23 Content="ScrollTopCommand" /> 24 <Button 25 Command="{Binding ScrollEndCommand}" 26 CommandParameter="{Binding ElementName=DataGrid1}" 27 Content="ScrollEndCommand" /> 28 29 <Separator /> 30 31 <Button Content="ScrollTopAction"> 32 <i:Interaction.Triggers> 33 <i:EventTrigger EventName="Click"> 34 <v:ScrollTopAction TargetObject="{Binding ElementName=DataGrid1}" /> 35 </i:EventTrigger> 36 </i:Interaction.Triggers> 37 </Button> 38 <Button Content="ScrollEndAction"> 39 <i:Interaction.Triggers> 40 <i:EventTrigger EventName="Click"> 41 <v:ScrollEndAction TargetObject="{Binding ElementName=DataGrid1}" /> 42 </i:EventTrigger> 43 </i:Interaction.Triggers> 44 </Button> 45 </StackPanel> 46 47 <DataGrid 48 Name="DataGrid1" 49 IsReadOnly="True" 50 ItemsSource="{Binding DataSource1}" /> 51 </DockPanel> 52</Window>

cs

1using System.Windows; 2using Microsoft.Xaml.Behaviors; 3using System.Windows.Controls; 4 5namespace Questions375184.Views 6{ 7 public partial class MainWindow : Window 8 { 9 public MainWindow() => InitializeComponent(); 10 11 private void BtnTopLine_Click(object sender, RoutedEventArgs e) 12 { 13 DataGrid1.Focus(); 14 DataGrid1.ScrollIntoView(DataGrid1.Items[0]); 15 } 16 17 private void BtnLastLine_Click(object sender, RoutedEventArgs e) 18 { 19 DataGrid1.Focus(); 20 DataGrid1.ScrollIntoView(DataGrid1.Items[^1]); 21 } 22 } 23 24 public class ScrollTopAction : TargetedTriggerAction<DataGrid> 25 { 26 protected override void Invoke(object parameter) 27 { 28 Target.Focus(); 29 Target.ScrollIntoView(Target.Items[0]); 30 } 31 } 32 33 public class ScrollEndAction : TargetedTriggerAction<DataGrid> 34 { 35 protected override void Invoke(object parameter) 36 { 37 Target.Focus(); 38 Target.ScrollIntoView(Target.Items[^1]); 39 } 40 } 41}

cs

1using System.Data; 2using System.Windows.Controls; 3using Prism.Commands; 4using Prism.Mvvm; 5 6namespace Questions375184.ViewModels 7{ 8 public class MainWindowViewModel : BindableBase 9 { 10 public string Title { get => _title; set => SetProperty(ref _title, value); } 11 private string _title = "Prism Application"; 12 13 public DataTable DataSource1 { get => _dataSource1; set => SetProperty(ref _dataSource1, value); } 14 private DataTable _dataSource1; 15 16 public DelegateCommand<DataGrid> ScrollTopCommand { get; } 17 public DelegateCommand<DataGrid> ScrollEndCommand { get; } 18 19 20 public MainWindowViewModel() 21 { 22 var columnCount = 20; 23 var rowCount = 20; 24 var dt = new DataTable(); 25 26 for (var i = 0; i < columnCount; i++) 27 { 28 dt.Columns.Add($"Column{i}"); 29 } 30 31 for (var i = 0; i < rowCount; i++) 32 { 33 var row = dt.NewRow(); 34 for (var k = 0; k < columnCount; k++) 35 { 36 row[k] = $"{i}-{k}"; 37 } 38 dt.Rows.Add(row); 39 } 40 41 DataSource1 = dt; 42 43 44 ScrollTopCommand = new DelegateCommand<DataGrid>(ScrollToTop); 45 ScrollEndCommand = new DelegateCommand<DataGrid>(ScrollToEnd); 46 } 47 48 private void ScrollToTop(DataGrid dataGrid) 49 { 50 dataGrid.Focus(); 51 dataGrid.ScrollIntoView(dataGrid.Items[0]); 52 } 53 54 private void ScrollToEnd(DataGrid dataGrid) 55 { 56 dataGrid.Focus(); 57 dataGrid.ScrollIntoView(dataGrid.Items[^1]); 58 } 59 } 60}

投稿2021/12/23 08:22

編集2023/08/15 09:34
TN8001

総合スコア9862

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Morganite

2021/12/24 06:51

非常に勉強になりました。ありがとうございます。まだMVVMを始めたばかりで、よくわからないことが多いです。コードビハインドとViewModelの使いどころがわかってないのだと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問