OneWayToSource-Bindung von schreibgeschützter Eigenschaft in XAML

85

Ich versuche, Readonlymit OneWayToSourceas mode an eine Eigenschaft zu binden , aber es scheint, dass dies in XAML nicht möglich ist:

<controls:FlagThingy IsModified="{Binding FlagIsModified, 
                                          ElementName=container, 
                                          Mode=OneWayToSource}" />

Ich bekomme:

Die Eigenschaft 'FlagThingy.IsModified' kann nicht festgelegt werden, da sie keinen zugänglichen Set-Accessor hat.

IsModifiedist ein Readonly DependencyPropertyauf FlagThingy. Ich möchte diesen Wert an die FlagIsModifiedEigenschaft im Container binden .

Deutlich sein:

FlagThingy.IsModified --> container.FlagIsModified
------ READONLY -----     ----- READWRITE --------

Ist dies nur mit XAML möglich?


Update: Nun, ich habe diesen Fall behoben, indem ich die Bindung für den Container und nicht für den Container festgelegt habe FlagThingy. Aber ich würde immer noch gerne wissen, ob dies möglich ist.

Inferis
quelle
Aber wie können Sie einen Wert für eine schreibgeschützte Eigenschaft festlegen?
idursun
2
Das kannst du nicht. Es ist auch nicht das, was ich erreichen will. Ich versuche, von der Eigenschaft readonly IsModifiedzur Eigenschaft readwrite zu gelangen FlagIsModified.
Inferis
Gute Frage. Ihre Problemumgehung funktioniert nur, wenn der Container ein DependencyObject und FlagIsModified eine DependencyProperty ist.
Josh G
9
Gute Frage, aber ich verstehe die akzeptierte Antwort nicht. Ich würde mich freuen, wenn ein WPF-Guru mich noch mehr aufklären könnte - Ist das ein Fehler oder ein Entwurf?
Oskar
@ Oskar nach diesem ist es ein Bug. Keine Lösung in Sicht.
user1151923

Antworten:

45

Einige Forschungsergebnisse für OneWayToSource ...

Option 1.

// Control definition
public partial class FlagThingy : UserControl
{
    public static readonly DependencyProperty IsModifiedProperty = 
            DependencyProperty.Register("IsModified", typeof(bool), typeof(FlagThingy), new PropertyMetadata());
}
<controls:FlagThingy x:Name="_flagThingy" />
// Binding Code
Binding binding = new Binding();
binding.Path = new PropertyPath("FlagIsModified");
binding.ElementName = "container";
binding.Mode = BindingMode.OneWayToSource;
_flagThingy.SetBinding(FlagThingy.IsModifiedProperty, binding);

Option 2

// Control definition
public partial class FlagThingy : UserControl
{
    public static readonly DependencyProperty IsModifiedProperty = 
            DependencyProperty.Register("IsModified", typeof(bool), typeof(FlagThingy), new PropertyMetadata());

    public bool IsModified
    {
        get { return (bool)GetValue(IsModifiedProperty); }
        set { throw new Exception("An attempt ot modify Read-Only property"); }
    }
}
<controls:FlagThingy IsModified="{Binding Path=FlagIsModified, 
    ElementName=container, Mode=OneWayToSource}" />

Option 3 (Echte schreibgeschützte Abhängigkeitseigenschaft)

System.ArgumentException: Die Eigenschaft 'IsModified' kann nicht datengebunden werden.

// Control definition
public partial class FlagThingy : UserControl
{
    private static readonly DependencyPropertyKey IsModifiedKey =
        DependencyProperty.RegisterReadOnly("IsModified", typeof(bool), typeof(FlagThingy), new PropertyMetadata());

    public static readonly DependencyProperty IsModifiedProperty = 
        IsModifiedKey.DependencyProperty;
}
<controls:FlagThingy x:Name="_flagThingy" />
// Binding Code
Same binding code...

Reflektor gibt die Antwort:

