Я знаю, что этот вопрос действительно старый, но недавно я сам столкнулся с этой проблемой, поэтому, возможно, я смогу помочь кому-то еще.
Я хотел создать TextBox, у которого OneWayBinding имеет свойство Text.
Я обнаружил, что это не работает, как показано в вопросе, потому что WPF объединяет существующие метаданные и переопределяющие метаданные вместе, в основном объединяя флаги в OR.
Поскольку BindsTwoWayByDefault является одним из таких флагов, пока один из объектов метаданных имеет BindsTwoWayByDefault = true, он остается истинным.
Единственный способ обойти метаданные после того, как процесс слияния WPF происходит в OverrideMetadata.
Однако объект метаданных помечен как закрытый в методе.
Как любой хороший разработчик, я бы остановился здесь и пересмотрел ...
Надеюсь, я использовал отражение, чтобы "распечатать" объект метаданных и установить для BindsTwoWayByDefault значение true.
Если кто-нибудь знает лучший способ сделать это, пожалуйста, дайте мне знать.
Вот мой код:
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();
}
}