2015-10-01 5 views
1

Я вернулся.Как избавиться от ошибки времени проектирования XAML «Ссылка на объект не установлена ​​на экземпляр объекта» при установке datacontext

Я получаю сообщение об ошибке «Ссылка на объект, не установленную на экземпляр объекта» в моем дизайне XAML, когда я добавляю datacontext моей модели времени разработки.

enter image description here

Я пытался отладить с Visual Studio в надежде получить ответы на некоторые вопросы, но ничего не показывает вверх. Все работает нормально, но я не могу полагаться на факт, если есть ошибка или нет.

<Window x:Class="ISynergy.Views.Relations.Editors.ServicingProduct" 
    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:ISynergy.Views.Relations.Editors" 
    xmlns:syncfusion="http://schemas.syncfusion.com/wpf" 
    xmlns:Controls="clr-namespace:ISynergy.Controls;assembly=I-Synergy.Controls" 
    xmlns:Converters="clr-namespace:ISynergy.Controls.Converters;assembly=I-Synergy.Controls" 
    mc:Ignorable="d" 
    Title="ServicingProduct" Width="700" WindowStartupLocation="CenterScreen" 
    xmlns:ViewModels="clr-namespace:ISynergy.Models.Relations.Editors;assembly=I-Synergy.Models" 
    d:DataContext="{d:DesignInstance {x:Type ViewModels:ServicingProduct_ViewModel}, IsDesignTimeCreatable=True}" 
    Style="{DynamicResource StandardDialogWindow}"> 