internal static BindingExpression CreateBindingExpression(DependencyObject d, DependencyProperty dp, Binding binding, BindingExpressionBase parent)
{
    FrameworkPropertyMetadata fwMetaData = dp.GetMetadata(d.DependencyObjectType) as FrameworkPropertyMetadata;
    if (((fwMetaData != null) && !fwMetaData.IsDataBindingAllowed) || dp.ReadOnly)
    {
        throw new ArgumentException(System.Windows.SR.Get(System.Windows.SRID.PropertyNotBindable, new object[] { dp.Name }), "dp");
    }
 ....
alex2k8
quelle
29
Das ist also eigentlich ein Fehler.
Inferis
Gute Forschung. Wenn Sie es hier nicht so schön angelegt hätten, wäre ich denselben schmerzhaften Weg gegangen. Stimmen Sie mit @Inferis überein.
Kevinarpe
1
Ist das ein Fehler? Warum sollte eine OneWayToSource-Bindung mit einer schreibgeschützten DependencyProperty nicht zulässig sein?
Alex Hope O'Connor
Dies ist kein Fehler. Es ist beabsichtigt und gut dokumentiert. Dies liegt an der Funktionsweise der Bindungs-Engine in Verbindung mit dem Abhängigkeitseigenschaftssystem (das Bindungsziel muss ein DependencyPropertyDP sein). Ein schreibgeschützter DP kann nur mit dem zugehörigen geändert werden DependencyPropertyKey. Um eine zu registrieren, muss BindingExpressiondie Engine die Metadaten des Ziel-DP manipulieren. Da dies DependencyPropertyKeyals privat angesehen wird, um den öffentlichen Schreibschutz zu gewährleisten, muss die Engine diesen Schlüssel ignorieren, da die Bindung auf einem schreibgeschützten DP nicht registriert werden kann.
BionicCode
22

Dies ist eine Einschränkung von WPF und beabsichtigt. Hier wird über Connect berichtet:
OneWayToSource-Bindung von einer schreibgeschützten Abhängigkeitseigenschaft

Ich habe eine Lösung gefunden, um schreibgeschützte Abhängigkeitseigenschaften dynamisch an die Quelle zu übertragen, über PushBindingdie ich hier gebloggt habe . Das folgende Beispiel führt OneWayToSourceBindungen von den schreibgeschützten DPs ActualWidthund ActualHeightzu den Eigenschaften Breite und Höhe derDataContext

<TextBlock Name="myTextBlock">
    <pb:PushBindingManager.PushBindings>
        <pb:PushBinding TargetProperty="ActualHeight" Path="Height"/>
        <pb:PushBinding TargetProperty="ActualWidth" Path="Width"/>
    </pb:PushBindingManager.PushBindings>
</TextBlock>

PushBindingfunktioniert mit zwei Abhängigkeitseigenschaften, Listener und Mirror. Der Listener ist an OneWaydie TargetProperty gebunden und PropertyChangedCallbackaktualisiert darin die Mirror-Eigenschaft, die an OneWayToSourcedie in der Bindung angegebenen Werte gebunden ist .

Demo-Projekt kann hier heruntergeladen werden.
Es enthält Quellcode und kurze Beispielnutzung oder besuchen Sie meinen WPF-Blog, wenn Sie an den Implementierungsdetails interessiert sind.

Fredrik Hedblad
quelle
Interessant! Ich habe eine ähnliche Lösung gefunden und sie als "Conduit" bezeichnet - das Conduit hatte zwei Abhängigkeitseigenschaften gemäß Ihrem Design und zwei separate Bindungen. Der Anwendungsfall, den ich hatte, bestand darin, einfache alte Eigenschaften an einfache alte Eigenschaften in XAML zu binden.
Daniel Paull
3
Ich sehe, dass Ihr MS Connect-Link nicht mehr funktioniert. Bedeutet das, dass MS es in einer neueren Version von .NET behoben hat oder es einfach gelöscht hat?
Winzig
@Tiny Connect scheint leider irgendwann aufgegeben worden zu sein. Es war an zahlreichen Stellen verbunden. Ich denke nicht, dass dies speziell darauf hindeutet, ob ein Problem behoben wurde.
UuDdLrLrSs
5

Schrieb dies:

Verwendung:

<TextBox Text="{Binding Text}"
         p:OneWayToSource.Bind="{p:Paths From={x:Static Validation.HasErrorProperty},
                                         To=SomeDataContextProperty}" />

Code:

using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;

