Hi I build a simple test solution in VS 2012 with two projects.
One is a Class library and the other a WPF application.
Both use .NET 4.5.
In the class library I add an EF element (DataFirst) which maps a simple table.
Next I reference this project in my WPF project.
Add EF from Nuget and using a very simple MVVM like pattern I add a class which looks like this (please note - this is not production code - it's just to reproduce the problem).
public class Class1 {
public static Helper TheHelper { get; set; }
public Class1() {
TheHelper = new Helper();
}
}
public class Helper {
public Helper() {
Nam = "aaa";
}
string connectionString = "metadata=res://*/Mod.csdl|res://*/Mod.ssdl|res://*/Mod.msl;provider=System.Data.SqlClient;provider connection string=\";data source=.\\sqlx8r2;initial catalog=FCdata;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework\"";
public string Nam { get; set; }
#region PCs
private List<PC> m_lPCs;
public List<PC> PCs {
get {
if(m_lPCs == null) {
try {
using(FCdataEntities dE = new FCdataEntities(connectionString)) {
m_lPCs = dE.PCs.ToList();
}
}
catch(Exception eX) {
m_lPCs = new List<PC>();
m_lPCs.Add(new PC() { Description = eX.Message });
}
}
return m_lPCs;
}
set {
if(m_lPCs != value) {
m_lPCs = value;
//RaisePropertyChanged(() => PCs);
}
}
}
#endregion
I also extended the context class like this:
public partial class FCdataEntities : DbContext {
public FCdataEntities(string strCon) : base(strCon) {
}
}
So I can pass the connection string which I copy from app.config.
In my main window I do a simple binding like this:
xmlns:local="clr-namespace:EFTest"
Title="MainWindow" Height="350" Width="1525">
<Window.Resources>
<local:Class1 x:Key="dG" />
</Window.Resources>
<Grid DataContext="{Binding Path=TheHelper, Source={StaticResource dG} }">
<Grid.RowDefinitions>
<RowDefinition Height="17*"/>
<RowDefinition Height="143*"/>
</Grid.RowDefinitions>
<TextBox Text="{Binding Nam}" />
<ListBox ItemsSource="{Binding PCs}" Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
The solution works fine at runtime.
But in the VS Designer I get an exception shown in my "dummy obect" which I create in the catch block of the property.
Could not load file or assembly 'Windows, Version=255.255.255.255, Culture=neutral, ContentType=WindowsRuntime' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)
What I need is data at design time - and no "dummy data" - instead I want to get it from the DB - avoiding the use of EF (and use linq2sql for an example) works like a charm.
Did I make a mistake with the connection string (or so) - or is there simply a problem in EF 5.0?
This particular error is a known issue in Entity Framework 5 with the Visual Studio & Expression designers and has been fixed in the Entity Framework 6 source code. However there are other design time errors which I haven't been able to resolve which prevent Entity Framework code from running in the designer.
Related
The markup extension uses the IXamlTypeResolver service to convert a TypeName string to a CLR Type. But in design mode, IServiceProvider does not return this service. Because of this, errors occur in the XAML Editor window and the Designer does not work.
Are there ways to create an IXamlTypeResolver or other ways to convert a TypeName string to a CLR Type?
Maybe there is a possibility to get ITypeDescriptorContext for TypeConverter?
An example of the simplest implementation. Everything except the problem discussed here is excluded from the example.
public class SomeCustomExtension : MarkupExtension
{
public string TypeName { get; set; } = string.Empty;
public SomeCustomExtension(string typeName)
{
TypeName = typeName;
}
public SomeCustomExtension()
{
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (serviceProvider.GetService(typeof(IXamlTypeResolver)) is not IXamlTypeResolver typeResolver)
throw new InvalidOperationException("No service \"IXamlTypeResolver\".");
return typeResolver.Resolve(TypeName);
}
}
<TextBlock Text="{Binding Tag, RelativeSource={RelativeSource Self}, TargetNullValue=null}"
Tag="{local:SomeCustom sys:Double}"/>
Screenshot in Design Mode:
Screenshot in Runtime:
P.S. A practical application uses a much more complex markup extension implementation. And its full work for the Design Mode is important because it greatly facilitates the Development of XAML layout.
I'm currently developing a Visual Studio plugin (VSPackage) which finally should be able to visualize call relations. In order to represent them I want to use the Graph# library which manages the graph (avoiding overlapping edges etc.).
Unfortunately I get the following error message at runtime in my XAML:
XamlParseException: The method or operation is not implemented.
The error pops up on the <graph:CallRelationGraphLayout Graph="{Binding RelationGraph}"/> tag.
<UserControl x:Class="Biocoder.InteractiveExploration.View.ExplorationControl"
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:graphsharp="clr-namespace:GraphSharp.Controls;assembly=GraphSharp.Controls"
xmlns:zoom="clr-namespace:WPFExtensions.Controls;assembly=WPFExtensions"
xmlns:graph="clr-namespace:Biocoder.InteractiveExploration.Graph"
xmlns:viewmodels="clr-namespace:Biocoder.InteractiveExploration.ViewModel"
xmlns:controls="clr-namespace:Biocoder.InteractiveExploration.Controls" mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<viewmodels:ExplorationToolViewModel/>
</UserControl.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<zoom:ZoomControl Grid.Row="1"
Zoom="0.2"
ZoomBoxOpacity="0.5"
Background="Yellow">
<graph:CallRelationGraphLayout Graph="{Binding RelationGraph}"/>
</zoom:ZoomControl>
</Grid>
</UserControl>
I also created own vertex, edge and graph layout classes. My graph should finally represent call relations (edges) between methods (vertices).
MethodVertex.cs
public class MethodVertex
{
public string ID { get; private set; }
public bool IsMale { get; private set; }
public MethodVertex(string id, bool isMale)
{
ID = id;
IsMale = isMale;
}
public override string ToString()
{
return string.Format("{0}-{1}", ID, IsMale);
}
}
RelationEdge.cs
public class RelationEdge : Edge<MethodVertex>
{
public string Id { get; private set; }
public RelationEdge(string id, MethodVertex source, MethodVertex target)
: base(source, target)
{
Id = id;
}
}
CallRelationGraphLayout.cs
public class CallRelationGraphLayout : GraphLayout<MethodVertex, RelationEdge, CallRelationGraph>
{}
CallRelationGraph.cs
public class CallRelationGraph : BidirectionalGraph<MethodVertex, RelationEdge>
{
public CallRelationGraph()
{}
public CallRelationGraph(bool allowParallelEdges)
: base(allowParallelEdges)
{ }
public CallRelationGraph(bool allowParallelEdges, int vertexCapacity)
: base(allowParallelEdges, vertexCapacity)
{}
}
In the ExplorationToolViewModel I declared the RelationGraph as follows:
private CallRelationGraph _relationGraph;
public CallRelationGraph RelationGraph
{
get { return _relationGraph; }
set
{
if (value != _relationGraph)
{
_relationGraph = value;
NotifyPropertyChanged("RelationGraph");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
What I maybe also should mention is that I have the following error displayed sometimes but the project compiles and runs.
GenericArguments[1 ], 'Biocoder.InteractiveExploration.Graph.RelationEdge', on 'GraphSharp.Algorithms.Layout.ILayoutAlgorithm`3[TVertex,TEdge,TGraph]' violates the constraint of type 'TEdge'.
Maybe its the source of the problem but I ignored it so far since it compiled and I did it corresponding to this tutorial.
The strange thing is that it actually works in a normal WPF application using the DLLs provided by Graph#. When I leave the Graph-property out the error doesn't show up so I guess it has to do with the Graph property. Any hints about how to solve this?
Thank you very much in advance!
I've experienced the same issue when using Graph# in a VSPackage. I was able to overcome the issue by not using Bindings for the graph, but by assigning the Graph property in CodeBehind.
This led to an exception that the WPFExtensions assembly could not be loaded when assigning the Graph property. I suspect that the reason for that is that in GraphSharp.Controls, the assembly is used in XAML, but the reference is not added when compiling as there are no references in code. I was able to fix this by adding the following line before assigning the Graph property:
var a = System.Reflection.Assembly.Load("WPFExtensions, Version=1.0.3437.34043, Culture=neutral, PublicKeyToken=null");
This line loads the WPFExtensions library before WPF tries to load it based on the reference in the XAML. Afterwards, the graph was shown.
In my case an assembly wasn't copied to the output folder because copy local was set to false. Setting copy local to true solved it.
(An assembly A was dependent on assembly B which didn't have the copy local flag.)
In the xaml code i get an error telling cannot create an instance of
this AllEmployeeViewModel class file, actually this class file exists in the solution folder when i type scr: the intellsene shows me the class file
<UserControl.Resources>
<scr:AllEmployeeViewModel x:Key="empName"></scr:AllEmployeeViewModel>
</UserControl.Resources>
<Grid x:Name="MainGrid" Background="White" Width="400"
Height="407" DataContext="{Binding Source={StaticResource empName}}" >
<Grid x:Name="grdAllEmp" DataContext="{Binding Path=EmployeeClass}">
<sdk:DataGrid AutoGenerateColumns="True" Height="274"
HorizontalAlignment="Left" Margin="8,8,0,0"
Name="dgEmployee" VerticalAlignment="Top" Width="385"
ItemsSource="{Binding}"/>
<Button Content="Get All Employees" Height="23"
HorizontalAlignment="Left" Margin="12,288,0,0"
Name="btnAllEmplloyees" VerticalAlignment="Top" Width="381"
Command="{Binding Path=DataContext.GetEmployees,ElementName=MainGrid}"/>
</Grid>
i am trying to bind the data to grid, if i ignore the compile time error and run its gives an error key not found.
please let me know the solutionif you know,working on this issue from past 2days
any help would be great
thanks.
I too had the same issue.
cannot create instance of viewmodel
Just copy this code and place it in ViewModel
public bool IsDesignTime
{
get
{
return (Application.Current == null) ||
(Application.Current.GetType() == typeof(Application));
}
}
//Constructor
public ViewModelClass()
{
if(IsDesignTime == false)
{
//Your Code
}
}
Just add this line in MainPage.xaml.cs page
InitializeComponent();
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
//Code that throws the exception
}
it works fine.
Does your class AllEmployeeViewModel have a zero-argument constructor? WIthout that, Silverlight cannot create an instance of your class.
You have a binding to EmployeeClass. That has to be a collection of some type for this to work, but the name EmployeeClass sounds like a single object and not a collection.
You really needed to post your View Model code as we had to guess this.
I put together a quick example and if the ViewModel contains:
public ObservableCollection<EmployeeClass> Employees { get; set; }
and I populate them with a few sample EmployeeClass objects,
public AllEmployeeViewModel()
{
this.Employees = new ObservableCollection<EmployeeClass>();
this.Employees.Add(new EmployeeClass() { Name = "One" });
this.Employees.Add(new EmployeeClass() { Name = "Two" });
and I change the binding to:
<Grid x:Name="grdAllEmp" DataContext="{Binding Path=Employees}">
It looks like this (no other changes):
I was getting the same error, i will explain it to you hopefully it will help you.
In my ViewModel's constructor i was executing some code, all code was withing below if condition except,
If(!IsInDesignMode)
{
// my code
}
// Problamatic method execution point
Except a method that i wanted to execute every time, but it turns out that you can only execute code if above condition is satisfied else your view model instance will not be created.
So to avoid this you have to do like that:
If(!IsInDesignMode)
{
// my code
// Problamatic method execution point
}
Put all your code inside that condition and everything will be fine.
Note: I was using MVVMLight library along with Model-View-ViweModel pattern.
I am having problems getting validation to work properly in the designer for my custom activity. The simplest sample to reproduce the behavior is as follows:
I have a custom WF4 activity with a dynamic collection of arguments stored in a dictionary:
[Designer(typeof(DictionaryActivityDesigner))]
public class DictionaryActivity : NativeActivity
{
[Browsable(false)]
public Dictionary<string, InArgument> Arguments { get; set; }
public InArgument<string> StringArg { get; set; }
public DictionaryActivity()
{
Arguments = new Dictionary<string, InArgument>();
}
protected override void Execute(NativeActivityContext context)
{ }
}
In the designer I dinamically create expression text boxes for editing these arguments. The user has the possibility to define the arguments and their types in a separate modal window, but for the sake of simplicity I have fixed the arguments in this sample:
public partial class DictionaryActivityDesigner
{
private Dictionary<string, Type> definition;
public DictionaryActivityDesigner()
{
definition = new Dictionary<string, Type>
{
{ "String Arg", typeof(string) },
{ "Int Arg", typeof(int) }
};
InitializeComponent();
}
public void InitializeGrid(Dictionary<string, Type> arguments)
{
ArgumentsGrid.RowDefinitions.Clear();
ArgumentsGrid.Children.Clear();
int gridRow = 0;
foreach (var arg in arguments)
{
ArgumentsGrid.RowDefinitions.Add(new RowDefinition());
var label = new Label()
{
Content = arg.Key + ":"
};
Grid.SetRow(label, gridRow);
Grid.SetColumn(label, 0);
ArgumentsGrid.Children.Add(label);
var textbox = new ExpressionTextBox()
{
ExpressionType = arg.Value,
OwnerActivity = ModelItem,
UseLocationExpression = false
};
var binding = new Binding()
{
Mode = BindingMode.TwoWay,
Converter = new ArgumentToExpressionConverter(),
ConverterParameter = "In",
Path = new PropertyPath("ModelItem.Arguments[(0)]", arg.Key)
};
textbox.SetBinding(ExpressionTextBox.ExpressionProperty, binding);
Grid.SetRow(textbox, gridRow);
Grid.SetColumn(textbox, 1);
ArgumentsGrid.Children.Add(textbox);
gridRow++;
}
}
private void ActivityDesigner_Loaded(object sender, RoutedEventArgs e)
{
InitializeGrid(definition);
}
}
Below is the XAML for the designer:
<sap:ActivityDesigner x:Class="ActivityValidation.DictionaryActivityDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
xmlns:sapc="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation"
xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
Loaded="ActivityDesigner_Loaded">
<sap:ActivityDesigner.Resources>
<ResourceDictionary>
<sapc:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter" />
</ResourceDictionary>
</sap:ActivityDesigner.Resources>
<StackPanel Orientation="Vertical">
<Grid Name="ArgumentsGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition MinWidth="250" />
</Grid.ColumnDefinitions>
</Grid>
<sapv:ExpressionTextBox ExpressionType="s:String"
OwnerActivity="{Binding ModelItem}"
Expression="{Binding ModelItem.StringArg, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}" />
</StackPanel>
</sap:ActivityDesigner>
The InitializeGrid method adds the expression text boxes for the arguments to the ArgumentGrid. Under it I have a separate statically defined expression text box for a fixed argument in the activity to demonstrate the (almost) desired behavior.
Now for the problems:
Invalid expressions for the dynamic arguments only cause the error icon to appear beside the text box but it doesn't propagate to the top bar of the designer as it does if there is an error in the statically defined text box.
If I close the designer in such invalid state (and save the definition), the eror icon correctly propagates to the top bar even if the error is only in the dynamic text box. Though the behavior gets even more strange afterwards. After changing the values for the arguments, now even the error icon beside the text box doesn't work consistently any more.
If I delete the contents of a dynamic text box completely, the value in the dictionary gets set to null which manifests in the workflow definition as <x:Null x:Key="String Arg" /> instead of <InArgument x:TypeArguments="x:String" x:Key="String Arg">["a"]</InArgument> or just ommiting the entry as is the case before editing the expression for the first time. If I reopen such a workflow even the statically created text box doesn't work properly any more (the error icon is only visible when text box is focused and it doesn't propagate to the top any more).
It seems obvious that I am doing something wrong when creating the dynamic text boxes. What would be the correct way of doing it? Is there any example available for creating a designer for a custom activity with dynamic number of arguments?
EDIT:
For those interested:
There was some more discussion on MSDN Forums where I have also posted the issue.
As a result of that discussion, I've also filed a report on Microsoft Connect.
I encountered the problem I described here while trying to create a designer for a dynamic collection of arguments in an activity. I managed to work around the problem by using the built-in DynamicArgumentDialog window. I had to restructure my activity to accept a single collection of both input and output arguments:
public Dictionary<string, Argument> Arguments { get; set; }
instead of two separate collections I was using before:
public Dictionary<string, InArgument> InArguments { get; set; }
public Dictionary<string, OutArgument> OutArguments { get; set; }
I found the Custom Activity to Invoke XAML Based Child Workflows very helpful when making this work.
I recently plugged the NHibernate validation into my app, I've decorated the properties of my domain objects with the NHibernate attributes as so ...
[NotEmpty, Length(Min = 1, Max = 40)]
public string Description { get; set; }
I've also implemented IDataErrorInfo on my Domain Object ...
public string this[string columnName]
{
get
{
var result = new ValidatorEngine().Validate(this);
_invalidValues = result.Where(x => x.PropertyName == columnName).Select(x => x.Message);
return _invalidValues.FirstOrDefault();
}
}
public string Error
{
get
{
return string.Empty;
}
}
The XAML looks like this
<TextBox Grid.Row="0" Grid.Column="3" Text="{Binding Path=Entity.Description, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" IsEnabled="{Binding IsEditable}" ></TextBox>
My issue is that when I create a new instance of my Domain object then the validate is not being called, as effectively the properties (such as the Description in my example) have not changed.
I was going to write a method to use reflection and set the properties to what they are already equal to in order to trigger the validate, but this dosnt seem a particularly efficient approach!!
Can someone put me back on track please?
Cheers,
Andy
Paul Stovell for has an excellent article for validation of business objects
http://www.codeproject.com/KB/cs/DelegateBusinessObjects.aspx
It was because the properties were Null and I needed another NHibernate validation decorator to take account of that (NotNullNotEmpty) rather than the NotEmpty I had used.
[NotNullNotEmpty, Length(Min = 1, Max = 40)]
public string Description { get; set; }