An error occurs when specifying a resource with the ViewModel of my class:

<Window x:Class="KTM.TouristsListWnd" 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:KTM" mc:Ignorable="d" Title="TouristsList" Height="388.102" Width="1001.393" Loaded="Window_Loaded"> <Window.DataContext> <!-- ошибка воникает здесь --> <local:TouristsListViewModel /> </Window.DataContext> 

despite the fact that the class is in scope (public)?

 public class TouristsListViewModel 

UPD: class constructor:

 public TouristsListViewModel() { try { conn.Open(); MySqlCommand cmd = new MySqlCommand("SELECT * FROM tourmanager.tourists;", conn); MySqlDataAdapter adp = new MySqlDataAdapter(cmd); DataSet ds = new DataSet(); adp.Fill(ds); foreach (DataRow dr in ds.Tables[0].Rows) { _tourists.Add(new Tourist((int)dr["id"], (string)dr["firstname"], (string)dr["secondname"], (string)dr["patronymic"], (string)dr["passport"], (string)dr["sex"])); } } catch (MySqlException ex) { throw new Exception("", ex); } finally { conn.Close(); } } 
  • And what a mistake? And does your project compile without it? - VladD
  • @VladD yes, it compiles, the error is literally “Object link does not indicate an object instance”. It’s just a blister of eyes, I can’t understand what the catch is. Link to the screenshot: yadi.sk/i/7plMWxYD34KmPn - LukavskyM
  • And if you say the project Rebuild? What does the Output window show? - VladD
  • @VladD Successfully 1, with errors and skipped - 0. No error is collected. - LukavskyM
  • Well, then the error should go. Take a look! - VladD

1 answer 1

The problem is this. The program normally compiles, and in Intellisense (that is, in the visual editor) an error occurs.

The XAML editor attempts to instantiate a TouristsListWnd to draw it. At the same time, he clearly tries to create an instance of TouristsListViewModel , because it is part of XAML. But in the design-time designer, apparently, does not work.

A simple solution is to check if we are running in the designer. To do this, you can use the following structure:

 if (DesignerProperties.GetIsInDesignMode(new DependencyObject())) return; 

at the beginning of the constructor.


Addition: notice that the declaration of properties with their initialization is similar

 public MySqlConnection conn = new MySqlConnection( ConfigurationManager.ConnectionStrings["ConnectionString"].Conne‌​ctionString); 

also, in fact, is part of the constructor, and if we disable it in the designer, we need to transfer this initialization to a point after the check. It turns out this:

 public MySqlConnection conn; public TouristsListViewModel() { if (DesignerProperties.GetIsInDesignMode(new DependencyObject())) return; conn = new MySqlConnection( ConfigurationManager.ConnectionStrings["ConnectionString"].Conne‌​ctionString); ... } 

Notice that it is not good to perform a long operation in the constructor of a VM object - this will slow down the UI thread. Therefore, we try to make reading the table in a separate thread. It turns out something like this:

 public TouristsListViewModel() { LoadData(); } async void LoadData() { InfoLabel.Text = "Loading database..."; try { await Task.Run(() => LoadDataInBackground()); InfoLabel.Text = null; } catch(MySqlException ex) { InfoLabel.Text = "Loading failed, error: " + ex.Message; } } void LoadDataInBackground() { try { conn.Open(); MySqlCommand cmd = new MySqlCommand("SELECT * FROM tourmanager.tourists;", conn); MySqlDataAdapter adp = new MySqlDataAdapter(cmd); DataSet ds = new DataSet(); adp.Fill(ds); foreach (DataRow dr in ds.Tables[0].Rows) { _tourists.Add( new Tourist((int)dr["id"], (string)dr["firstname"], (string)dr["secondname"], (string)dr["patronymic"], (string)dr["passport"], (string)dr["sex"])); } } finally { conn.Close(); } }