public static class OneWayToSource
{
    public static readonly DependencyProperty BindProperty = DependencyProperty.RegisterAttached(
        "Bind",
        typeof(ProxyBinding),
        typeof(OneWayToSource),
        new PropertyMetadata(default(Paths), OnBindChanged));

    public static void SetBind(this UIElement element, ProxyBinding value)
    {
        element.SetValue(BindProperty, value);
    }

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(UIElement))]
    public static ProxyBinding GetBind(this UIElement element)
    {
        return (ProxyBinding)element.GetValue(BindProperty);
    }

    private static void OnBindChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((ProxyBinding)e.OldValue)?.Dispose();
    }

    public class ProxyBinding : DependencyObject, IDisposable
    {
        private static readonly DependencyProperty SourceProxyProperty = DependencyProperty.Register(
            "SourceProxy",
            typeof(object),
            typeof(ProxyBinding),
            new PropertyMetadata(default(object), OnSourceProxyChanged));

        private static readonly DependencyProperty TargetProxyProperty = DependencyProperty.Register(
            "TargetProxy",
            typeof(object),
            typeof(ProxyBinding),
            new PropertyMetadata(default(object)));

        public ProxyBinding(DependencyObject source, DependencyProperty sourceProperty, string targetProperty)
        {
            var sourceBinding = new Binding
            {
                Path = new PropertyPath(sourceProperty),
                Source = source,
                Mode = BindingMode.OneWay,
            };

            BindingOperations.SetBinding(this, SourceProxyProperty, sourceBinding);

            var targetBinding = new Binding()
            {
                Path = new PropertyPath($"{nameof(FrameworkElement.DataContext)}.{targetProperty}"),
                Mode = BindingMode.OneWayToSource,
                Source = source
            };

            BindingOperations.SetBinding(this, TargetProxyProperty, targetBinding);
        }

        public void Dispose()
        {
            BindingOperations.ClearAllBindings(this);
        }

        private static void OnSourceProxyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            d.SetCurrentValue(TargetProxyProperty, e.NewValue);
        }
    }
}

[MarkupExtensionReturnType(typeof(OneWayToSource.ProxyBinding))]
public class Paths : MarkupExtension
{
    public DependencyProperty From { get; set; }

    public string To { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var provideValueTarget = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
        var targetObject = (UIElement)provideValueTarget.TargetObject;
        return new OneWayToSource.ProxyBinding(targetObject, this.From, this.To);
    }
}

Habe es noch nicht in Stilen und Vorlagen getestet, schätze, es braucht ein spezielles Gehäuse.

Johan Larsson
quelle
2

Hier ist eine weitere angehängte Eigenschaftslösung, die auf SizeObserver basiert. Hier wird beschrieben, wie schreibgeschützte GUI-Eigenschaften wieder in ViewModel verschoben werden

public static class MouseObserver
{
    public static readonly DependencyProperty ObserveProperty = DependencyProperty.RegisterAttached(
        "Observe",
        typeof(bool),
        typeof(MouseObserver),
        new FrameworkPropertyMetadata(OnObserveChanged));

    public static readonly DependencyProperty ObservedMouseOverProperty = DependencyProperty.RegisterAttached(
        "ObservedMouseOver",
        typeof(bool),
        typeof(MouseObserver));


    public static bool GetObserve(FrameworkElement frameworkElement)
    {
        return (bool)frameworkElement.GetValue(ObserveProperty);
    }

    public static void SetObserve(FrameworkElement frameworkElement, bool observe)
    {
        frameworkElement.SetValue(ObserveProperty, observe);
    }

    public static bool GetObservedMouseOver(FrameworkElement frameworkElement)
    {
        return (bool)frameworkElement.GetValue(ObservedMouseOverProperty);
    }

    public static void SetObservedMouseOver(FrameworkElement frameworkElement, bool observedMouseOver)
    {
        frameworkElement.SetValue(ObservedMouseOverProperty, observedMouseOver);
    }

