【问题标题】:Binding Viewmodel error | XAML Parse Exception绑定 Viewmodel 错误 | XAML 解析异常
【发布时间】:2018-04-13 08:14:33
【问题描述】:

我使用 MVVM 模式实现了一个小型 WPF 应用程序。 在 view.xaml 中设置 Datacontext 之后。我收到以下错误。

XAML 代码

<control:CustomWindow
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:control="clr-namespace:eCustomWindow;assembly=eCustomWindow"
    xmlns:eControls="clr-namespace:eControls;assembly=eControls"
    xmlns:nGantt="clr-namespace:nGantt;assembly=nGantt"
    xmlns:GanttChart="clr-namespace:nGantt.GanttChart;assembly=nGantt" 
     xmlns:viewModel="clr-namespace:ViewModel;assembly=ViewModel"
    x:Class="iView.Window_Absence"
    Title="Window_Absence" Height="914" Width="1599">


<control:CustomWindow.DataContext>
    <viewModel:ViewModel_Absence/>
</control:CustomWindow.DataContext>

我的视图模型

  namespace ViewModel

{
    public class ViewModel_Absence : INotifyPropertyChanged 
    {

    private readonly DatabaseContext _DataContext;


    public ViewModel_Absence()
    {
         this._DataContext = DatabaseContext.Instance;      
    }

    #region PropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;


    protected void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion

}

}

Databasecontext 类的代码。例外是相同的。它在用 adapter_employee 填充表员工后抛出。

    public class DatabaseContext
{

    /// <summary>
    /// Gets the data set.
    /// </summary>
    public ForeCastDataSet DataSet { get; private set; }
    private const string DatabaseFileName = "ForeCast.xml";
    private static DatabaseContext instance;
    private String team = "C ITS, Western-Center";




   // Adapter für die "Datagrids"
    public ForeCastDataSetTableAdapters.MonatsuebersichtTableAdapter adapter_viewmonth;
    public ForeCastDataSetTableAdapters.StammdatenTableAdapter adapter_master;
    public ForeCastDataSetTableAdapters.AbwesenheitenTableAdapter adapter_absence;

    // Adapter zum befüllen von "ComboBox"
    public ForeCastDataSetTableAdapters.BundeslandTableAdapter adapter_state;
    public ForeCastDataSetTableAdapters.MonatsauswahlTableAdapter adapter_month;
    public ForeCastDataSetTableAdapters.ProfileTableAdapter adapter_profile;
    public ForeCastDataSetTableAdapters.TeamAdapter adapter_team;


    // Abwesenheiten
 //   public ForeCastDataSetTableAdapters.UrlaubTableAdapter adapter_holiday;
    public ForeCastDataSetTableAdapters.MitarbeiterTableAdapter adapter_employee;
//   public ForeCastDataSetTableAdapters.AbwesenheitenplanungTableAdapter adapter_organiseAbsence;



