代码之家  ›  专栏  ›  技术社区  ›  Cosmin

使用MVVM、实体框架和mysql将基本数据绑定到textbox

  •  1
  • Cosmin  · 技术社区  · 7 年前

    我刚刚开始学习WPF和MVVM。我知道这个问题可能被问了很多,但我已经阅读了关于MVVM和EF的所有内容,尝试了那里的每个示例和教程,阅读了“How to survival MVVM for Enterprise”,但我仍然无法理解如何正确使用模式和框架来简单绑定到文本框。有人能帮我举个简单易懂的例子吗?

    namespace Location.Model
    {
        using System;
        using System.Data.Entity;
        using System.Data.Entity.Infrastructure;
    
        public partial class DailyEntities : DbContext
        {
            public DailyEntities()
                : base("name=DailyEntities")
            {
            }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                throw new UnintentionalCodeFirstException();
            }
    
            public DbSet<LocationKPI> LocationKPI { get; set; }
    
        }
    }
    

    位置KPI。反恐精英

    namespace Location.Model
    {
        using System;
        using System.Collections.Generic;
    
        public partial class LocationKPI
        {
            public long sMonth { get; set; }
            public Nullable<decimal> Efficiency { get; set; }
        }
    }
    

    我创建了一个ViewModel文件夹,其中包含一个实现INotifyPropertyChanged的类:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Location.ViewModel
    {
        public class LocationViewModel: INotifyPropertyChanged
        {
    
            public decimal Efficiency
            {
                get { return _Efficienecy; }
                set
                {
                    _Efficiency = value;
                    OnPropertyChanged("Efficiency");
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnPropertyChanged(string propertyName = null)
            {
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    <Window x:Class="Location.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:Location"
            xmlns:vm="clr-namespace:Location.ViewModel"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
    
        <Grid>
            <DatePicker HorizontalAlignment="Left" Margin="392,17,0,0" VerticalAlignment="Top"/>
            <TextBlock Text="Efficiency"></TextBlock>
            <TextBox Text="{Binding Efficiency}" ></TextBox>
    
        </Grid>
    </Window>
    

    我在这里真的疯了。我正在寻找一些关于如何将模型和viewmodel“粘合”到我的视图的指导,我只需要一个简单的示例来理解。如果问题太宽泛,我很抱歉。

    查询应该写在模型还是viewmodel中?如何定义数据上下文并编写一个简单的 select Efficiency where sMonth = 9

    1 回复  |  直到 7 年前
        1
  •  2
  •   Ibrahim Malluf    7 年前

    让我们从INotifyPropertyChanged接口开始,并介绍如何实现它。一般来说,我试图创建一个抽象类,Model和ViewModel都使用这个抽象类,它包含了我的所有模型和viewmodels中常见的一切。以下是这些抽象类:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    
    namespace WpfStackOverflow.Models
    {
    /// <summary>
    /// Abstract class that provides common functionality accross all View Models.
    /// </summary>
    public abstract class modelBase : INotifyPropertyChanged
    {
    
        #region INotifyPropertyChanged
        /// <summary>
        /// Provides a simplefied INotifyPropertyChanged interface.
        /// requires System.Runtime.CompilerServices and
        /// System.ComponentModel.
        /// </summary>
        /// <param name="property"></param>
        public void SetPropertyChanged([CallerMemberName] string property = null)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    }
    #endregion
    }
    
    namespace WpfStackOverflow.ViewModels
    {
        /// <summary>
        /// Abstract class that provides common functionality accross all View     Models.
        /// </summary>
        public abstract class ViewModelBase : INotifyPropertyChanged
        {
    
            #region INotifyPropertyChanged
            /// <summary>
            /// Provides a simplefied INotifyPropertyChanged interface.
            /// requires System.Runtime.CompilerServices and
            /// System.ComponentModel.
            /// </summary>
            /// <param name="property"></param>
            public void SetPropertyChanged([CallerMemberName] string property = null)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
            #endregion
        }
    }
    

    以下是我创建的视图模型:

    namespace WpfStackOverflow.ViewModels
    {
        class BasicMVVMViewModel:ViewModelBase
        {
    
            private ObservableCollectionEx<LocationKPI> _locations;
    
            public BasicMVVMViewModel()
            {
                CreateTestData();
            }
    
            private DateTime _selectedDate;
            public DateTime SelectedDate
            {
    
                get { return _selectedDate; }
                set
                {
                    _selectedDate = value;
                    SetPropertyChanged();
                    SetSelectedLocationKPI( _selectedDate.Month);
                }
            }
    
            private LocationKPI _selectedLocationKPI;
            public LocationKPI SelectedLocationKPI
            {
                get { return _selectedLocationKPI; }
                set
                {
                    _selectedLocationKPI = value;
                    SetPropertyChanged();
                }
            }
    
            private void  SetSelectedLocationKPI(long sMonth)
            {
                SelectedLocationKPI = _locations.Where(p => p.SMonth.Equals(sMonth)).FirstOrDefault();
            }
    
    
            private void CreateTestData()
            {
    
                _locations = new ObservableCollectionEx<LocationKPI>();
                for(int i=0; i < 12;i++)
                {
                    _locations.Add(new LocationKPI() { SMonth = i, Efficiency = i*17 });
                }
    
            }
    
        }
    }
    

    <UserControl x:Class="WpfStackOverflow.Controls.BasicMVVM"
                 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:WpfStackOverflow.Controls"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="35"/>
                <RowDefinition Height="35"/>
                <RowDefinition Height="35"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <DatePicker HorizontalAlignment="Left" Margin="30,5,0,0"   Grid.Row="1" VerticalAlignment="Top" Width="150" SelectedDate="{Binding SelectedDate}"/>
            <TextBlock x:Name="textBlock" HorizontalAlignment="Stretch"  Grid.Row="2" TextWrapping="Wrap" 
                   Text="{Binding SelectedLocationKPI.Efficiency,Mode=TwoWay}" VerticalAlignment="Stretch" Margin="5"/>
    
        </Grid>
    </UserControl>
    

    在Viewmodel中,我调用了一个创建测试数据的方法。在您的情况下,您可以从linq查询中获取数据。(你弄明白了:)

    您必须调整一些引用和命名以适应您的环境。我在这里发布的内容经过了测试,效果良好。我希望它能帮助您更好地理解MVVM。哦,是的,还有一件事,你在这里看到的XAML来自用户控件,而不是XAML窗口。在代码隐藏中,您必须实例化ViewModel并将其设置为DataContext:

    namespace WpfStackOverflow.Controls
    {
        /// <summary>
        /// Interaction logic for BasicMVVM.xaml
        /// </summary>
        public partial class BasicMVVM : UserControl
        {
            public BasicMVVM()
            {
               InitializeComponent();
               DataContext = new BasicMVVMViewModel();
            }
        }
    }