2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CommunityToolkit.Mvvmを使用したWPFのDataGridへの表示

Last updated at Posted at 2024-09-09

WPFでDataGridにbindingして、表示・変更する方法についてです。
どのフレームワークを使うかや書き方が色々あるようで、調べた結果の自分メモです。
今回はCommunityToolkit.Mvvm(ver8)を使いました。

[追記]
設定について追記しました。
メモリCPU使用率が高い

準備

  • vscode
  • .net8
  • dotnet new wpf -n TestWpf
  • dotnet add package CommunityToolkit.Mvvm

つくった内容

フォルダ構成

MVVMとしたいので少しかえます。
これがいいのかよく分かってはないです。。。

C:.
│  App.xaml
│  App.xaml.cs
│  AssemblyInfo.cs
│  MainWindow.xaml
│  MainWindow.xaml.cs
│  TestWpf.csproj
├─.vscode
├─bin
├─Moedls
│      User.cs
└─ViewModels
        UserViewModel.cs

MainWindow

MainWindow.xaml.cs

こちらはなにも変更しないです。

using System.Windows;

namespace TestWpf;

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

MainWindow.xaml

  • 名前空間にvmを追加する
  • そのvmをdatacontextに指定する
  • 表示したい内容を追加してBinding する
<Window x:Class="TestWpf.MainWindow"
        xmlns:vm="clr-namespace:TestWpf.ViewModels"
        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:TestWpf"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.DataContext>
        <vm:UserViewModel/>
    </Window.DataContext>

    <StackPanel>
        <Button Content="9999項目の追加" Command="{Binding AddClickCommand}" CommandParameter="test" />
        <Button Content="9999項目の削除" Command="{Binding RemoveClickCommand}" />
        <TextBlock Text="{Binding Name}" />
        <DataGrid ItemsSource="{Binding Users, Mode=OneWay}" IsReadOnly="True" />
    </StackPanel>
</Window>

ViwModel

UserViewModel.cs

  • [INotifyPropertyChanged][ObservableProperty][RelayCommand]を付けることで、ソースジェネレートしてくれる
  • Toolkit.mvvmのver8ではさらに必要な記述が減っているようですが、どういうことなのか分かっていないとなんでこんな書き方しているのて思ってしまうので注意
using System.Collections.ObjectModel;
using System.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using TestWpf.Models;

namespace TestWpf.ViewModels;

[INotifyPropertyChanged]
internal partial class UserViewModel
{
    [ObservableProperty]
    private string _Name;
    [ObservableProperty]
    public ObservableCollection<User> _Users;

    public UserViewModel()
    {
        _Name = "テキスト";

        _Users =
            [new User() { Id = 1111, UserName = "aiue", Result = false },
            new User() { Id = 2222, UserName = "kakikuke", Result = true },];
    }

    [RelayCommand]
    private void AddClick(string Parameter)
    {
        if (Name == "テキスト")
        {
            Name = "クリックしました!";
        }
        else
        {
            Name = "テキスト";
            Users.Add(new User()
            {
                Id = 9999,
                UserName = "addaddadd",
                Result = true
            });
            Users[0].UserName = "チェンジname";
        }
        Debug.WriteLine($"クリックしました {Parameter}");
    }
    [RelayCommand]
    private void RemoveClick()
    {
        Users.Remove(
            Users.FirstOrDefault(x => x.Id == 9999)
        );
    }
}

Model

User.cs

  • DataGridに反映する内容
  • 内容変更を通知できるように[INotifyPropertyChanged]をつける
using CommunityToolkit.Mvvm.ComponentModel;

namespace TestWpf.Models;

[INotifyPropertyChanged]
public partial class User
{
    [ObservableProperty]
    public int _Id;
    [ObservableProperty]
    public string _UserName;
    [ObservableProperty]
    public bool _Result;
}

完成

testwpf.gif

エラーとか

ファイルが見つからないエラー

デバッグ実行した時に、ソースファイルが見つかりません。となる時がある。
実際には存在している。
もう一度やり直したり、dotnet restoreとかするととりあえずは実行できるようになる。