<Grid Grid.Row="1" syncfusion:SkinStorage.VisualStyle="Metro" syncfusion:SkinStorage.MetroBrush="{DynamicResource Foreground}"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="28" /> 
     <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="125" /> 
     <ColumnDefinition /> 
     <ColumnDefinition Width="30" /> 
     <ColumnDefinition Width="10" /> 
     <ColumnDefinition Width="125" /> 
     <ColumnDefinition /> 
     <ColumnDefinition Width="30" /> 
    </Grid.ColumnDefinitions> 

    <TextBlock Text="Productcode:" VerticalAlignment="Center"/> 
    <TextBlock Text="Artikel:" Grid.Row="4" VerticalAlignment="Center" /> 
    <TextBlock Text="Uitvoering:" Grid.Row="5" VerticalAlignment="Center" /> 
    <TextBlock Text="Merk/Fabrikaat:" Grid.Row="8" VerticalAlignment="Center" /> 
    <TextBlock Text="Type:" Grid.Row="9" VerticalAlignment="Center" /> 
    <TextBlock Text="Serie:" Grid.Row="10" VerticalAlignment="Center" /> 
    <TextBlock Text="Diepte (mm):" Grid.Row="14" VerticalAlignment="Center" /> 
    <TextBlock Text="Breedte (mm):" Grid.Row="15" VerticalAlignment="Center" /> 
    <TextBlock Text="Hoogte (mm):" Grid.Row="16" VerticalAlignment="Center" /> 
    <TextBlock Text="Gewicht (kg):" Grid.Row="17" VerticalAlignment="Center" /> 
    <TextBlock Text="Serienummer:" Grid.Row="9" Grid.Column="4" VerticalAlignment="Center" /> 
    <TextBlock Text="Extra Informatie:" Grid.Row="11" VerticalAlignment="Center" /> 
    <TextBlock Text="Afbeelding:" Grid.Column="4" VerticalAlignment="Center" /> 
    <TextBlock Text="Memo:" Grid.Row="18" VerticalAlignment="Center" /> 
    <TextBlock Text="Ingevoerd door:" Grid.Column="4" Grid.Row="19" Margin="1" VerticalAlignment="Center" /> 
    <TextBlock Text="Laatst gewijzigd door:" Grid.Column="4" Grid.Row="20" Margin="1" VerticalAlignment="Center" /> 
    <TextBox Grid.Column="1" AcceptsTab="True" Grid.Row="18" Margin="1" Grid.RowSpan="3" Name="txtMemo" TextWrapping="WrapWithOverflow" TabIndex="26" AcceptsReturn="True" VerticalContentAlignment="Top" /> 
    <TextBox Grid.Column="1" AcceptsTab="True" Grid.Row="11" Margin="1" Grid.RowSpan="3" Name="txtExtraInfo" TextWrapping="WrapWithOverflow" TabIndex="19" AcceptsReturn="True" VerticalContentAlignment="Top" /> 
    <Border Grid.Column="5" Margin="1" Grid.RowSpan="9" BorderThickness="1" BorderBrush="{DynamicResource BorderBrushNormal}"> 
     <Image Name="pbFoto" /> 
    </Border> 
    <TextBox Grid.Column="5" AcceptsTab="False" Grid.Row="9" Margin="1" Name="txtSerial" TabIndex="18" /> 

    <syncfusion:IntegerTextBox Height="26" Grid.Column="1" Grid.Row="14" Margin="1" Name="txtL" /> 
    <syncfusion:IntegerTextBox Height="26" Grid.Column="1" Grid.Row="15" Margin="1" Name="txtB" /> 
    <syncfusion:IntegerTextBox Height="26" Grid.Column="1" Grid.Row="16" Margin="1" Name="txtH" /> 
    <syncfusion:DoubleTextBox Height="26" NumberDecimalDigits="2" Grid.Column="1" Grid.Row="17" Margin="1" Name="txtW" /> 
    <TextBox Grid.Column="1" AcceptsTab="False" Grid.Row="10" Margin="1" Name="txtSerie" TabIndex="6" MaxLength="48" /> 
    <TextBox Grid.Column="1" AcceptsTab="False" Grid.Row="9" Margin="1" Name="txtModel" TabIndex="5" MaxLength="50" /> 
    <TextBox Grid.Column="1" AcceptsTab="False" Grid.Row="8" Margin="1" Name="txtMerk" TabIndex="4" MaxLength="50" /> 
    <TextBox Grid.Column="1" AcceptsTab="True" Grid.Row="5" Margin="1" Grid.RowSpan="3" Name="txtDescLong" TextWrapping="WrapWithOverflow" TabIndex="3" AcceptsReturn="True" VerticalContentAlignment="Top" /> 
    <TextBox Grid.Column="1" AcceptsTab="False" Grid.Row="4" Margin="1" Name="txtDescShort" TabIndex="2" MaxLength="48" /> 
    <TextBox Grid.Column="1" AcceptsTab="False" Margin="1" Name="txtNummer" CharacterCasing="Upper" TabIndex="1" MaxLength="25" /> 
    <Border> 
     <Image Grid.Column="5" Grid.RowSpan="9" Stretch="Uniform" Margin="1" Name="pbImage" Height="Auto" MaxHeight="220" VerticalAlignment="Center" /> 
    </Border> 
    <Controls:ToolButton Grid.Column="6" Height="26" Width="26" Source="ISynergy.Resources.Assets.Images.tb_search.xaml" Cursor="Hand" Name="cmdBrowse" /> 
    <Controls:ToolButton Grid.Column="2" Grid.Row="11" Name="cmdMergeFields" Source="ISynergy.Resources.Assets.Images.tb_search.xaml" Width="26" Height="26" /> 
    <TextBlock Text="" Grid.Column="5" Grid.Row="19" Name="txtInputFirst" Margin="1" VerticalAlignment="Center" /> 
    <TextBlock Text="" Grid.Column="5" Grid.Row="20" Name="txtInputLast" Margin="1" VerticalAlignment="Center" /> 
    <TextBlock Text="Oppervlakte" Grid.Column="4" Grid.Row="14" Name="lblOppervlakte" VerticalAlignment="Center" /> 
    <TextBlock Text="Volume" Grid.Column="4" Grid.Row="15" Name="lblVolume" VerticalAlignment="Center" /> 
    <TextBlock Text="Dichtheid" Grid.Column="4" Grid.Row="16" Name="lblDichtheid" VerticalAlignment="Center" /> 
    <Controls:ToolButton Name="cmdEditorUitvoering" Grid.Column="2" Grid.Row="5" Source="ISynergy.Resources.Assets.Images.tb_search.xaml" Width="26" Height="26" /> 
    <Controls:ToolButton Name="cmdEditorNotitie" Grid.Column="2" Grid.Row="18" Source="ISynergy.Resources.Assets.Images.tb_search.xaml" Width="26" Height="26" /> 
    <TextBlock Text="Adres:" Grid.Row="1" VerticalAlignment="Center" /> 
    <TextBlock Text="Locatie:" Grid.Row="2" VerticalAlignment="Center" /> 
    <CheckBox Content="Eigen artikel" Grid.Row="3" VerticalAlignment="Center" Name="chkIsArtikel" /> 
    <StackPanel Orientation="Horizontal" Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="4" Margin="0,0,5,0"> 
     <TextBox Margin="1" Name="txtArtikel" CharacterCasing="Upper" Width="100" /> 
     <Controls:ToolButton Height="26" Width="26" Source="ISynergy.Resources.Assets.Images.tb_search.xaml" Cursor="Hand" Name="cmdListArtikel" /> 
     <TextBlock Text="" Name="txtArtikelOmschrijving" /> 
    </StackPanel> 
    <syncfusion:ComboBoxAdv Grid.Column="1" Grid.Row="1" Margin="1" Name="selAdres" /> 
    <syncfusion:ComboBoxAdv Grid.Column="1" Grid.Row="2" Margin="1" Name="selLocatie" /> 
    <TextBlock Text="Staat" Grid.Column="4" Grid.Row="10" VerticalAlignment="Center" /> 
    <syncfusion:ComboBoxAdv Grid.Column="5" Grid.Row="10" Margin="1" Name="selStaat" DisplayMemberPath="Text" SelectedValuePath="Value"/> 
    <CheckBox Content="Leverdatum" Grid.Column="4" Grid.Row="11" VerticalAlignment="Center" Name="chkLeverDatum" /> 
    <DatePicker Grid.Column="5" Grid.Row="11" Width="150" HorizontalAlignment="Left" Margin="1" Name="txtLeverDate" /> 
    <TextBlock Text="Garantie (maanden):" Grid.Column="4" Grid.Row="12" VerticalAlignment="Center" /> 
    <syncfusion:IntegerTextBox Height="26" Grid.Column="5" Grid.Row="12" Margin="1,1,78,1" Name="txtGarantie" /> 
