0
votes

I implement a small WPF application by using a MVVM pattern. After I've setting the Datacontext in view.xaml. I got the following error.

XAML Parse Exception

XAML-Code

<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>

My ViewModel

  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

}

}

The code of the Databasecontext class. The Exception is the same one. It threw after filling the table employee with the 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());
        }
    }
1
Kindly paste your error in english.Gaurang Dave
or wait for us to learn German :DMuds
can you check you get error even after commenting this._DataContext = DatabaseContext.Instance; ?rahulaga_dev
i added a translationFrederik.Wagener
Hey Frederick. You should look into an orm like entity framework or dapper. The actual database connection stuff should be in a model class rather than viewmodel. The viewmodel should call get... to just get a list of data and the model connects to the database, reads the data and returns the list.Andy

1 Answers

1
votes

IMO you have a design problem: you shouln't have your DataContext in the ViewModel, ViewModel is DataContext. The purpose of MVVM is to have View and ViewModel as decoupled as possible. For the sake of decoupling, interfaces are absolutely relevant.

I would do the following. As ViewModel:

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

In CodeBehind (MainWindow.xaml.cs) of the View:

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;
    }
}

and in the View (MainWindow.xaml), make sure to have in the Window (or any View type) markup:

    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}"

As such you'll have an instance of your ViewModel available for your design as you work on the design, and you'll have also the proper ViewModel as you run. You can hence tune properties of your ViewModel for design (eg., with mocking) and have other values (maybe with a connexion to database or anything) for runtime.