    private DatabaseContext()
    {


        this.DataSet =  new DataModel.ForeCastDataSet();

        this.adapter_month = new ForeCastDataSetTableAdapters.MonatsauswahlTableAdapter();
        this.adapter_month.Fill(this.DataSet.Monatsauswahl, this.team);
        // Adapter für neue Mitarbeiter initalisieren

        this.adapter_viewmonth = new ForeCastDataSetTableAdapters.MonatsuebersichtTableAdapter();
        this.adapter_month = new ForeCastDataSetTableAdapters.MonatsauswahlTableAdapter();
        this.addColumnsViewMonth();
        this.adapter_month.Fill(this.DataSet.Monatsauswahl, team);

        this.adapter_state = new ForeCastDataSetTableAdapters.BundeslandTableAdapter();
        this.adapter_state.Fill(this.DataSet.Bundesland);

        this.adapter_team = new ForeCastDataSetTableAdapters.TeamAdapter();
        this.adapter_team.Fill(this.DataSet.Team);

        this.adapter_master = new ForeCastDataSetTableAdapters.StammdatenTableAdapter();
        this.adapter_master.Fill(this.DataSet.Stammdaten,this.team, 2018);

        this.adapter_profile = new ForeCastDataSetTableAdapters.ProfileTableAdapter();
        this.adapter_profile.Fill(this.DataSet.Profile, this.team);

        this.adapter_absence = new ForeCastDataSetTableAdapters.AbwesenheitenTableAdapter();
        this.adapter_absence.Fill(this.DataSet.Abwesenheiten);

        this.adapter_employee = new ForeCastDataSetTableAdapters.MitarbeiterTableAdapter();
        this.adapter_employee.Fill(this.DataSet.Mitarbeiter, this.team, 2018);


        this.adapter_viewmonth = new ForeCastDataSetTableAdapters.MonatsuebersichtTableAdapter();
        ForeCastDataSet.MonatsuebersichtDataTable dt = new ForeCastDataSet.MonatsuebersichtDataTable();
        DateTime date = System.DateTime.Now.AddMonths(1);
        int month = date.Month;
        adapter_viewmonth.Fill(dt, team, month, 2018);

        this.DataSet.Monatsuebersicht.Merge(dt);


        // Abwesenheiten
     //  this.adapter_holiday = new ForeCastDataSetTableAdapters.UrlaubTableAdapter();
      //  this.adapter_holiday.Fill(this.DataSet.Urlaub, this.team, 2018);

    //   this.adapter_organiseAbsence = new ForeCastDataSetTableAdapters.AbwesenheitenplanungTableAdapter();
     //  this.adapter_organiseAbsence.Fill(this.DataSet.Abwesenheitenplanung, DateTime.Now, DateTime.Now.AddDays(25), this.team);




        if (File.Exists(DatabaseFileName))
        {
            // Load the existing database file.
          //  this.DataSet.ReadXml(DatabaseFileName);
            this.DataSet.AcceptChanges();
        }
        else
        {


        }
    }

 public static DatabaseContext Instance
    {
        get
        {
            return instance ?? (instance = new DatabaseContext());
        }
    }

【问题讨论】:

  • 请用英文粘贴您的错误。
  • 或者等我们学德语:D
  • 即使在评论this._DataContext = DatabaseContext.Instance; 之后,你能检查你是否得到错误?
  • 我添加了翻译
  • 嘿弗雷德里克。您应该研究类似实体框架或 dapper 的 orm。实际的数据库连接内容应该在模型类而不是视图模型中。 viewmodel 应该调用 get... 来获取数据列表,然后模型连接到数据库,读取数据并返回列表。

标签: c# wpf xaml mvvm viewmodel


【解决方案1】:

IMO 你有一个设计问题:你不应该在 ViewModel 中有你的 DataContext,ViewModel 是 DataContext。 MVVM 的目的是让 View 和 ViewModel 尽可能地解耦。为了解耦,接口是绝对相关的。

我会做以下事情。作为 ViewModel:

public interface IMainViewModel : IViewModel {}
public interface IViewModel {}
public class MainViewModel : IMainViewModel, INotifyPropertyChanged {}

在 View 的 CodeBehind (MainWindow.xaml.cs) 中:

public interface IView {}
public partial class MainWindow : IView
{
    public IMainViewModel ViewModel
    {
        get { return (IMainViewModel)DataContext; }
        set { DataContext = value; }
    }

    public MainWindow() // for design
    {
        InitializeComponent();
        ViewModel = new MainViewModel();
    }

    public MainWindow(IMainViewModel mainViewModel) // for DI
    {
        InitializeComponent();
        ViewModel = mainViewModel;
    }
}

在 View (MainWindow.xaml) 中,确保在 Window(或任何 View 类型)中有标记:

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:myns="clr-namespace:YOURNAMESPACE"
    d:DataContext="{d:DesignInstance myns:MainViewModel, IsDesignTimeCreatable=True}"

因此,在您进行设计时,您将拥有一个可用于设计的 ViewModel 实例,并且在运行时您也将拥有正确的 ViewModel。因此,您可以调整 ViewModel 的属性以进行设计(例如,使用模拟)并为运行时设置其他值(可能与数据库或其他任何东西有关)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多