简体   繁体   English

WPF 双向绑定与内部 setter

[英]WPF two-way binding with internal setter

I'm using WPF's two-way binding on a CLR property, which implements INotifyPropertyChanged.我在实现 INotifyPropertyChanged 的​​ CLR 属性上使用 WPF 的双向绑定。 The set for the property is internal , while the get is public .该属性的setinternal ,而getpublic

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'. System.Windows.Markup.XamlParseException 未处理 消息:PresentationFramework.dll 中发生类型为“System.Windows.Markup.XamlParseException”的未处理异常附加信息:TwoWay 或 OneWayToSource 绑定无法对只读属性“名称”起作用输入“我的类型”。

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.我原以为内部设置器应该可以正常工作...请注意,CLR 类型是在另一个程序集中定义的,并且在当前程序集中可见,具有[assembly: InternalsVisibleTo("MyAssembly")]属性。

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 .声明程序集是一个类库,因此我不能将set更改为public

Oh my... I just found out, WPF bindings don't work with internal properties.哦,我的...我刚刚发现,WPF 绑定不适用于内部属性。 Oh, Microsoft... Whatever were you thinking?哦,微软……你在想什么?


Update:更新:

Here's what I've understood so far (Thank you, @Grx70):这是我到目前为止所了解的(谢谢,@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. WPF 不是 .NET 框架的本机部分,它只是一个“插件”框架,恰好也是由 Microsoft 编写的。 That is why it can't access the internal members of your assembly.这就是它无法访问程序集internal成员的原因。
  • 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.微软本可以允许 WPF 尊重[assembly: InternalsVisibleTo("XXX")]属性,但截至目前,WPF 忽略了它——不幸的是,这并没有留下任何简单的解决方法。 Note: I tested using InternalVisibleTo - both Signed and Unsigned, with PresentationFramework, PresentationCore, and a whole bunch of other DLLs with no luck.注意:我使用InternalVisibleTo - 签名和未签名,以及 PresentationFramework、PresentationCore 和一大堆其他 DLL 进行了测试,但没有运气。
  • 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.这是一个相当大的 PITA(我有很多类,我讨厌创建相同数量的“代理”类所带来的维护噩梦)——所以我可能会考虑使用 PostSharp、或 Fody 或某种织布机来自动- 如果可以的话,创建这些“代理”类。

All the best to anyone else facing this issue.祝其他面临这个问题的人一切顺利。

You can create your own NEW public wraper property and use getter and setter of it to interact with your internal property您可以创建自己的新公共包装器属性并使用它的 getter 和 setter 与您的内部属性进行交互

         internal string _SideTabHeader;

            public string SideTabHeader
            {
                get { return _SideTabHeader; }
                set 
{
    if( value<0)
    {
        do nothing
    }
    else
    {
       _SideTabHeader=value;
    };
}
        }

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如果您的内部属性是 Enum 类型,则跳过

In my case I was trying to do a WPF xaml binding to a property of type inherited from a WCF service.就我而言,我试图将 WPF xaml 绑定到从 WCF 服务继承的类型的属性。 The easy way to solve that simple case was to use int.解决这个简单情况的简单方法是使用 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 . _DeliveryProduct是我对域对象的引用,其属性ProductType是一个枚举,但在我的视图模型中,该属性是一个int ... Note that ProductEnum is autogenerated from the API and can't be changed to public. ... 请注意, ProductEnum是从 API 自动生成的,不能更改为公开。

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()}
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM