.NET 4.0 Breaking Change - Using a Markup Extensio

2019-05-21 14:38发布

In .NET 3.5SP1 I had a style with the following property setting.

<Setter Property="ToolTip" Value="{resource:Resource Group=Text, Key=BTN_CLOSE}"/>

The markup extension will access our satellite assemblies and pull in the proper resource text for the tooltip. The reason this is done this way is our application is customizable. Using the markup extension allows our clients to use a key combination to see the Key for the text and then go modify the text value if they choose to do so.

After upgrading to .NET 4.0 the error below occurs when the above xaml to define the tooltip on my button style is defined. Is there a different way to do this?

System.Windows.Markup.XamlParseException: A 'Binding' cannot be set on the
'Value' property of type 'Setter'. A 'Binding' can only be set on a
DependencyProperty of a DependencyObject.
at System.Windows.Markup.XamlReader.RewrapException(Exception e, Uri baseUri)
at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)
at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlObjectWriter objectWriter)
at System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(DependencyObject container, IComponentConnector componentConnector, IStyleConnector styleConnector, List`1 affectedChildren, UncommonField`1 templatedNonFeChildrenField)
at System.Windows.FrameworkTemplate.LoadContent(DependencyObject container, List`1 affectedChildren)
at System.Windows.StyleHelper.ApplyTemplateContent(UncommonField`1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate)
at System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField`1 templateDataField, FrameworkElement container)
at System.Windows.FrameworkElement.ApplyTemplate()
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Canvas.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Documents.AdornerDecorator.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Border.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Window.MeasureOverrideHelper(Size constraint)
at System.Windows.Window.MeasureOverride(Size availableSize)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Interop.HwndSource.Process_WM_SIZE(UIElement rootUIElement, IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Interop.HwndSource.LayoutFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

I guess I left out a key element. In order to allow the swapping between text and the keys we have a ResourceCache class which stores the values. In the provide value the part that is breaking the tooltip binding is the fact that we are returning binding.ProvideValue(serviceProvider). This is the same as we had it in .NET 3.5SP1.

public override object ProvideValue(IServiceProvider serviceProvider)
{
  ResourceCache resourceCache = ResourceCache.Instance;
  resourceCache["cacheKey"] = "hello";

  Binding binding;

  binding = new Binding();
  binding.Source = resourceCache;
  binding.Path = new PropertyPath("[" + "cacheKey" + "]");
  binding.Mode = BindingMode.OneWay;

  return binding.ProvideValue(serviceProvider);
}

1条回答
登录 后发表回答