У меня есть пользовательские расширения разметки «ThemeExtension» для предоставления «SolidColorBrush» из моего DefaultTheme.xaml ResourceDictionary.
Пример вызова: BorderBrush="{extensions:Theme Key= FooKeyValue}"
Он работает без проблем во время выполнения, но ИНОГДА он начинает падать во время проектирования, и я больше не могу разрабатывать.Дизайнер разбился.Перестройте, Чистое решение, перезагрузка ОС больше не помогает.Если я изменю какое-то значение внутри кода XAML, оно будет работать ровно для одного рисунка!И после этого снова происходит сбой!
Предварительный просмотр
XAML Stacktrace
bei System.Windows.Setter.Seal()
bei System.Windows.SetterBaseCollection.Seal()
bei System.Windows.Style.Seal()
bei System.Windows.StyleHelper.UpdateStyleCache(FrameworkElement fe, FrameworkContentElement fce, Style oldStyle, Style newStyle, Style& styleCache)
bei System.Windows.FrameworkElement.OnStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
bei System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
bei System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
bei System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
bei System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
bei System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue)
bei System.Windows.FrameworkElement.UpdateStyleProperty()
bei System.Windows.FrameworkElement.OnInitialized(EventArgs e)
bei System.Windows.Controls.Primitives.Selector.OnInitialized(EventArgs e)
bei System.Windows.FrameworkElement.TryFireInitialized()
bei System.Windows.FrameworkElement.EndInit()
bei System.Windows.Controls.ItemsControl.EndInit()
bei MS.Internal.Xaml.Runtime.ClrObjectRuntime.InitializationGuard(XamlType xamlType, Object obj, Boolean begin)
ThemeExtension.cs
[MarkupExtensionReturnType(typeof(Color))]
public class ThemeColorExtension : ThemeExtension
{
internal override object ModifyThemeValue(object value)
{
if (value is SolidColorBrush solidColorBrush)
return solidColorBrush.Color;
return value;
}
}
[MarkupExtensionReturnType(typeof(SolidColorBrush))]
public class ThemeExtension : MarkupExtension
{
// ##############################################################################################################################
// Properties
// ##############################################################################################################################
#region Properties
// ##########################################################################################
// Public Properties
// ##########################################################################################
/// <summary>
/// The Key in the Resource Theme file
/// </summary>
public string Key { get; set; }
// ##########################################################################################
// Private Properties
// ##########################################################################################
private static readonly List<ThemeExtension> _Cache = new List<ThemeExtension>();
private static readonly ResourceDictionary _DefaultTheme;
private static ResourceDictionary _CurrentTheme;
private PropertyInfo _Property { get; set; }
private DependencyProperty _DependencyProperty { get; set; }
private WeakReference _TargetReference { get; set; }
#endregion
// ##############################################################################################################################
// Constructor
// ##############################################################################################################################
#region Constructor
static ThemeExtension()
{
_DefaultTheme = new ResourceDictionary
{
Source = new Uri("/HtPlcFramework;component/Themes/DefaultTheme.xaml", UriKind.Relative)
};
_CurrentTheme = _DefaultTheme;
NavigationService.Navigated += _OnNavigated;
}
public ThemeExtension() { }
#endregion
// ##############################################################################################################################
// public methods
// ##############################################################################################################################
#region public methods
/// <summary>
/// https://social.msdn.microsoft.com/Forums/vstudio/en-US/931d7bff-90b6-4a70-bb0b-3a097e1301a1/net-40-breaking-change-using-a-markup-extension-as-value-of-property-setter-in-xaml-style?forum=wpf
/// </summary>
/// <param name="serviceProvider"></param>
/// <returns></returns>
public override object ProvideValue(IServiceProvider serviceProvider)
{
IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (target == null)
return this;
if (target.TargetObject != null && target.TargetProperty != null)
{
_TargetReference = new WeakReference(target.TargetObject);
if (target.TargetProperty.GetType() == typeof(PropertyInfo))
{
_Property = (PropertyInfo)target.TargetProperty;
}
else if (target.TargetProperty is DependencyProperty)
{
_DependencyProperty = (DependencyProperty)target.TargetProperty;
}
}
if (!_Cache.Contains(this))
_Cache.Add(this);
return ModifyThemeValue(_ReadThemeKey(Key));
}
/// <summary>
/// Change the Theme set
/// </summary>
/// <param name="themeUri">Default is: new Uri("/HtPlcFramework;component/Themes/DefaultTheme.xaml", UriKind.Relative)</param>
public static void ChangeTheme(Uri themeUri)
{
_CurrentTheme = new ResourceDictionary { Source = themeUri };
foreach (ThemeExtension reference in _Cache)
{
reference._UpdateTheme();
}
}
/// <summary>
/// Get the current theme entry. Can be null!
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static object ReadThemeKey(string key) => _ReadThemeKey(key);
internal virtual object ModifyThemeValue(object value)
{
return value;
}
#endregion
// ##############################################################################################################################
// private methods
// ##############################################################################################################################
#region private methods
private static void _OnNavigated(object sender, string layer)
{
_Cache.RemoveAll(ti => !ti._TargetReference.IsAlive);
}
private static object _ReadThemeKey(string key)
{
try
{
return _CurrentTheme[key] ?? _DefaultTheme[key];
}
catch (Exception)
{
Trace.WriteLine($"The key '{key}' was not found in {_CurrentTheme.Source}!");
return null;
}
}
private void _UpdateTheme()
{
if (_TargetReference.IsAlive)
{
if (_Property != null)
_Property.GetSetMethod().Invoke(_TargetReference.Target, new object[] { _ReadThemeKey(Key) });
else if (_DependencyProperty != null)
{
DependencyObject dependencyObject = _TargetReference.Target as DependencyObject;
dependencyObject?.SetValue(_DependencyProperty, _ReadThemeKey(Key));
}
}
else
{
_Cache.Remove(this);
}
}
#endregion
}
Связанное сообщение сообщества разработчиков VStudio
https://developercommunity.visualstudio.com/content/problem/364029/foomarkupextension-is-not-valid-for-settervalue-th.html
Связанное сообщение без решения
{0} недопустимо для Setter.Значение.Единственными поддерживаемыми типами MarkupExtension являются DynamicResourceExtension и BindingBase или производные типы
VS2010 Custom MarkupExtension
На следующем веб-сайте приведен пример «Разметка»Расширение ":
https://dzone.com/articles/extend-wpf-add-your-own-keywor (Загрузить пример проекта http://raasiel.typepad.com/MyXamlExtensions.zip)
Если я запусту этот пример, я получу также это исключение, вызывающее раздражение! Так что, возможно, это проблема VisualStudio.