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

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

新規登録して質問してみよう
ただいま回答率
85.48%
VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

MVVM

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

WPF

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

Q&A

解決済

1回答

1083閲覧

wpfアプリの画面遷移について

noke

総合スコア6

VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

MVVM

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

WPF

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

0グッド

0クリップ

投稿2023/08/28 08:19

実現したいこと

MainWindow.xamlに配置しているUserControl1.xamlのsettingButtonを押下して表示内容をUserControl2.xamlに切り替えたいです。

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

エラー BC30456 'DataContext' は 'MainWindowsViewModel' のメンバーではありません。 ColorArrayInspection C:\Users\F000000\source\repos\ColorArrayInspection\ColorArrayInspection\ViewModels\MainWindowsViewModel.vb 48 アクティブ

該当のソースコード

・MainWindowsViewModel.vb
Imports CommunityToolkit.Mvvm.Input
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Imports System.Text.RegularExpressions

Public Class MainWindowsViewModel
Implements INotifyPropertyChanged

Private _currentView As Object Public Property CurrentView As Object Get Return _currentView End Get Set(value As Object) _currentView = value OnPropertyChanged() End Set End Property Private Sub OnPropertyChanged(<CallerMemberName> Optional propertyName As String = Nothing) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) End Sub Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged Private Sub LotText_PreviewTextInput(ByVal sender As Object, ByVal e As TextCompositionEventArgs) ' 半角英数字以外の文字が入力された場合は、イベントをキャンセルする If Not Regex.IsMatch(e.Text, "^[0-9a-zA-Z]+$") Then e.Handled = True End If ' 入力文字数が16文字を超えた場合は、イベントをキャンセルする 'If lotText.Text.Length >= 16 And e.Text <> ChrW(8) Then ' e.Handled = True 'End If End Sub Private _settingButtonCommand As ICommand Public ReadOnly Property SettingButtonCommand As ICommand Get If _settingButtonCommand Is Nothing Then _settingButtonCommand = New RelayCommand(AddressOf SettingButton_Click) End If Return _settingButtonCommand End Get End Property Private Sub SettingButton_Click() Dim mainWindowViewModel As MainWindowsViewModel = TryCast(Me.DataContext, MainWindowsViewModel) mainWindowViewModel.CurrentView = New UserControl2() End Sub

End Class

・UserControl1.xaml <UserControl x:Class="UserControl1" 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:ColorArrayInspection" d:DataContext="{d:DesignInstance Type=local:MainWindowsViewModel}" xmlns:vm="clr-namespace:ColorArrayInspection" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.DataContext> <vm:MainWindowsViewModel/> </UserControl.DataContext> <Grid Background="White"> <TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}" x:Name="homeBlock" TextWrapping="Wrap" Background="#7F673AB7" Foreground="White" FontSize="24" VerticalAlignment="Top" Height="42" Text="UserControl1&#xD;&#xA;"/> <TextBox x:Name="lotText" HorizontalAlignment="Left" Height="64" Margin="205,64,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="310" Style="{DynamicResource MaterialDesignOutlinedTextBox}" MaxLength="16" FontSize="24" VerticalContentAlignment="Center"/> <Label x:Name="messageLabel" Content="メッセージ" Margin="80,185,0,225" FontSize="24" HorizontalAlignment="Left" RenderTransformOrigin="0.472,0.851"/> <TextBlock Style="{StaticResource MaterialDesignHeadline1TextBlock}" x:Name="messageBlock" TextWrapping="Wrap" Margin="80,225,80,50" Background="#19000000" FontSize="48"><Run Language="ja-jp" Text=""/></TextBlock> <Button x:Name="settingButton" Content="設定" Margin="720,5,10,413" Command="{Binding SettingButtonCommand}"/> <Label x:Name="lotLabel" Content="ロット番号" Margin="80,76,0,334" FontSize="24" RenderTransformOrigin="0.472,0.851" VerticalContentAlignment="Stretch" HorizontalAlignment="Left" Width="120"/> </Grid> </UserControl> ### 試したこと ここに問題に対して試したことを記載してください。 ### 補足情報(FW/ツールのバージョンなど) ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

そりゃそうですよね?
MeMainWindowsViewModel自身なんですからDataContextはありません。

vb

1Private Sub SettingButton_Click() 2 Dim mainWindowViewModel As MainWindowsViewModel = TryCast(Me.DataContext, MainWindowsViewModel) 3 mainWindowViewModel.CurrentView = New UserControl2() 4End Sub