CSC : error CS2001: ソース ファイル 'C:\.....\TestWpf\obj\Debug\net8.0-windows\MainWindow.g.cs' が見つかりませんでし
た。 [C:\....\TestWpf\TestWpf.csproj]
CSC : error CS2001: ソース ファイル 'C:\....\TestWpf\obj\Debug\net8.0-windows\App.g.cs' が見つかりませんでした。 [C:\....\TestWpf\TestWpf.csproj]
CSC : error CS2001: ソース ファイル 'C:\....\TestWpf\obj\Debug\net8.0-windows\GeneratedInternalTypeHelper.g.cs' が見
つかりませんでした。 [C:\....\TestWpf\TestWpf.csproj]

Microsoft.CodeAnalysis.LanguageServerが動き続けているせい?
Microsoft LearnにはRoslyn analyzerの診断があるとなっているので関係ありそう。
以下設定を追加してみることにしました。

setting.json
{
  "dotnet.backgroundAnalysis.analyzerDiagnosticsScope": "none"
}

参考にした似たような事

C# and Visual Basic compiler diagnostics
Roslyn analyzer diagnostics, which includes:
Built-in IDE analyzers for code-style suggestions
Built-in CA analyzers for code-quality suggestions
External analyzer packages that are installed for projects in the current solution

tmpファイルが増え続ける

デバッグ実行する度に、\obj\Debug\net8.0-windows\のフォルダ内にソースジェネレーターでつくられたと思われるtmpファイルが増え続けているようです。
増えないような設定が分からなかったので、デバッグビルド時に削除する処理を入れました。
TestWpf.csprojに追記します。
以下で、obj\フォルダ内のtmpファイルが削除されます。
削除したファイルを表示しますが、vscode標準の設定では、Message Importance="High"を入れないとコンソールに表示されないようでした。

TestWpf.csproj
<Target Name="DeletetmpFiles" AfterTargets="build">
    <ItemGroup>
      <FilesToDelete Include="$(BaseIntermediateOutputPath)*tmp*" />
      <FilesToDelete Include="$(BaseIntermediateOutputPath)Debug\net8.0-windows\*tmp*" />
    </ItemGroup>
    <Delete Files="@(FilesToDelete)">
      <Output 
        TaskParameter="DeletedFiles"
        ItemName="FilesDeleted"/>
    </Delete>
    <Message Importance="High" Text="Files deleted: @(FilesDeleted)"/>
    <!-- フォルダを削除する場合 -->
    <!-- <RemoveDir Directories="$(BaseIntermediateOutputPath)" /> -->
</Target>

以下を参考にしました。
Removing bin and obj folder in .NET
タスクを削除する

ワイルドカードで指定するのに間違った場合、ルートフォルダが対象となるので、ItemGroupにてリストを作成してから、DeleteのFilesへ指定するのがいいようです。

警告
Delete タスクでワイルドカードを使用する場合は注意してください。 $(SomeProperty)**. や $(SomeProperty)/**/. などの式を使用すると、間違ったファイルを簡単に削除できます。プロパティが空の文字列に評価される場合は特に、Files パラメーターがドライブのルートに評価され、削除したいものよりもはるかに多く削除される場合があります。

Delete タスクでワイルドカードを直接使用する代わりに、削除するファイルの ItemGroup を作成し、それに対して Delete タスクを実行します。 ただし、ItemGroup は慎重に配置してください。 ItemGroup をプロジェクト ファイルの最上位レベルに配置すると、ビルドの開始前の早い段階で評価されるため、ビルド プロセスの一部としてビルドされたファイルは含まれません。 そのため、削除する項目のリストを作成する ItemGroup を、Delete タスクの近くのターゲットに配置します。 ドライブのルートから始まるパスを持つ項目リストを作成しないように、プロパティが空でないことを確認する条件を指定します。

メモリCPU使用率が高い

コード編集をしていると、CPU/メモリの使用率がかなり高くなる。
ファンの音もすごくなりノートPCが熱くなる。
いくつかのissueに似たよなことがありましたが、ソースジェネレーターを参照するとこうなってしまうようです。

以下を.csprojファイルのプロパティに追記しました。
が、あまり変わらない。。。
ソースジェネレーターが動き続けているっぽい。
デバッグの時にファイルが見つからないというのも、ソースジェネレーターがファイルを開いているからのようです。

test.csproj
<RunAnalyzersDuringLiveAnalysis>false</RunAnalyzersDuringLiveAnalysis>

.NET のソース コード分析を無効にする

参考

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?