0

以前の質問では、私が明確ではなかったと思うので、役立つ回答が得られなかったので、コード例をいくつか投稿します。GreenScreen.xaml

<UserControl x:Class="WPFTut.GreenScreenView"
         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" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid Background="Green">
    <Label Content="{Binding ScreenViewModel.ScreenName}"/>
    <Label Content="{Binding ScreenViewModel.UniqueProperty}"/>
</Grid>

RedScreen.xaml

<UserControl x:Class="WPFTut.RedScreenView"
         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" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid Background="Red">
    <Label Content="{Binding ScreenViewModel.ScreenName}"/>
</Grid>

Main.xaml

<Window x:Class="WPFTut.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid x:Name="LayoutRoot">
</Grid>

IScreenViewModel.cs

namespace WPFTut
{
    interface IScreenViewModel
    {
        string ScreenName { get; set; }
    }
}

RedScreenViewModel.cs

namespace WPFTut
{
    class RedScreenViewModel:IScreenViewModel
    {
        public string ScreenName
        {
            get; set;
        }
    }
}

GreenScreenViewModel.cs

  namespace WPFTut
    {
    class GreenScreenViewModel : IScreenViewModel
    {
        public string ScreenName { get; set; }

        public string UniqueProperty { get; set; }
    }
   }

ScreenViewModelWrapper.cs

using System.ComponentModel;

namespace WPFTut
{
    class ScreenViewModelWrappers : INotifyPropertyChanged
    {
        private IScreenViewModel screenViewModel;

        private IScreenViewModel ScreenViewModel
        {
            get { return screenViewModel; }
            set
            {
                if (screenViewModel != value)
                {
                    screenViewModel = value;
                    OnPropertyChanged("ScreenViewModel");
                }
            }
        }

        public void SwapViewModel(MainWindow mainWindow)
        {
            //Yeah it was done statically, but in my original code, it is actually dynamic to switch between 
            //any screens. Just to keep it simlpe
            mainWindow.LayoutRoot.Children.Clear();
            mainWindow.LayoutRoot.Children.Add(new GreenScreenView()); // here add randomly chosen screen from array of screens.
            mainWindow.UpdateLayout(); //it doesn't refresh the visual tree. So if a red screen was selected next, an exception is thrown
            ScreenViewModel = new GreenScreenViewModel(); //
        }
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            var s = new PropertyChangedEventArgs(propertyName);
            if (handler != null)
            {

                handler(this, s);
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}

それが私が書くことができる簡単な例です。繰り返しになりますが、ViewModelWrapper では、ユーザー入力に基づいて画面が動的に選択されます。GreenScreenView が最初に選択されたと仮定すると、RedScreen を削除してクリアして追加し、バインディングを更新しようとしたときに ScreenViewModel を RedScreenViewModel に変更しても、GreenScreenView が表示されます。したがって、これを検索しようとします。

<Label Content="{Binding ScreenViewModel.UniqueProperty}"/>

しかし、そのコードは RedScreenView に属していないので、ビジュアル ツリーを更新して正しい xaml ツリーを表示するにはどうすればよいでしょうか? NullReferenceException をスローしているためです。もっとはっきりさせられるかどうかは本当にわかりません。再度、感謝します。

前の質問へのリンク: UpdateLayout またはその他の代替手段を使用してビューのデータバインディングを更新する

4

0 に答える 0