わかりました、私UserControl
は s の代わりにPage
s を使用して、それらを単一のウィンドウに保持します。あなたは XAML を投稿していないので、あなたの本当のニーズが何であるかはわかりませんが、ここに私の考えがあります:
MultiPageSample.xaml (「メイン ウィンドウ」):
<Window x:Class="MiscSamples.MultiPageMVVM.MultiPageSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MiscSamples.MultiPageMVVM"
Title="MultiPageSample" Height="300" Width="300">
<UniformGrid Rows="1" Columns="2">
<local:Page1 DataContext="{Binding Page1}"/>
<local:Page2 DataContext="{Binding Page2}"/>
</UniformGrid>
</Window>
コードビハインド:
public partial class MultiPageSample : Window
{
public MultiPageSample()
{
InitializeComponent();
DataContext = new MultiPageViewModel();
}
}
ビューモデル:
public class MultiPageViewModel
{
public Page1ViewModel Page1 { get; set; }
public Page2ViewModel Page2 { get; set; }
public MultiPageViewModel()
{
Page1 = new Page1ViewModel();
Page2 = new Page2ViewModel();
Page2.AddNewCommand = new Command(Page1.AddCommand);
}
}
ページ1:
<UserControl x:Class="MiscSamples.MultiPageMVVM.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ItemsControl ItemsSource="{Binding Commands}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding}" Content="Click Me!"
Margin="2"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
コードビハインド:
public partial class Page1 : UserControl
{
public Page1()
{
InitializeComponent();
}
}
ページ2:
<UserControl x:Class="MiscSamples.MultiPageMVVM.Page2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Button Content="Add New Command (I Mean Button)"
VerticalAlignment="Center" HorizontalAlignment="Center"
Command="{Binding AddNewCommand}"/>
</UserControl>
コードビハインド:
public partial class Page2 : UserControl
{
public Page2()
{
InitializeComponent();
}
}
ビューモデル:
public class Page2ViewModel
{
public Command AddNewCommand { get; set; }
}
コマンド クラス (ほとんどの MVVM フレームワークで見つけることができます)
//Dead-simple implementation of ICommand
//Serves as an abstraction of Actions performed by the user via interaction with the UI (for instance, Button Click)
public class Command : ICommand
{
public Action Action { get; set; }
public void Execute(object parameter)
{
if (Action != null)
Action();
}
public bool CanExecute(object parameter)
{
return IsEnabled;
}
private bool _isEnabled = true;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged;
public Command(Action action)
{
Action = action;
}
}
public class Command<T>: ICommand
{
public Action<T> Action { get; set; }
public void Execute(object parameter)
{
if (Action != null && parameter is T)
Action((T)parameter);
}
public bool CanExecute(object parameter)
{
return IsEnabled;
}
private bool _isEnabled;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged;
public Command(Action<T> action)
{
Action = action;
}
}
結果:
さて、このすべての混乱の説明:
まず第一に、コードで UI 要素を操作するという従来の考え方を捨てて、MVVMを採用する必要があります。
WPF には、古代の恐竜フレームワークにはまったくない非常に強力なDataBinding機能があります。
Page1ViewModel のボタンを表すために、再利用可能なCommand
クラス (ほとんどの MVVM フレームワークの基本部分のようなもの) をどのように使用しているかに注意してください。のこれらのインスタンスはCommand
に追加されObservableCollection
、要素が追加または削除されたときに WPF に通知されるため、UI は によって自動的に更新されますBinding
。
次に、forDataTemplate
として定義されたを使用して、 内の各アイテムを「レンダリング」します。ItemTemplate
ItemsControl
Page1
ObservableCollection
これは、WPF で作業するにはまったく異なる考え方が必要であると私が言うときに言及するものです。これは、WPF のすべてに対するデフォルトのアプローチです。手続き型コードで UI 要素を参照/作成/操作する必要はほとんどありません。それが XAML の目的です。
ViewModel
また、これは両方の s に同じものを使用することで大幅に簡略化できることに注意してPage
ください。ただし、異なる ViewModel が互いに直接通信しているこのケースを示すために、意図的にそれらを分けておきました。
ご不明な点がございましたらお知らせください。