前回は、WPFのソースコードの構成について「画面に関するコードは’XAML’、処理に関するコードは’C#’で書く」と書きました。
ということは、画面に関するコードは’XAML’、処理に関するコードを’VB.NET’で書いたプロジェクトの「画面に関するコードだけを置き換える」ということは可能なのでしょうか?
実際に作ってみる
C#で画面(MainWindow)1つ、その画面にボタン(button)が1つのプロジェクトを作ります。
そして、このボタンを「Close」(閉じる)ボタンにします。
コードは下記のようになります。
C#のプロジェクト
画面側(MainWindow.xaml)
<Window x:Class="WpfApplication2.MainWindow" 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:WpfApplication2" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Window.CommandBindings> <CommandBinding Command="Close" Executed="CommandBinding_Executed" CanExecute="CommandBinding_CanExecute"> </CommandBinding> </Window.CommandBindings> <Grid> <Button x:Name="button" Content="Close" HorizontalAlignment="Left" Margin="191,224,0,0" VerticalAlignment="Top" Width="75" Command="Close"/> </Grid> </Window>
処理側(MainWindow.xaml.cs)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApplication2 { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) { Close(); // ウィンドウを閉じる } private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; // 無条件で実行可能 } } }
VB.NETでまったく同じ構成(画面1つ、ボタン1つ)のプロジェクトを作成します。
(ここで作成するプロジェクト名はC#版とできるだけ似た名称にしておきます)
VB.NETのプロジェクト
画面側(MainWindow.xaml)
<Window x:Class="MainWindow" 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:WpfApplication2" mc:Ignorable="d" Title="MainWindow" Height="300" Width="300"> <Window.CommandBindings> <CommandBinding Command="Close" Executed="CommandBinding_Executed" CanExecute="CommandBinding_CanExecute"> </CommandBinding> </Window.CommandBindings> <Grid> <Button x:Name="button" Content="Close" HorizontalAlignment="Left" Margin="191,224,0,0" VerticalAlignment="Top" Width="75" Command="Close"/> </Grid> </Window>
処理側(MainWindow.xaml.vb)
Public Class MainWindow Private Sub CommandBinding_Executed(sender As Object, e As ExecutedRoutedEventArgs) Close() End Sub Private Sub CommandBinding_CanExecute(sender As Object, e As CanExecuteRoutedEventArgs) e.CanExecute = True End Sub End Class
処理側は言語が違いますが、呼び出されるメソッドの名称は同じです。
これは、XAMLで定義している
Executed="CommandBinding_Executed" CanExecute="CommandBinding_CanExecute"
というメソッドの名称なので、合わせています。
画面側(MainWindow.xaml)はまったく同じ?
では、「画面側で共通となる”MainWindow.xaml”は全く同じ」なのか、という話になります。
結果は、「全く同じではない」となります。
全く同じであれば、どちらかのMainWindow.xamlを相手のプロジェクトに上書きしても、プログラムを動作させることができるはずです。
実際にC#からVB.NETにMainWindow.xamlを持って行って実行しようとしたところ下記のようなエラーがでました。
重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー BC30456 ‘CommandBinding_Executed’ は ‘MainWindow’ のメンバーではありません。
エラー BC30456 ‘CommandBinding_CanExecute’ は ‘MainWindow’ のメンバーではありません。
エラー BC30451 ‘Close’ は宣言されていません。アクセスできない保護レベルになっています。
原因は、はっきりしていて、MainWindowというクラスのメンバがうまくXAMLのコードと関連付けられていないのでエラーとなっているのです。
ウィンドウそのものの位置やサイズ、ボタンの位置やサイズはデザイナの操作による違いは置いておくと、違うのは先頭の1行だけになります。
C#版の”MainWindow.xaml”
(XMLタグが閉じていませんが、ここは違いを見ていただくために先頭の1行だけにしています)
<Window x:Class="WpfApplication2.MainWindow"
VB.NET版の”MainWindow.xaml”
<Window x:Class="MainWindow"
C#のほうだけ、クラス名の前に名前空間が入っています。
VB.NETへ持っていた”MainWindow.xaml”の先頭行のクラス名から名前空間を消してクラス名だけにしてみます。
<Window x:Class="MainWindow"
すると、ちゃんと起動します。
今回は、小さなプログラムでしたので違いはこのくらいでしたが、「まったく違う」というほどの違いではないので、期待はできそうです。