ただ通すだけならこれで済みますが、それで解決とも思えません。

vb

1Private Sub SettingButton_Click() 2 CurrentView = New UserControl2() 3End Sub

このコードはもともと(MainWindowUserControl1?の)ビハインドコードですよね?

MVVMで画面遷移する場合は、子ViewModelを用意してDataTemplateで切り替えるパターンが多いです(VBでの例が見つけられませんでしたが雰囲気はわかると思います)
【WPF】ContentControlで画面遷移する方法を紹介(MVVM)
wpf 画面遷移 - Google 検索

ViewModelでUserControl自体を保持してしまうと、テストしづらくMVVMのメリットがありません(というかViewとViewModelが分離できておらずMVVMになっていません)

VBできないのでこれと言ってサンプル提示もできませんが^^;


他気になった点

CommunityToolkitを入れているのであれば、INotifyPropertyChanged実装はすでに入っています。
ObservableObject - .NET Community Toolkit | Microsoft Learn

ぐちゃぐちゃマージン(Margin="80,185,0,225"のような)があると、ウィンドウリサイズ等で盛大に崩れます。
GridDockPanel等を使ってちゃんとレイアウトしましょう。


ざっとサンプル作りました(C#からの機械翻訳なので変なところがあるかもしれません)
が、遷移コマンドを子ViewModel内に用意するのは、ちょっと気持ち悪い気がします^^;
個人的にはNavigationRailTabControl)やDrawerHost等を使って、こういった遷移にならないようにするほうが好みです^^

xml:MainWindow.xaml

1<Window 2 x:Class="MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:local="clr-namespace:Qoa07su5ulvykbq" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 Title="MainWindow" 9 Width="800" 10 Height="450" 11 mc:Ignorable="d"> 12 <Window.Resources> 13 <DataTemplate DataType="{x:Type local:UserControl1ViewModel}"> 14 <local:UserControl1 /> 15 </DataTemplate> 16 <DataTemplate DataType="{x:Type local:UserControl2ViewModel}"> 17 <local:UserControl2 /> 18 </DataTemplate> 19 </Window.Resources> 20 <Grid> 21 <ContentControl Content="{Binding CurrentView}" /> 22 </Grid> 23</Window>

xml:UserControl1.xaml

1<UserControl 2 x:Class="UserControl1" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 7 d:DesignHeight="450" 8 d:DesignWidth="800" 9 Background="White" 10 mc:Ignorable="d"> 11 <DockPanel> 12 <Grid DockPanel.Dock="Top"> 13 <TextBlock 14 Background="#7F673AB7" 15 FontSize="24" 16 Foreground="White" 17 Text="UserControl1" /> 18 <Button 19 Margin="8,4" 20 HorizontalAlignment="Right" 21 Command="{Binding SettingButtonCommand}" 22 Content="設定" /> 23 24 <!-- こうやればコマンドをもらわずに済むがこれはこれで気持ち悪い^^; --> 25 <!--<Button 26 Margin="8,4" 27 HorizontalAlignment="Right" 28 Command="{Binding DataContext.GoToUserControl2Command, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" 29 Content="設定" />--> 30 </Grid> 31 32 <Grid Margin="80,20,80,40"> 33 <Grid.RowDefinitions> 34 <RowDefinition Height="Auto" /> 35 <RowDefinition /> 36 </Grid.RowDefinitions> 37 <DockPanel TextBlock.FontSize="24"> 38 <Label VerticalAlignment="Center" Content="ロット番号" /> 39 <TextBox 40 MinWidth="310" 41 MinHeight="64" 42 HorizontalAlignment="Left" 43 Style="{DynamicResource MaterialDesignOutlinedTextBox}" 44 Text="{Binding LotNumber, UpdateSourceTrigger=PropertyChanged}" /> 45 </DockPanel> 46 47 <DockPanel Grid.Row="1" Margin="0,60,0,0"> 48 <Label 49 Content="メッセージ" 50 DockPanel.Dock="Top" 51 FontSize="24" /> 52 <TextBlock 53 Background="#19000000" 54 FontSize="48" 55 Style="{StaticResource MaterialDesignHeadline1TextBlock}" /> 56 </DockPanel> 57 </Grid> 58 </DockPanel> 59</UserControl>

xml:UserControl2.xaml

