System.Reflection.AmbiguousMatchException - wpf

I added Designer support for my control.
I got the following exception when setting the property value like below.
var colStyle = visibleColumn.Properties["PropertyName"].SetValue(Value);
The same above code works fine for VS 2010 project
but it shows the following exception for VS 2008 project
InnerException: System.Reflection.AmbiguousMatchException
Message="Ambiguous match found."
Source="mscorlib"

Just a wild guess, but this may be due to a derived class having a property that is hiding the base class implementation, confusing the reflection mechanism.
If you use GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).SetValue(target, value, null) it may fix the problem.

Related

WPF two-way binding with internal setter

I'm using WPF's two-way binding on a CLR property, which implements INotifyPropertyChanged.
The set for the property is internal, while the get is public.
Unfortunately, I get the following error:
System.Windows.Markup.XamlParseException was unhandled
Message: An unhandled exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll
Additional information: A TwoWay or OneWayToSource binding cannot work on the read-only property 'Name' of type 'MyType'.
Is this the expected behavior? I would have thought that internal setters should work just fine...
Note that the CLR-type is defined in another assembly, and are visible in the current assembly, with the [assembly: InternalsVisibleTo("MyAssembly")] attribute.
Does anyone have workarounds/suggestions? The declaring assembly is a class library, so it's not an option for me to change the set to public.
You can create your own NEW public wraper property and use getter and setter of it to interact with your internal property
internal string _SideTabHeader;
public string SideTabHeader
{
get { return _SideTabHeader; }
set
{
if( value<0)
{
do nothing
}
else
{
_SideTabHeader=value;
};
}
}
Oh my... I just found out, WPF bindings don't work with internal properties. Oh, Microsoft... Whatever were you thinking?
Update:
Here's what I've understood so far (Thank you, #Grx70):
WPF is not a native part of the .NET framework, it's just a "plug-in" framework that happens to be also written by Microsoft. That is why it can't access the internal members of your assembly.
Microsoft could have allowed WPF to respect the [assembly: InternalsVisibleTo("XXX")] attribute, but as of right now, WPF ignores it - which unfortunately does not leave one with any easy workarounds.
Note: I tested using InternalVisibleTo - both Signed and Unsigned, with PresentationFramework, PresentationCore, and a whole bunch of other DLLs with no luck.
The only workaround I can think of right now is to create a "Proxy" class which can expose all required members as public. This is quite a PITA (I have a LOT of classes, and I hate the maintenance nightmare that comes with creating an equal number of "Proxy" classes) - so I might look into using PostSharp, or Fody or some kind of weaver to auto-create these "Proxy" classes if I can.
All the best to anyone else facing this issue.
This is very late and not solving the initial question, but as very related it may help someone else which very similar problem...
If your internal property is of type Enum else skip
In my case I was trying to do a WPF xaml binding to a property of type inherited from a WCF service. The easy way to solve that simple case was to use int.
public Dictionary<int, string> ProductsList => EnumExtensions.ProductsList;
public int ProductType
{
get { return (int)_DeliveryProduct.ProductType; }
set
{
if (value.Equals(ProductType)) return;
_DeliveryProduct.ProductType = (ProductEnum)value;
RaisePropertyChanged(() => ProductType);
}
}
_DeliveryProduct is my reference to my domain object for which the property ProductType is an enum but in my viewmodel that property is an int.
... Note that ProductEnum is autogenerated from the API and can't be changed to public.
internal static Dictionary<int, string> ProductsList => new Dictionary<int, string>
{
{(int)ProductEnum.Regular, ProductEnum.Regular.GetDisplayName()},
{(int)ProductEnum.Intermediate, ProductEnum.Intermediate.GetDisplayName()},
{(int)ProductEnum.Super, ProductEnum.Super.GetDisplayName()},
{(int)ProductEnum.Diesel, ProductEnum.Diesel.GetDisplayName()}
};

Why Can't I Use My DbContext Type?

I'd like to access some static properties of my DbContext type in a WPF Window. I thought I could use the same XAML that I use to refer to individual entities:
<Window.Resources>
<entity:Account x:Key="account"/> //Works fine
<entity:MyEntities x:Key="myEntities"/> //Throws an error!
</Window.Resources>
I get this error:
No connection string named 'MyEntities' could be found in the application config file.
Why is it treating the DbContext type (MyEntities) differently than the Account entity? Is there an easy way I can access the static properties of my MyEntities type?
The syntax you used is for creating instances, not static properties. If you want to access a static property you need to use the x:Static markup extension
<Window.Resources>
<entity:Account x:Key="account" SomeProperty={x:Static entity:MyEntities.MyProperty}/>
</Window.Resources>
The above xaml would be similar to the C# code
var account = new Account()
{
SomeProperty = MyEntities.MyProperty
};
this.Resources["account"] = account;
See that you are calling new Account(), if you called new MyEntites() (like your original example did) you get the error you where getting.
It appears that particular error results due to the static constructor that I placed in my DbContext. When I remove the static constructor the error changes to:
Object reference not set to an instance of an object.
As it turns out, the original error doesn't prevent me from compiling or running my application. I changed my code to use Scott Chamberlain's suggestion (which produces a similar ignorable error) because it is much cleaner and I can access the static properties on the DbContext just fine in spite of Visual Studio's complaints. Thanks, everyone, for the help and suggestions.

WinForms Designer Exception

A WinForms form that includes a UserControl throws an exception when I attempt to display it in design mode, but runs properly when the program is ran or debugged.
The designer says:
The variable 'fpInfoA' is either undeclared or was never assigned.
ResearchTool fMain.Designer.cs Line:282 Column:1
Call Stack
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase.Error(IDesignerSerializationManager manager, String exceptionText, String helpLink)
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeExpression(IDesignerSerializationManager manager, String name, CodeExpression expression)
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeExpression(IDesignerSerializationManager manager, String name, CodeExpression expression)
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeStatement(IDesignerSerializationManager manager, CodeStatement statement)
However, it looks like the variable is assigned as I would expect in InitializeComponent
private void InitializeComponent()
{
// ... (Order of statements is same as in actual code) ...
this.tpFpA = new System.Windows.Forms.TabPage();
this.fpInfoA = new ResearchTool.FPInfo();
// ...
this.tpFpA.Controls.Add(this.fpInfoA); // THIS LINE BLOWS UP IN DESIGN MODE
}
Thoughts on how to track down this issue? For example, is there a way to debug initialization of the designer?
One workaround in case you can't fix the issue, would be to surround the offending bits of code with checks for DesignMode.
As in:
private void InitializeComponent()
{
...
if(!DesignMode)
{
this.fpInfoA = new ResearchTool.FPInfo();
}
...
}
This can also speed it up a little bit if it's doing things that aren't needed in design mode and that are quite slow, like connecting to databases or similar.
As Hans Olsson said, this potentially could be resolved by checking for design-mode and disabling offending logic.
This error will also trigger if there is any issue with the constructor of your UserControl. If there is an exception caused when the designer instantiates your UserControl, the designer will fail. In my case, the failure resulted in the same "[...] is either undeclared or was never assigned" error.
For example, see the following user control:
public class MyUserControl : UserControl {
public MyUserControl()
{
InitializeComponent();
throw new Exception(); //Causes a designer error.
}
}
Now, when observing the designer for a form that contains this MyUserControl, we will see something similar to the following:
I cannot say if the designer is like this for previous versions of Visual Studio; but as for Visual Studio 2017, you can clearly see what happened.
The designer failed because a System.Exception was thrown. As a result, the variable [REDACTED] was thought to be undeclared or never assigned when in fact the auto-generated designer code was correct. The issue was with the MyUserControl's constructor.
Now, if you need to put logic that depends on external services/resources inside the control's constructor, you need to indicate that it should only occur during runtime. Alternatively, you can provide mock-up resources for design-time.
To do this, you can use the LicenseManager and check its current UsageMode.
The modified code below only throws the exception in runtime now, and the designer doesn't have the error anymore.
public class MyUserControl : UserControl {
public MyUserControl()
{
InitializeComponent();
if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
{
throw new Exception(); //No longer fails in design-time.
}
}
}
You will find the information on how to trace design time code execution at:
What information do you need to fix a problem, which occurs with your products at design time?

IronPython: Trouble building a WPF ShaderEffect

I'm trying to build an extensible program where users, among other things, can build their own shader effects.
Google searching got me this far;
class Test(ShaderEffect):
inputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", type(Test()), 0)
But I still get the error;
TypeError: cannot access protected
member
RegisterPixelShaderSamplerProperty
without a python subclass of
ShaderEffect.
Any help would be greatly appreciated.
The best source on the net I could find is linked here
You will need to use Reflection to access protected memeber of .NET class - you don't have a Python subclass where you can access such member directly.
Try somethink like this (I have't tested it):
inputPropertyType = ShaderEffect.GetType().GetMember(
'RegisterPixelShaderSamplerProperty',
BindingFlags.Instance | BindingFlags.NonPublic)
inputProperty = inputPropertyType.GetValue(ShaderEffect, None)
inputProperty("Input", type(Test()), 0)

Embedded IronPython scripts and converting types

I've got a WPF application that embeds IronPython to use as a scripting language. I've got an object model that IronPython scripts can use to do 'stuff'.
However I've come across a strange problem that I've solved in a way that I don't believe is correct.
In my script I want to type the following to set the location of an object in WPF.
map.CanvasLocation = 10,10
This comes up with an exception saying that it cannot convert from PythonTuple to System.Windows.Point.
I've currently solved that using a custom type converter in my c# object, but I'm not sure if this is the best way to do it.
Is there a way to tell IronPython or .Net in general how to convert from one type to another that can be extended at run time?
The way I do this is to use TypeDescriptor to add a type converter attribute to PythonTuple at runtime.
TypeDescriptor.AddAttributes(typeof(PythonTuple),
new TypeConverterAttribute(typeof(Converter)));
Then I use the following code to find the converter in the attribute setter (SetMemberAfter method)
var converter = TypeDescriptor.GetConverter(value);
if (converter.CanConvertTo(destinationType))
{
var destinationValue = converter.ConvertTo(value, destinationType);
return destinationValue;
}
else
{
throw new InvalidOperationException("Cannot convert from {0} to {1}".UIFormat(
value == null ? "null" : value.GetType().Name, destinationType.Name));
}
Why not do a
map.CanvasLocation = Point(10,10)

Resources