0

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.

Omaer
  • 817
  • 1
  • 7
  • 22
  • I found the following question on SO: http://stackoverflow.com/questions/4106721/internalsvisibleto-is-not-working-for-wpf-application?rq=1 It leaves me without much hope - apparently WPF doesn't care about the "InternalsVisibleTo" attribute. If anyone has workarounds, I'd still like to know. – Omaer Nov 13 '16 at 08:11

3 Answers3

0

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.

Omaer
  • 817
  • 1
  • 7
  • 22
  • 2
    I think they were thinking _"If you're authoring a class library and want to allow 3rd party libraries (like `PresentationFramework`) to access property setters you **should not** make them `internal`"_. – Grx70 Nov 13 '16 at 10:54
  • So... If I read you right, can I use InternalsVisibleTo to give `PresentationFramework` visibility to the `internal` properties? – Omaer Nov 13 '16 at 13:26
  • I don't think so. I'm pretty sure that the requirement for the binding source properties to be public is a design choice rather than a technicality, which even more shows that the class library in question was not designed to be used with `PresentationFramework` directly (or at least it was not thought out well). – Grx70 Nov 13 '16 at 14:10
  • Thank you for the help - just to shed some light on why the class library was designed this way: None of the users of the class library should be able to access the internal properties - except for the "Configuration" GUI. Now, I've been asked to develop this "Configuration GUI" and I decided to use WPF (and of course, to use Data Bindings as well). I'm just disappointed that my use case won't work. If it's a technical limitation, I would find that acceptable - but if you say it's a design decision, I don't see why they would do that... – Omaer Nov 13 '16 at 14:22
  • 1
    I understand the concept. But notice that _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_. What if I devised a framework similar to _WPF_? Would I also be entitled to access the internal members of your library? Of course you can access just about anything using reflection (even private members), but not respecting access modifiers would kind of defeat the point of having them at all. And these are more of a statements describing your code rather than means for technical limitations. – Grx70 Nov 13 '16 at 15:04
  • You make a fair point - but I would expect the framework to respect the "InternalsVisibleTo" attribute - so that if I choose to give your third party framework access to my internals, I can do that. In this case, the binding doesn't work even if I use the InternalsVisibleTo attribute with PresentationFramework. – Omaer Nov 14 '16 at 10:50
0

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;
    };
}
        }
  • As mentioned, in the question, it isn't possible for me to change the property to `public` – Omaer Nov 13 '16 at 10:09
  • Add NEW public wraper property and as iner part of it will be possible to use your internal property – Виталий Белоусов Nov 13 '16 at 10:23
  • Are you suggesting that I inherit from the original class, and then create a NEW property to replace the original, but with public setters? – Omaer Nov 13 '16 at 13:28
  • Yes, this is one workaround, another one is to use reflection in getter of your public property, to get internal property defined in another assembly – Виталий Белоусов Nov 13 '16 at 13:45
  • This would mean creating "Proxy" classes for every single entity type- just to make the properties public... I'm hoping for another solution, but this might be what I end up doing I guess... Thanks for the help, I'll wait for a few days in the hope that someone suggests something easier before accepting your answer. – Omaer Nov 13 '16 at 13:50
0

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()}
};
Abyte0
  • 852
  • 8
  • 9