    private static void OnObserveChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        var frameworkElement = (FrameworkElement)dependencyObject;
        if ((bool)e.NewValue)
        {
            frameworkElement.MouseEnter += OnFrameworkElementMouseOverChanged;
            frameworkElement.MouseLeave += OnFrameworkElementMouseOverChanged;
            UpdateObservedMouseOverForFrameworkElement(frameworkElement);
        }
        else
        {
            frameworkElement.MouseEnter -= OnFrameworkElementMouseOverChanged;
            frameworkElement.MouseLeave -= OnFrameworkElementMouseOverChanged;
        }
    }

    private static void OnFrameworkElementMouseOverChanged(object sender, MouseEventArgs e)
    {
        UpdateObservedMouseOverForFrameworkElement((FrameworkElement)sender);
    }

    private static void UpdateObservedMouseOverForFrameworkElement(FrameworkElement frameworkElement)
    {
        frameworkElement.SetCurrentValue(ObservedMouseOverProperty, frameworkElement.IsMouseOver);
    }
}

Deklarieren Sie die angehängte Eigenschaft unter Kontrolle

<ListView ItemsSource="{Binding SomeGridItems}"                             
     ut:MouseObserver.Observe="True"
     ut:MouseObserver.ObservedMouseOver="{Binding IsMouseOverGrid, Mode=OneWayToSource}">    
jv_
quelle
1

Hier ist eine weitere Implementierung zum Binden an Validation.HasError

public static class OneWayToSource
{
    public static readonly DependencyProperty BindingsProperty = DependencyProperty.RegisterAttached(
        "Bindings",
        typeof(OneWayToSourceBindings),
        typeof(OneWayToSource),
        new PropertyMetadata(default(OneWayToSourceBindings), OnBinidngsChanged));

    public static void SetBindings(this FrameworkElement element, OneWayToSourceBindings value)
    {
        element.SetValue(BindingsProperty, value);
    }

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(FrameworkElement))]
    public static OneWayToSourceBindings GetBindings(this FrameworkElement element)
    {
        return (OneWayToSourceBindings)element.GetValue(BindingsProperty);
    }

    private static void OnBinidngsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((OneWayToSourceBindings)e.OldValue)?.ClearValue(OneWayToSourceBindings.ElementProperty);
        ((OneWayToSourceBindings)e.NewValue)?.SetValue(OneWayToSourceBindings.ElementProperty, d);
    }
}

public class OneWayToSourceBindings : FrameworkElement
{
    private static readonly PropertyPath DataContextPath = new PropertyPath(nameof(DataContext));
    private static readonly PropertyPath HasErrorPath = new PropertyPath($"({typeof(Validation).Name}.{Validation.HasErrorProperty.Name})");
    public static readonly DependencyProperty HasErrorProperty = DependencyProperty.Register(
        nameof(HasError),
        typeof(bool),
        typeof(OneWayToSourceBindings),
        new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    internal static readonly DependencyProperty ElementProperty = DependencyProperty.Register(
        "Element",
        typeof(UIElement),
        typeof(OneWayToSourceBindings),
        new PropertyMetadata(default(UIElement), OnElementChanged));

    private static readonly DependencyProperty HasErrorProxyProperty = DependencyProperty.RegisterAttached(
        "HasErrorProxy",
        typeof(bool),
        typeof(OneWayToSourceBindings),
        new PropertyMetadata(default(bool), OnHasErrorProxyChanged));

    public bool HasError
    {
        get { return (bool)this.GetValue(HasErrorProperty); }
        set { this.SetValue(HasErrorProperty, value); }
    }

    private static void OnHasErrorProxyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        d.SetCurrentValue(HasErrorProperty, e.NewValue);
    }

    private static void OnElementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue == null)
        {
            BindingOperations.ClearBinding(d, DataContextProperty);
            BindingOperations.ClearBinding(d, HasErrorProxyProperty);
        }
        else
        {
            var dataContextBinding = new Binding
                                         {
                                             Path = DataContextPath,
                                             Mode = BindingMode.OneWay,
                                             Source = e.NewValue
                                         };
            BindingOperations.SetBinding(d, DataContextProperty, dataContextBinding);

            var hasErrorBinding = new Binding
                                      {
                                          Path = HasErrorPath,
                                          Mode = BindingMode.OneWay,
                                          Source = e.NewValue
                                      };
            BindingOperations.SetBinding(d, HasErrorProxyProperty, hasErrorBinding);
        }
    }
}

Verwendung in xaml

