创建新的ViewModel时,ContentControl不刷新视图

时间:2019-09-14 21:46:24

标签: c# .net wpf mvvm mvvm-light

我正在尝试使用带有带有带有按钮的侧栏的MVVMLight制作应用程序,每个按钮都显示一个托管在ContentControl中的新用户控件。当用户单击侧栏中的按钮(显示视图1 /显示视图2)时,将正确显示视图。

当用户已经显示一个View(可能是View1或View2),比如说View1并再次单击(Show View1)时,就会出现我的问题** ** View1控件保持相同的值,我想显示与所有控件相同的视图,就像重新启动一样。 (我知道我可以重置用户控件(View1)中的所有控件,但是我的应用程序每次单击按钮时都需要有一个新的视图实例。)

以某种方式,在相同的情况下,当用户处于视图1中时,切换到视图2并返回到视图1,将创建一个新实例并按照我的意愿显示。我希望得到相同的结果,而无需切换到视图2并返回。

以下是该问题的可重现示例:

  

ViewModelLocator.cs

using CommonServiceLocator;
using GalaSoft.MvvmLight.Ioc;

namespace SidebarApp.ViewModel
{
    public class ViewModelLocator
    {
        /// <summary>
        /// Initializes a new instance of the ViewModelLocator class.
        /// </summary>
        public ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

            // Register viewmodels
            SimpleIoc.Default.Register<MainViewModel>();
            SimpleIoc.Default.Register<View1ViewModel>();
            SimpleIoc.Default.Register<View2ViewModel>();
        }

        public MainViewModel Main { get { return ServiceLocator.Current.GetInstance<MainViewModel>(); } }

        public View1ViewModel View1Vm { get { return ServiceLocator.Current.GetInstance<View1ViewModel>(); } }

        public View2ViewModel View2Vm { get { return ServiceLocator.Current.GetInstance<View2ViewModel>(); } }

        public static void Cleanup()
        {
            // TODO Clear the ViewModels
        }
    }
}
  

MainViewModel.cs

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Windows.Input;

namespace SidebarApp.ViewModel
{
    public class MainViewModel : ViewModelBase
    {

        // Commands
        public ICommand ShowView1Command { get; private set; }
        public ICommand ShowView2Command { get; private set; }

        /// <summary>
        /// Property that will cointain the current viewmodel to show
        /// ViewModelBase inplements ObservableObject class which imlements INotifyPropertyChanged
        /// </summary>
        public ViewModelBase CurrentViewModel { get; set; }

        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            this.ShowView1Command = new RelayCommand(ShowView1);
            this.ShowView2Command = new RelayCommand(ShowView2);
        }

        private void ShowView1()
        {
            // I tried this but it doesn't work
            //CurrentViewModel = null or View2ViewModel;

            CurrentViewModel = new View1ViewModel();

        }
        private void ShowView2()
        {
            CurrentViewModel = new View2ViewModel();
        }

    }
}
  

MainWindow.xaml

<Window x:Class="SidebarApp.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:SidebarApp"
        mc:Ignorable="d"
        DataContext="{Binding Main, Source={StaticResource Locator}}"
        Title="MainWindow" Height="348.965" Width="560.683">

    <Window.Resources>
        <DataTemplate DataType="{x:Type local:View1ViewModel}">
            <local:View1View />
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:View2ViewModel}">
            <local:View2View />
        </DataTemplate>

    </Window.Resources>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.3*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <StackPanel>
            <Button Command="{Binding ShowView1Command}">Show View1</Button>
            <Button Command="{Binding ShowView2Command}">Show View2</Button>            
        </StackPanel>
        <ContentControl Grid.Column="1" Content="{Binding Path=CurrentViewModel}"></ContentControl>
    </Grid>
</Window>
  

View1View.xaml

<UserControl x:Class="SidebarApp.View1View"
             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:SidebarApp"
             mc:Ignorable="d" 
             DataContext="{Binding View1Vm, Source={StaticResource Locator}}"
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid Background="LightPink">
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock HorizontalAlignment="Center" Text="Welcome to View 1" FontSize="20"/>
            <TextBox HorizontalAlignment="Stretch" Text="Original text value"/>
            <CheckBox Content="Some boolean value"/>
        </StackPanel>
    </Grid>
</UserControl>
  

View1ViewModel.cs

using GalaSoft.MvvmLight;

namespace SidebarApp
{
    public class View1ViewModel : ViewModelBase
    {
        public View1ViewModel()
        {

        }
    }
}
  

View2View.xaml

<UserControl x:Class="SidebarApp.View2View"
             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:SidebarApp"
             mc:Ignorable="d" 
             DataContext="{Binding View2Vm, Source={StaticResource Locator}}"
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid Background="LightCyan">
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock HorizontalAlignment="Center" Text="Welcome to View 2" FontSize="20"/>
            <TextBox HorizontalAlignment="Stretch" Text="Some text in view2"/>
            <Button Content="Button"/>
        </StackPanel>
    </Grid>
</UserControl>
  

View2ViewModel.cs

using GalaSoft.MvvmLight;

namespace SidebarApp
{
    public class View2ViewModel : ViewModelBase
    {
        public View2ViewModel()
        {

        }
    }
}
  

App.xaml

<Application x:Class="SidebarApp.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SidebarApp" StartupUri="MainWindow.xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d1p1:Ignorable="d" xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006">
  <Application.Resources>
    <ResourceDictionary>
      <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:SidebarApp.ViewModel" />
    </ResourceDictionary>
  </Application.Resources>
</Application>

例如,我进入view1并将文本框的值(“原始文本值”)更改为另一个值,然后在Show View1中再次单击该文本,并且用户控件中的所有内容保持不变,但是当我切换到view2时然后返回到view1,将显示一个新的用户控件及其原始值。

1 个答案:

答案 0 :(得分:0)

这似乎是一种解决方法,但它可以工作。希望它将证明有用。 (显然,对View2View视图/视图模型进行了相同的更改。)


ViewModelLocator.cs

 public View1ViewModel View1Vm { get { return new View1ViewModel(); } }


MainViewViewModel.cs

 private void ShowView1()
 {            
    CurrentViewModel = new ViewModelLocator().View1Vm;           
 }


View1View.xaml

<UserControl x:Class="SidebarApp.View1View"
             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:SidebarApp"
             mc:Ignorable="d"                  
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid Background="LightPink">
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock HorizontalAlignment="Center" Text="Welcome to View 1" FontSize="20"/>
            <TextBox HorizontalAlignment="Stretch" Text="{Binding Path=View1Text, Mode=TwoWay}"/>
            <CheckBox Content="Some boolean value" IsChecked="{Binding Path=CheckBoxChecked, Mode=TwoWay}"/>
        </StackPanel>
    </Grid>
</UserControl>

View1ViewModel.cs

public class View1ViewModel : ViewModelBase
{
        private string _view1Text;
        private bool _checkBoxedChecked;

        public string View1Text
        {
            get
            {
                return _view1Text;
            }
            set
            {
                _view1Text = value;
                RaisePropertyChanged("View1Text");                
            }
        }

        public bool CheckBoxChecked
        {
            get
            {
                return _checkBoxedChecked;
            }
            set
            {
                _checkBoxedChecked = value;
                RaisePropertyChanged("CheckBoxChecked");
            }
        }

        public View1ViewModel()
        {
            View1Text = "Original text value";
        }
}

相关问题