Я хотел создать текстовое поле только для чтения, которое имеет свойство OneWay Binding по умолчанию в свойстве Text. Как в very similar question моей первой попытки был такой:Переопределение DefaultTwoWayByDefault в FrameworkPropertyMetadata
public partial class SelectableTextBlock : TextBox
{
static SelectableTextBlock()
{
TextBox.TextProperty.OverrideMetadata(typeof(ReadOnlyTextBox),
new FrameworkPropertyMetadata() { BindsTwoWayByDefault = false, Journal = true, DefaultUpdateSourceTrigger = UpdateSourceTrigger.Explicit });
}
public SelectableTextBlock()
{
InitializeComponent();
}
}
я обнаружил, что это не работает, потому что WPF объединяет существующие метаданные и первостепенные метаданные по существу ORing всех флагов вместе. Поскольку BindsTwoWayByDefault является одним из этих флагов, пока один из объектов метаданных имеет BindsTwoWayByDefault = true, остается true.
Единственный способ изменить метаданные после того, как процесс объединения WPF занимает место в OverrideMetadata. Однако объект Metadata отмечен как запечатанный в методе.
Как любой хороший разработчик, я бы остановился здесь и передумал ... Нааа, я использовал отражение, чтобы «распечатать» объект метаданных и вернуть BindsTwoWayByDefault в true.
Пожалуйста, скажите мне, что я глуп и не вижу очевидного и правильного способа сделать это в WPF.
Вот мой код:
public partial class SelectableTextBlock : TextBox
{
static SelectableTextBlock()
{
var defaultMetadata = (FrameworkPropertyMetadata)TextProperty.GetMetadata(typeof(TextBox));
var newMetadata = new FrameworkPropertyMetadata(
defaultMetadata.DefaultValue,
FrameworkPropertyMetadataOptions.Journal,
defaultMetadata.PropertyChangedCallback,
defaultMetadata.CoerceValueCallback,
defaultMetadata.IsAnimationProhibited,
defaultMetadata.DefaultUpdateSourceTrigger);
TextProperty.OverrideMetadata(typeof(SelectableTextBlock), newMetadata);
//Workaround for a bug in WPF were the Metadata is merged wrongly and BindsTwoWayByDefault is always true
var sealedProperty = typeof(PropertyMetadata).GetProperty("Sealed", BindingFlags.Instance | BindingFlags.NonPublic);
sealedProperty.SetValue(newMetadata, false);
newMetadata.BindsTwoWayByDefault = false;
sealedProperty.SetValue(newMetadata, true);
}
public SelectableTextBlock()
{
InitializeComponent();
}
}
Действительно ли это цель сделать это инструкцией по коду? Я бы лучше определил стиль вашего дела и применил его по типу во всем содержимом вашей формы, если он соответствует вашим требованиям. –
Я не уверен, что полностью понимаю, что вы имеете в виду. Но установка режима привязки по умолчанию для DependencyProperty может выполняться только в коде, а не в стиле. – Bluuu
То, что он, вероятно, имел в виду, это игнорировать значение по умолчанию и каждый раз устанавливать его в OneWay, когда вам это нужно, чтобы избежать головной боли. – nkoniishvt