首页 > 解决方案 > 试图理解 MVVM 数据不断重置

问题描述

目标:当我在技术人员姓名的文本框中输入一个值时:我希望它在 DataModel 中更新,当我单击 NewCallView 时,它将显示在 newcall 视图中,当我单击返回 DefaultViewModel 时,它仍将显示为已输入。

问题:当我在视图之间更改时,数据会重置。

我将提供我的完整代码,以找出我的数据不断重置的原因。- 我还在学习 MVVM,这是我的第一次尝试。我通常会使用代码隐藏制作一个 1 页的应用程序。我发现很难将我的模型链接到我的视图模型,也许我错误地调用(获取/设置)属性。

关于我的每个视图背后的代码,我根本没有改变它的创建,我只在 Xaml 中工作。

主窗口代码隐藏

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using callFlow.ViewModels;
using callFlow.Models;

namespace callFlow
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            
        }

        private void DefaultViewClicked(object sender, RoutedEventArgs e)
        {
            DataContext = new DefaultViewModel();
        }

         private void NewCallClicked(object sender, RoutedEventArgs e)
        {
            DataContext = new NewCallViewModel();
        }
    }
}

主窗口视图 / wpf

<Window x:Class="callFlow.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:callFlow"
        xmlns:viewmodels="clr-namespace:callFlow.ViewModels"
        xmlns:views="clr-namespace:callFlow.Views"  
        mc:Ignorable="d"
        Title="Call FLow Management" Height="728" Width="1260">
    <Window.Resources>
        <DataTemplate x:Name="defaultViewTemplate" DataType="{x:Type viewmodels:DefaultViewModel}">
            <views:DefaultView DataContext="{Binding}"/>
          </DataTemplate>
        <DataTemplate x:Name="newCallViewTemplate" DataType="{x:Type viewmodels:NewCallViewModel}">
            <views:NewCallView DataContext="{Binding}"/>
        </DataTemplate>

    </Window.Resources>
    <Grid>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

          <Grid.RowDefinitions>
             <RowDefinition Height="*" />
             <RowDefinition Height="*" />
             <RowDefinition Height="*" />
             <RowDefinition Height="*" />
             <RowDefinition Height="*" />
             <RowDefinition Height="*" />
             <RowDefinition Height="*" />
        </Grid.RowDefinitions>
         <Grid Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="5" Grid.RowSpan="6" Background=" 
{DynamicResource {x:Static SystemColors.MenuBrushKey}}"/>
         <Grid Grid.Row="1" Grid.Column="0" Grid.RowSpan="6" />
         <Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="6" Background="FloralWhite">
            <Image Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Source="/BofA2.png"  Width="400" 
HorizontalAlignment="Left" />
            <Border BorderThickness="1" BorderBrush="Black" Grid.Column="0" Grid.Row="0" 
Grid.ColumnSpan="6" CornerRadius="8 8 8 8"/>
            <Border BorderThickness="1" BorderBrush="Black" Grid.Column="0" Grid.Row="1" 
Grid.RowSpan="6" 
CornerRadius="8 8 8 8"/>
 
        </Grid>
        <StackPanel Grid.Row="1" Grid.Column="0" Grid.RowSpan="6">

            <Button Name="loadDefaultView" Content="Home" Grid.Column="2" Grid.Row="2" Height="40" 
Margin="5 5 5 5" Click="DefaultViewClicked" >  </Button>
            <Button Name="loadNewCall" Content="New Call" Grid.Column="2" Grid.Row="2" Height="40" 
Margin="5 0 5 0 " Click="NewCallClicked" ></Button>
        </StackPanel>
        <ContentControl Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="6" Grid.RowSpan="6" Content=" 
  {Binding}">
            
        </ContentControl>
    </Grid>


</Window>

视图/DefaultView.xaml

<UserControl x:Class="callFlow.Views.DefaultView"
             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:callFlow.Views"
             xmlns:viewmodels="clr-namespace:callFlow.ViewModels"
             xmlns:model="clr-namespace:callFlow.Models"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid Background="FloralWhite">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBlock Grid.Column="0" Grid.ColumnSpan="7" Margin="0 10 0 0" HorizontalAlignment="Center" 
Text="Call Flow Management" TextWrapping="Wrap" FontSize="24" VerticalAlignment="Top"/>
        <StackPanel Grid.Row="0" Grid.Column="5" Grid.ColumnSpan="1" Margin="0 5 0 0">        
         <TextBlock HorizontalAlignment="Left" Grid.Column="0" Grid.Row="1" Text="Technician Name: " 
 FontSize="14" TextWrapping="Wrap" Grid.ColumnSpan="2" Width="134"/>
        </StackPanel>
        <StackPanel Grid.Row="0" Grid.Column="6" Grid.ColumnSpan="1" Margin="5 5 5 0">
            <TextBox Name="techName" Text="{Binding SelectedModel.TechName,Mode=TwoWay, 
UpdateSourceTrigger=PropertyChanged}"  BorderBrush="#FF4A5780" Grid.RowSpan="2" />
            </StackPanel>
        <TextBlock x:Name="TextUpdate" Grid.Column="5" HorizontalAlignment="Left" Margin="41,0,0,0" 
Grid.Row="1" Text="{Binding SelectedModel.TechName}" TextWrapping="Wrap" VerticalAlignment="Center"/>

    </Grid>
</UserControl>

ViewModels/DefaultViewModel.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using callFlow.Models;


namespace callFlow.ViewModels
 {
    public class DefaultViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        


        public DefaultViewModel() { }

        private ObservableCollection<DataModel> model = new ObservableCollection<DataModel>();
        private DataModel _SelectedModel;

   

        public DataModel SelectedModel
        {
            get { return _SelectedModel ?? (_SelectedModel = new DataModel()); }
            set { _SelectedModel = value; OnPropertyChanged(); }
        }
        public void changeSelectedModel(DataModel newSelectedModel)
        {
            SelectedModel.TechName = newSelectedModel.TechName;

        }

        private void OnPropertyChanged([CallerMemberName] string techName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(techName));
        }


    }
}

视图\NewCallView.xaml

<UserControl x:Class="callFlow.Views.NewCallView"
             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:callFlow.Views"
             xmlns:viewmodels="clr-namespace:callFlow.ViewModels"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid Background="#FFFDFDFD">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBlock x:Name="techNameSet" Grid.Column="2" HorizontalAlignment="Left" Margin="40,52,0,0" 
 Grid.Row="2" Text="{Binding SelectedModel.TechName}" TextWrapping="Wrap" VerticalAlignment="Top" 
 Grid.ColumnSpan="2" Width="114"/>

    </Grid>
</UserControl>

NewCallViewModel.cs

namespace callFlow.ViewModels
{
    class NewCallViewModel
    {
//It's empty, my view is calling SelectedModel.TechName from DataViewModel which works when I update the DataModel Directly          
    }
}

最后但并非最不重要的!!!!

模型/DataModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using System.Drawing;



namespace callFlow.Models
{
    public class DataModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        
        private string techName;

        public DataModel()
        {
        }

        public string TechName
        {
            get { return techName; }
            set { techName = value;  OnPropertyChanged(); } 

        }

        private void OnPropertyChanged([CallerMemberName] string techName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(techName));
        }
    }
}

标签: c#wpfmvvm

解决方案


推荐阅读