<StackPanel>
    <TextBox Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}">
        <local:OneWayToSource.Bindings>
            <local:OneWayToSourceBindings HasError="{Binding HasError}" />
        </local:OneWayToSource.Bindings>
    </TextBox>
    <CheckBox IsChecked="{Binding HasError, Mode=OneWay}" />
</StackPanel>

Diese Implementierung ist bindungsspezifisch Validation.HasError

Johan Larsson
quelle
0

WPF verwendet den CLR-Eigenschaftssetzer nicht, scheint jedoch eine seltsame Validierung basierend darauf durchzuführen.

Möglicherweise ist dies in Ihrer Situation in Ordnung:

    public bool IsModified
    {
        get { return (bool)GetValue(IsModifiedProperty); }
        set { throw new Exception("An attempt ot modify Read-Only property"); }
    }
alex2k8
quelle
1
Die CLR-Eigenschaft wird in diesem Fall nicht verwendet.
Inferis
Meinen Sie damit, dass Sie gerade DependencyProperty definiert haben und <Steuerelemente schreiben konnten: FlagThingy IsModified = "..." />? Für mich heißt es: "Die Eigenschaft 'IsModified' existiert nicht im XML-Namespace", wenn ich keine CLR-Eigenschaft hinzufüge.
Alex2k8
1
Ich glaube, die Entwurfszeit verwendet die clr-Eigenschaften, wobei die Laufzeit tatsächlich direkt zur Abhängigkeitseigenschaft geht (falls es eine ist).
Meandmycode
Die CLR-Eigenschaft ist in meinem Fall nicht erforderlich (ich verwende IsModified nicht aus Code), aber sie ist trotzdem vorhanden (nur mit einem öffentlichen Setter). Sowohl die Entwurfszeit als auch die Laufzeit funktionieren nur mit der Registrierung der abhängigen Eigenschaft einwandfrei.
Inferis
Die Bindung selbst verwendet keine CLR-Eigenschaft, aber wenn Sie die Bindung in XAML definieren, muss sie in Code übersetzt werden. Ich denke, auf dieser Stufe sieht der XAML-Parser, dass die IsModified-Eigenschaft schreibgeschützt ist und eine Ausnahme auslöst (noch bevor die Bindung erstellt wurde).
Alex2k8
0

Hmmm ... Ich bin mir nicht sicher, ob ich mit einer dieser Lösungen einverstanden bin. Wie wäre es, wenn Sie in Ihrer Immobilienregistrierung einen Zwangsrückruf angeben, der externe Änderungen ignoriert? Zum Beispiel musste ich eine schreibgeschützte Positionseigenschaftseigenschaft implementieren, um die Position eines MediaElement-Steuerelements innerhalb eines Benutzersteuerelements abzurufen. So habe ich es gemacht:

    public static readonly DependencyProperty PositionProperty = DependencyProperty.Register("Position", typeof(double), typeof(MediaViewer),
        new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, OnPositionChanged, OnPositionCoerce));

    private static void OnPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var ctrl = d as MediaViewer;
    }

    private static object OnPositionCoerce(DependencyObject d, object value)
    {
        var ctrl = d as MediaViewer;
        var position = ctrl.MediaRenderer.Position.TotalSeconds;

        if (ctrl.MediaRenderer.NaturalDuration.HasTimeSpan == false)
            return 0d;
        else
            return Math.Min(position, ctrl.Duration);
    }

    public double Position
    {
        get { return (double)GetValue(PositionProperty); }
        set { SetValue(PositionProperty, value); }
    }

Mit anderen Worten, ignorieren Sie einfach die Änderung und geben Sie den Wert zurück, der von einem anderen Mitglied ohne öffentlichen Modifikator unterstützt wird. - Im obigen Beispiel ist MediaRenderer das private MediaElement-Steuerelement.

Mario
quelle
Schade, dass dies für vordefinierte Eigenschaften von BCL-Klassen nicht funktioniert: - /
OR Mapper
0

Die Art und Weise, wie ich diese Einschränkung umging, bestand darin, nur eine Bindungseigenschaft in meiner Klasse verfügbar zu machen und die DependencyProperty insgesamt privat zu halten. Ich habe eine schreibgeschützte Eigenschaft "PropertyBindingToSource" implementiert (dies ist keine DependencyProperty), die in der xaml auf einen verbindlichen Wert gesetzt werden kann. Im Setter für diese schreibgeschützte Eigenschaft rufe ich BindingOperations.SetBinding auf, um die Bindung mit der DependencyProperty zu verknüpfen.

