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

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

ただいまの
回答率

88.37%

Viewを内部に持つViewを複数生成できない

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,200

zin123

score 11

Viewを内部に持つViewを複数生成したいです。

ListBoxの数値を選択すると、選択された数値を受け取ったViewを表示するプログラムを作っています。
以前表示したViewは残して、異なる数値が選択された場合、新しくViewを生成するようにしたいです。

Viewの内部にViewを持っていると1→2に変えたときに下記のエラーが出ます。

ArgumentException: Region with the given name is already registered: ViewBRegion

WPF
.NET Core 3
Prism.Unity(7.2.0.1367)
ReactiveProperty(6.1.4)

<フォルダ構成>

ViewModelsフォルダ

  • MainWindowViewModel.cs
  • ViewAViewModel.cs
  • ViewBViewModel.cs

Viewsフォルダ

  • UserControls/ViewA.xaml
  • UserControls/ViewB.xaml
  • MainWindow.xaml

App.xaml

MainWindowViewModel.cs

using Prism.Mvvm;
using Prism.Regions;
using Reactive.Bindings;
using System;
using System.Collections.Generic;
using Test.Views.UserControls;
using Unity;

namespace Test.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        [Dependency]
        public IRegionManager RegionManager { get; set; }
        public List<int> NumberList { get; private set; }
        public ReactiveProperty<int> SelectedNumber { get; set; }
        public MainWindowViewModel()
        {
            this.NumberList = new List<int> { 1, 2, 3 };
            this.SelectedNumber = new ReactiveProperty<int>();

            this.SelectedNumber.Subscribe(_=>this.ChangeView()) ;
        }

        private void ChangeView()
        {
            if(RegionManager != null)
            {
                this.RegionManager.RequestNavigate("ContentRegion", nameof(ViewA), new NavigationParameters($"id={this.SelectedNumber.Value}"));
            }
        }
    }
}


ViewAViewModel.cs

using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using Reactive.Bindings;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Test.ViewModels
{
    public class ViewAViewModel : BindableBase, INavigationAware
    {
        public ReactiveProperty<string> Id { get; private set; }
        public ViewAViewModel()
        {
            Id = new ReactiveProperty<string>();
        }

        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return this.Id.Value == navigationContext.Parameters["id"] as string;
        }

        public void OnNavigatedFrom(NavigationContext navigationContext)
        {

        }

        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            this.Id.Value = navigationContext.Parameters["id"] as string;
        }
    }
}


ViewBViewModel.cs

using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Test.ViewModels
{
    public class ViewBViewModel : BindableBase
    {
        public ViewBViewModel()
        {

        }
    }
}


MainWindow.xaml

<Window x:Class="Test.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525" >
    <StackPanel>
        <ListBox ItemsSource="{Binding NumberList}" SelectedItem="{Binding SelectedNumber.Value}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListBox>
        <ContentControl prism:RegionManager.RegionName="ContentRegion" />
    </StackPanel>
</Window>


ViewA.xaml

<UserControl x:Class="Test.Views.UserControls.ViewA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True"
             Loaded="UserControl_Loaded">
    <StackPanel>
        <TextBlock Text="{Binding Id.Value}"/>
        <ContentControl prism:RegionManager.RegionName="ViewBRegion" />
    </StackPanel>
</UserControl>


ViewA.xaml.cs

using Prism.Ioc;
using Prism.Regions;
using System.Windows.Controls;
using Unity;

namespace Test.Views.UserControls
{
    /// <summary>
    /// Interaction logic for ViewA
    /// </summary>
    public partial class ViewA : UserControl
    {
        [Dependency]
        public IContainerExtension ContainerExtension { get; set; }
        [Dependency]
        public IRegionManager RegionManager { get; set; }
        public ViewA()
        {
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            RegionManager.AddToRegion("ViewBRegion", ContainerExtension.Resolve<ViewB>());

        }
    }
}


ViewB.xaml

<UserControl x:Class="Test.Views.UserControls.ViewB"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True">
    <Grid>
        <TextBlock Text="ViewB"/>
    </Grid>
</UserControl>


app.xaml.cs

using Prism.Ioc;
using Test.Views;
using System.Windows;
using Test.Views.UserControls;
using Prism.Mvvm;
using Test.ViewModels;

namespace Test
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App
    {
        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<ViewA>();
        }
        protected override void ConfigureViewModelLocator()
        {
            base.ConfigureViewModelLocator();
            ViewModelLocationProvider.Register<ViewA, ViewAViewModel>();
            ViewModelLocationProvider.Register<ViewB, ViewBViewModel>();

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

メッセージの通りRegionManagerに"ViewBRegion"を複数回登録しているから出ている例外です。
複数カ所で登録しているか または、Loadedイベントが複数回発生してないか確認してください。
また、おそらくその用途なら、ContainerRegistryに登録するのが適切であろうかと思われます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/11 16:44 編集

    回答ありがとうございます。
    ViewAを複数生成するので、毎回ViewBをRegionに登録しているから例外が出ていることがわかりました。ありがとうございました。
    例としてユーザー一覧からユーザー詳細画面(Viewを複数含む)を複数生成したい場合、この例外を回避する方法はあるのでしょうか?

    キャンセル

  • 2019/12/11 16:52

    RegionManagerの使い方が間違っています。
    Regionは大まかな枠組みに使って、動的な画面遷移などはContainerRegistryに登録したものを使うのが筋です。
    サンプルはいくらでもありますから先ずはサンプル通りに作ってみてください。

    キャンセル

  • 2019/12/11 22:21

    回答ありがとうございます。
    やってみます。

    キャンセル

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

  • ただいまの回答率 88.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る