</Grid> 

и это мой ViewModel со всеми унаследованными родителей

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using ISynergy.Entities.Relations; 
using Flurl; 
using Flurl.Http; 
using ISynergy.Common.Types; 
using ISynergy.Library; 

namespace ISynergy.Models.Relations.Editors 
{ 
public class ServicingProduct_ViewModel : Base.Base_Relation_Dialog_ViewModel<ISynergy.Entities.Relations.Servicing_Product> 
{ 
    #region "Properties" 
    public List<ValuedItem> Product_States { get; set; } 

    #endregion 

    #region "Constructors" 
    public ServicingProduct_ViewModel() 
     :base() 
    { 
     Product_States = new List<ValuedItem>(); 

     Item = new Servicing_Product() { Relation_Id = Relation.Relation_Id }; 
     IsNew = true; 

     using (BusyIndicator = new Busy()) 
     { 
      Initialization = InitializeAsync(); 
     } 
    } 

    public ServicingProduct_ViewModel(Servicing_Product e) 
     :this() 
    { 
     Item = e; 
     IsNew = false; 
    } 
    #endregion 

    #region "Initializers" 
    public async override Task InitializeAsync() 
    { 
     await Task.Run(() => 
     { 
      Product_States.Clear(); 
      Product_States.Add(new ValuedItem(0, StringTable.Onbekend)); 
      Product_States.Add(new ValuedItem(1, StringTable.ArtikelStaatNieuw)); 
      Product_States.Add(new ValuedItem(2, StringTable.ArtikelStaatGebruikt)); 
     }); 
    } 
    #endregion 