1<UserControl 2 x:Class="UserControl2" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 7 d:DesignHeight="450" 8 d:DesignWidth="800" 9 Background="White" 10 mc:Ignorable="d"> 11 <DockPanel> 12 <Grid DockPanel.Dock="Top"> 13 <TextBlock 14 Background="#7F673AB7" 15 FontSize="24" 16 Foreground="White" 17 Text="UserControl2" /> 18 <Button 19 Margin="8,4" 20 HorizontalAlignment="Right" 21 Command="{Binding BackButtonCommand}" 22 Content="戻る" /> 23 </Grid> 24 25 <TextBox 26 Margin="80,20,80,40" 27 VerticalAlignment="Top" 28 FontSize="24" 29 Style="{DynamicResource MaterialDesignOutlinedTextBox}" 30 Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" /> 31 </DockPanel> 32</UserControl>

vb

1Imports System.ComponentModel.DataAnnotations 2Imports CommunityToolkit.Mvvm.ComponentModel 3Imports CommunityToolkit.Mvvm.Input 4 5Public Class MainWindowViewModel 6 Inherits ObservableObject 7 8 Public Property CurrentView As Object 9 Get 10 Return _currentView 11 End Get 12 Set(ByVal value As Object) 13 SetProperty(_currentView, value) 14 End Set 15 End Property 16 Private _currentView As Object 17 18 Public ReadOnly Property GoToUserControl1Command As ICommand 19 Public ReadOnly Property GoToUserControl2Command As ICommand 20 21 Private userControl2ViewModel As UserControl2ViewModel 22 23 Public Sub New() 24 GoToUserControl1Command = New RelayCommand(AddressOf BackButton_Click) 25 GoToUserControl2Command = New RelayCommand(AddressOf SettingButton_Click) 26 27 '遷移させるのはこっちなのでコマンドを差し込み(ちょっと気持ち悪いか?^^; 28 CurrentView = New UserControl1ViewModel(GoToUserControl2Command) 29 userControl2ViewModel = New UserControl2ViewModel(GoToUserControl1Command) 30 End Sub 31 32 Private Sub SettingButton_Click() 33 'インスタンス使いまわし(なのでTextの状態が残る) 34 CurrentView = userControl2ViewModel 35 End Sub 36 37 Private Sub BackButton_Click() 38 'インスタンス都度生成(なのでLotNumberの状態は残らない) 39 CurrentView = New UserControl1ViewModel(GoToUserControl2Command) 40 End Sub 41End Class 42 43Public Class UserControl1ViewModel 44 Inherits ObservableValidator 45 46 <MaxLength(16, ErrorMessage:="最大16文字までです。")> 47 <RegularExpression("[a-zA-Z0-9]+", ErrorMessage:="半角英数字のみ入力できます。")> 48 Public Property LotNumber As String 49 Get 50 Return _lotNumber 51 End Get 52 Set(ByVal value As String) 53 SetProperty(_lotNumber, value, True) 54 End Set 55 End Property 56 Private _lotNumber As String 57 58 Public Property Message As String 59 Get 60 Return _message 61 End Get 62 Set(ByVal value As String) 63 SetProperty(_message, value) 64 End Set 65 End Property 66 Private _message As String 67 68 Public ReadOnly Property SettingButtonCommand As ICommand 69 70 Public Sub New(ByVal settingButtonCommand As ICommand) 71 Me.SettingButtonCommand = settingButtonCommand 72 End Sub 73End Class 74 75Public Class UserControl2ViewModel 76 Inherits ObservableObject 77 78 Public Property Text As String 79 Get 80 Return _text 81 End Get 82 Set(ByVal value As String) 83 SetProperty(_text, value, True) 84 End Set 85 End Property 86 Private _text As String 87 88 Public ReadOnly Property BackButtonCommand As ICommand 89 90 Public Sub New(ByVal backButtonCommand As ICommand) 91 Me.BackButtonCommand = backButtonCommand 92 End Sub 93End Class 94 95Partial Public Class MainWindow 96 Inherits Window 97 98 Public Sub New() 99 InitializeComponent() 100 DataContext = New MainWindowViewModel() 101 End Sub 102End Class

NuGet Gallery | CommunityToolkit.Mvvm 8.2.1
NuGet Gallery | MaterialDesignThemes 4.9.0

アプリ動画

投稿2023/08/28 11:13

編集2023/08/28 15:19
TN8001

総合スコア9326

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問