Für das spezifische Beispiel des OP würde es so aussehen:

Die FlatThingy-Implementierung:

public partial class FlatThingy : UserControl
{
    public FlatThingy()
    {
        InitializeComponent();
    }

    public Binding IsModifiedBindingToSource
    {
        set
        {
            if (value?.Mode != BindingMode.OneWayToSource)
            {
                throw new InvalidOperationException("IsModifiedBindingToSource must be set to a OneWayToSource binding");
            }

            BindingOperations.SetBinding(this, IsModifiedProperty, value);
        }
    }

    public bool IsModified
    {
        get { return (bool)GetValue(IsModifiedProperty); }
        private set { SetValue(IsModifiedProperty, value); }
    }

    private static readonly DependencyProperty IsModifiedProperty =
        DependencyProperty.Register("IsModified", typeof(bool), typeof(FlatThingy), new PropertyMetadata(false));

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        IsModified = !IsModified;
    }
}

Beachten Sie, dass das statische schreibgeschützte DependencyProperty-Objekt privat ist. Im Steuerelement habe ich eine Schaltfläche hinzugefügt, deren Klick von Button_Click verarbeitet wird. Die Verwendung des FlatThingy-Steuerelements in meiner window.xaml:

<Window x:Class="ReadOnlyBinding.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:ReadOnlyBinding"
    mc:Ignorable="d"
    DataContext="{x:Static local:ViewModel.Instance}"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>

    <TextBlock Text="{Binding FlagIsModified}" Grid.Row="0" />
    <local:FlatThingy IsModifiedBindingToSource="{Binding FlagIsModified, Mode=OneWayToSource}" Grid.Row="1" />
</Grid>

Beachten Sie, dass ich auch ein ViewModel zum Binden implementiert habe, das hier nicht angezeigt wird. Es macht eine DependencyProperty mit dem Namen "FlagIsModified" verfügbar, wie Sie aus der obigen Quelle entnehmen können.

Es funktioniert hervorragend und ermöglicht es mir, Informationen aus der Ansicht lose gekoppelt in das ViewModel zurückzuschieben, wobei die Richtung dieses Informationsflusses explizit definiert ist.

John Thoits
quelle
-1

Sie machen die Bindung gerade in die falsche Richtung. OneWayToSource versucht, FlagIsModified für Container zu aktualisieren, wenn IsModified Änderungen an dem von Ihnen erstellten Steuerelement ändert. Sie möchten das Gegenteil, nämlich IsModified an container.FlagIsModified binden. Dafür sollten Sie den Bindungsmodus OneWay verwenden

<controls:FlagThingy IsModified="{Binding FlagIsModified, 
                                          ElementName=container, 
                                          Mode=OneWay}" />

Vollständige Liste der Aufzählungsmitglieder: http://msdn.microsoft.com/en-us/library/system.windows.data.bindingmode.aspx

JaredPar
quelle
5
Nein, ich möchte genau das Szenario, das Sie beschreiben und das ich nicht tun möchte. FlagThingy.IsModified -> container.FlagIsModified
Inferis
3
Markiert zu werden, weil der Fragesteller eine mehrdeutige Frage hatte, scheint etwas übertrieben.
JaredPar
6
@JaredPar: Ich sehe nicht, was an der Frage nicht eindeutig ist. Die Frage besagt, dass 1) es eine schreibgeschützte Abhängigkeitseigenschaft gibt IsIsModified, dass 2) das OP eine Bindung für diese Eigenschaft in XAML deklarieren möchte und dass 3) die Bindung im OneWayToSourceModus funktionieren soll . Ihre Lösung funktioniert praktisch nicht, da Sie, wie in der Frage beschrieben, vom Compiler keine Bindung für eine schreibgeschützte Eigenschaft deklarieren können, und sie funktioniert konzeptionell nicht, da sie IsModifiedschreibgeschützt ist und ihr Wert daher nicht sein kann geändert (durch die Bindung).
ODER Mapper