    #region "Events" 
    public async override Task Submit(Servicing_Product e) 
    { 
     if (IsNew == true) 
     { 
      await new Url(Current.ApiUrl) 
       .AppendPathSegment("servicing_products") 
       .WithBasicAuth(Current.Username, Current.Password) 
       .PostJsonAsync(e); 
     } 
     else 
     { 
      await new Url(Current.ApiUrl) 
       .AppendPathSegment("servicing_products") 
       .WithBasicAuth(Current.Username, Current.Password) 
       .PutJsonAsync(e); 
     } 

     await Item_Changed(); 
     await Close(); 
    } 
    #endregion 
} 
} 

ответ

3

DesignInstance создает реальный экземпляр вашей ViewModel. Это означает, что любой код, выполняемый внутри ctor этого типа, будет запущен в Visual Studio и дизайнере. Невозможно предотвратить это, используя DesignInstance, так как это поведенческое поведение.

Вы можете обойти это несколькими способами.

Во-первых, не делайте никакой работы в своем ctor. Если это невозможно ...

Проверьте, не находитесь ли вы в режиме дизайна до выполнения работы в своем ctor. Это достигается с помощью метода GetIsInDesignMode.

if(System.ComponentModel.DesignerProperties.GetIsInDesignMode(
    new DependencyObject())) 
    return; // short circuit in design mode 
InitializeComponentForRuntimeLol(); 

Некоторые люди имеют аллергию на это по какой-то причине, но если вы не чихаете, это вариант.

Если вы чихаете на этом, последний вариант заключается в создании типов с тем же фасадом, что и ваши виртуальные машины, но в них нет никакого исполняемого кода. Это означает, что у вас будут случайные типы, зависающие вокруг, которые вам не нужны во время выполнения.

Во всяком случае, в настоящее время нет идеального решения. Были призывы к использованию json для определения объектов для использования в привязке к дизайнеру, но я не думаю, что это было сделано в 2015 году:/

+0

Большое спасибо за это - решила проблему превосходно для меня. У меня была модель просмотра времени разработки, которая унаследовала модель просмотра приложения. К сожалению, VM базового класса выполнил некоторую работу, которая не могла быть выполнена во время разработки. Добавление охранника решило проблему. –

0

Ответ Уилла правильный, что ваша проблема вызвана дизайнер пытается запустить ваш viewmodel во время разработки. Позвольте мне предложить альтернативное решение, которое не предполагает создание вашего кода IDE.

Сначала назначьте DataContext в xaml. Я обычно делаю это так, но вариация на ваш метод, вероятно, также работают:

<WindowClass.DataContext> 
    <viewmodels:ViewModel /> 
</WindowClass.DataContext> 

Далее в ViewModel, изолируют собственности инициализаций, которые должны оставаться в конструкторе, от методов, которые населяют свойства с данные. Дизайнер сможет инициализировать все свойства, но не будет полагаться на доступность фактических данных для создания экземпляра класса. Он будет иметь макет так:

public class ViewModel 
{ 
    public ObervableCollection<string> ListOfThings { get; set; } 

    ViewModel() 
    { 
     ListOfThings = new ObservableCollection<string>(); 
    } 

    public void PopulateData() 
    { 
     ListOfThings = DataHelperClass.GetData(); 
    } 
} 

Это позволяет разработчику создать экземпляр класса без необходимости иметь доступ к данным или классам извлечения данных, которые доступны только во время выполнения.

Наконец, мы вызываем метод для заполнения данных из конструктора нашего кода page.xaml.cs. Это гарантирует, что он работает под нагрузкой, но не во время разработки:

public partial class WindowClass : Window 
{ 
    ViewModel vm = (ViewModel)this.DataContext; 
    vm.PopulateData(); 
} 

Если у вас есть несколько элементов управления с их собственным DataContext, вы можете просто назвать их х: Имя, а затем получить их просмотра моделей в код заменив «это» на имя.

Еще одно примечание: Если вы делаете это с помощью WPF UserControl внутри ElementHost внутри формы Windows, как и я, вам нужно поместить вызов для заполнения данных в конструкторе внешней формы. cs, так что дизайнер для формы окон работает. Вы можете сделать это примерно так:

public FormHost() 
{ 
    InitializeComponent(); 
    ViewModel vm = (ViewModel)((System.Windows.Controls.UserControl)elementHost1.Child).DataContext; 
    vm.PopulateData(); 
}