1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Windows Forms - NavigationView のようなサイドバー形式

Last updated at Posted at 2025-05-18

はじめに

UWP - NavigationView は、左端 もしくは 上端にナビゲーションメニューを配置し、選択された項目に応じてメインコンテンツを切り替えることができます。

WPF では、Nuget - ModernWpfUI を導入することで、NavigationView を利用できます。

本記事では、Windows Forms で、NavigationView のようなサイドバー形式とする手法について記載します。

テスト環境

ここに記載した情報/ソースコードは、Visual Studio Community 2022 を利用した下記プロジェクトで生成したモジュールを Windows 11 24H2 で動作確認しています。

  • Windows Forms - .NET Framework 4.8
  • Windows Forms - .NET 8

記載したソースコードは .NET 8 ベースとしています。
.NET Framework 4.8 の場合は、コメントで記載している null 許容参照型の明示 ? を削除してください。

Visual Studio 2022 - .NET Framework 4.8 は、C# 7.3 が既定です。
このため、サンプルコードは、C# 7.3 機能範囲で記述しています。

素材

アイコンとして下記を利用させて頂きました。

デザイン

Windows Forms で NavigationView のようなレイアウト実現は、いくつかの手法が存在します。
本記事では、RadioButton と TabControl を用いて、NavigationView のような左端サイドバー形式レイアウトを実現しようと思います。

sample-00.png

本記事では、TabControl+Panel という実装としていますが、Qiita コメントで、個々の Panel を UserControl にする手法を提示されました。
確かに UserControl 化が正攻法で、TabControl+Panel は力業なので、実際に利用する場合は、正攻法をご検討ください。

TabControl+Panel を選択したのは、手軽な(標準コントールのみで)実装というアプローチでした。

手順

ベースとなるパネル配置

コンパクトなサンプルとしたいので、フォームサイズを 500, 300 とします。
サイドバー用 Panel - pnlNavigation を追加、Dock = Left として、幅を 150 とします。
次に、コンテンツ用 Panel - pnlContents を追加、Dock = Fill とします。

Design-01.png

コンテンツ配置

デザイナ画面で、各コンテンツを編集することを目的に TabControl - tabControl1 を、pnlNavigation に Dock = Fill で配置します。
今回のサンプルにあわせて、タブをひとつ追加した後、それぞのタブに対して Panel を Dock = Fill で追加します。

Design-02.png

対象タブ 配置する Panel
tabPage1 pnlUpload
tabPage2 pnlDownload
tabPage3 pnlSettings

デザイナ画面でタブを切り替えて、それぞれの Panel にコンテンツを構築(コントールを配置)します。
後述ソースコードで、上記 Panel を pnlContents の子コントールに再配置(Dock = Fill)して、tabControl1 は Visuble = False として無効化します。
ナビゲーションボタン選択で、ひとつの Panel のみ表示することで、コンテンツ切り替えを実現します。
このように、tabControl1 はデザイナ画面での編集だけのために利用します。

それぞれの Panel に対して、パネル切り替えを識別するために Label を追加します。

Design-03.png

対象タブ 対象 Panel 配置する Label の Text
tabPage1 pnlUpload UPLOAD コンテンツ
tabPage2 pnlDownload DOWNLOAD コンテンツ
tabPage3 pnlSettings SETTINGS コンテンツ

ナビゲーション配置

RadioButton は単一選択のコントールです。
この単一選択という特性を利用して、ナビゲーションボタンとして下記プロパティで配置します。

  • Appearance = Appearance.Button
  • AutoSize = false
  • FlatStyle = FlatStyle.Flat
  • FlatAppearance.BorderSize = 0
  • Image = <UPLOADアイコン>
  • ImageAlign = ContentAlignment.MiddleLeft
  • Text = UPLOAD
  • TextImageRelation = TextImageRelation.ImageBeforeText
  • Locaion = 0, 0
  • Height = 32
  • Width = 150(pnlNavigation.Width)

Design-04.png

コンテンツに対応する RadioButton を配置します。

RadioButton Image Text Location
rbUpload upload-24.png UPLOAD 0, 0
rbDownload download-24.png DOWNLOAD 0, 32
rbSettings Setting-24.png SETTINGS 0, 64

Design-05.png

ソースコード

Form1.cs
public partial class Form1 : Form
{
  private List<Panel> lstPanels = new List<Panel>();
  private List<RadioButton> lstNavigate = new List<RadioButton>();

  public Form1()
  {
    InitializeComponent();

    // Panel と RadioButton の関連づけ
    // Navigate2Panel(string keyword)用
    pnlUpload.Tag = rbUpload.Text;
    pnlDownload.Tag = rbDownload.Text;
    pnlSettings.Tag = rbSettings.Text;

    // Panel
    lstPanels.Add(pnlUpload); 
    lstPanels.Add(pnlDownload);
    lstPanels.Add(pnlSettings);
    foreach(var panel  in lstPanels)
    {
      panel.Parent = pnlContents; // pnlContents の子コントールに設定
      // panel.Dock = DockStyle.Fill;   // サンプルではデザイナで設定
    }
    tabControl1.Visible = false;  // TabControl は不要

    // RadioButton
    lstNavigate.Add(rbUpload);
    lstNavigate.Add(rbDownload);
    lstNavigate.Add(rbSettings);
    int height = 32;
    int py = 0;
    foreach(var button in lstNavigate)
    {
      button.CheckedChanged += rbNavigate_CheckChanged;
      button.Location = new Point( 0, py );   // レイアウト再調整
      button.Width = pnlNavigation.Width;     // レイアウト再調整
      button.Height = height;                 // レイアウト再調整
      py += height;
    }

    // 初期選択
    lstNavigate[0].Checked = true;
  }
  // .NET Framework 時 object? の ? 不要
  private void rbNavigate_CheckChanged(object? sender, EventArgs e)
  {
    if (sender is RadioButton button)
    {
      Navigate2Panel(button.Text);
    }
  }
  // Navigate に連動して、対象 Panel を表示
  private void Navigate2Panel(string keyword)
  {
    bool bMatch = false;
    foreach (var panel in lstPanels)
    {
      // keyword に一致するか?
      if (panel.Tag is string tag
       && string.Compare(keyword, tag) == 0)
      {
        panel.Visible = true;
        bMatch = true;
      }
      else
      {
        panel.Visible = false;
      }
    }
    // 一致するモノがない場合は先頭を選択(あり得ない...)
    if (!bMatch)
    {
      lstPanels[0].Visible = true;
    }
  }
}
1
2
4

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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?