Powiązanie OneWayToSource z właściwości tylko do odczytu w języku XAML

88

Próbuję powiązać z Readonlywłaściwością OneWayToSourcew trybie as, ale wydaje się, że nie można tego zrobić w języku XAML:

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

Dostaję:

Nie można ustawić właściwości „FlagThingy.IsModified”, ponieważ nie ma ona dostępnego metody dostępu do zestawu.

IsModifiedjest DependencyPropertywłączony tylko do odczytu FlagThingy. Chcę powiązać tę wartość z FlagIsModifiedwłaściwością kontenera.

Żeby było jasne:

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

Czy jest to możliwe przy użyciu tylko XAML?


Aktualizacja: Cóż, naprawiłem ten przypadek, ustawiając wiązanie w kontenerze, a nie w FlagThingy. Ale nadal chciałbym wiedzieć, czy jest to możliwe.

Inferis
źródło
Ale jak ustawić wartość właściwości tylko do odczytu?
idursun
3
Nie możesz. To też nie jest to, co próbuję osiągnąć. Próbuję uzyskać właściwość FROM readonly IsModifieddo właściwości readwrite FlagIsModified.
Inferis
Dobre pytanie. Obejście działa tylko wtedy, gdy kontener jest DependencyObject, a FlagIsModified jest DependencyProperty.
Josh G
10
Świetne pytanie, ale nie rozumiem zaakceptowanej odpowiedzi. Byłbym wdzięczny, gdyby jakiś guru WPF mógł mnie trochę bardziej oświecić - czy to błąd czy projekt?
Oskar
@Oskar zgodnie z tym jest to błąd. nie widać jednak poprawki.
user1151923

Odpowiedzi:

46

Niektóre wyniki badań dla OneWayToSource ...

Opcja 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);

Opcja 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}" />

Opcja nr 3 (prawdziwa właściwość zależności tylko do odczytu)

System.ArgumentException: Właściwość „IsModified” nie może być powiązana z danymi.

// 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...

Reflector daje odpowiedź:

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
źródło
30
Więc to właściwie błąd.
Inferis
Niezłe badania. Gdybyś nie ułożył tego tak ładnie tutaj, poszedłbym tą samą, bolesną ścieżką. Zgadzam się z @Inferis.
kevinarpe
1
Czy to błąd? Dlaczego powiązanie OneWayToSource nie byłoby dozwolone z DependencyProperty tylko do odczytu?
Alex Hope O'Connor,
To nie jest błąd. Jest to zgodne z projektem i dobrze udokumentowane. Dzieje się tak ze względu na sposób, w jaki silnik powiązań działa w połączeniu z systemem właściwości zależności (celem powiązania musi być DependencyPropertyDP). DP tylko do odczytu można modyfikować tylko przy użyciu skojarzonego pliku DependencyPropertyKey. Aby zarejestrować BindingExpressionsilnik, musi manipulować metadanymi docelowego DP. Ponieważ DependencyPropertyKeyjest uważany za prywatny, aby zagwarantować publiczną ochronę przed zapisem, silnik będzie musiał zignorować ten klucz, co spowoduje brak możliwości zarejestrowania powiązania na DP tylko do odczytu.
BionicCode
23

Jest to ograniczenie WPF i jest zgodne z projektem. Jest zgłaszany w Connect here:
OneWayToSource z właściwości zależności tylko do odczytu

Stworzyłem rozwiązanie, aby dynamicznie móc przesyłać właściwości zależności tylko do odczytu do źródła o nazwie, o PushBindingktórym pisałem tutaj na blogu . Poniższy przykład robi OneWayToSourceWiązania z tylko do odczytu DP ActualWidthi ActualHeightna szerokość i wysokość właściwościDataContext

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

PushBindingdziała przy użyciu dwóch właściwości zależności: Listener i Mirror. Listener jest powiązany OneWayz TargetProperty i PropertyChangedCallbackaktualizuje właściwość Mirror, która jest powiązana OneWayToSourcez tym, co określono w Binding.

Projekt demonstracyjny można pobrać tutaj.
Zawiera kod źródłowy i krótkie przykłady użycia.

Fredrik Hedblad
źródło
Ciekawy! Wymyśliłem podobne rozwiązanie i nazwałem je „Conduit” - przewód miał dwie właściwości zależności, zgodnie z Twoim projektem i dwa oddzielne powiązania. Przypadek użycia, który miałem, wiązał zwykłe stare właściwości ze zwykłymi starymi właściwościami w XAML.
Daniel Paull,
3
Widzę, że twoje łącze MS Connect już nie działa. Czy to oznacza, że ​​MS naprawiło to w nowszej wersji .NET, czy po prostu go usunęło?
Mały
Wygląda na to, że @Tiny Connect zostało niestety porzucone. W wielu miejscach był powiązany. Nie sądzę, żeby to konkretnie wskazywało na to, czy problem został rozwiązany.
UuDdLrLrSs
5

Napisał to:

Stosowanie:

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

Kod:

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);
    }
}

Nie testowałem go jeszcze w stylach i szablonach, myślę, że wymaga specjalnej obudowy.

Johan Larsson
źródło
2

Oto kolejne dołączone rozwiązanie właściwości oparte na SizeObserver opisane tutaj Przekazywanie właściwości GUI tylko do odczytu z powrotem do ViewModel

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);
    }
}

Zadeklaruj dołączoną właściwość w kontroli

<ListView ItemsSource="{Binding SomeGridItems}"                             
     ut:MouseObserver.Observe="True"
     ut:MouseObserver.ObservedMouseOver="{Binding IsMouseOverGrid, Mode=OneWayToSource}">    
jv_
źródło
1

Oto kolejna implementacja powiązania z 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);
        }
    }
}

Wykorzystanie w 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>

Ta implementacja jest specyficzna dla wiązania Validation.HasError

Johan Larsson
źródło
0

WPF nie będzie używać metody ustawiającej właściwości CLR, ale wydaje się, że na jej podstawie przeprowadza pewne dziwne sprawdzanie poprawności.

Może być w Twojej sytuacji, tak może być w porządku:

    public bool IsModified
    {
        get { return (bool)GetValue(IsModifiedProperty); }
        set { throw new Exception("An attempt ot modify Read-Only property"); }
    }
alex2k8
źródło
1
W tym przypadku właściwość CLR nie jest używana.
Inferis
Czy masz na myśli, że właśnie zdefiniowałeś DependencyProperty i mogłeś napisać <controls: FlagThingy IsModified = "..." />? Dla mnie to mówi: „Właściwość„ IsModified ”nie istnieje w przestrzeni nazw XML”, jeśli nie dodam właściwości CLR.
alex2k8
1
Uważam, że czas projektowania wykorzystuje właściwości clr, gdzie jako środowisko uruchomieniowe faktycznie przechodzi bezpośrednio do właściwości zależności (jeśli jest jedną).
meandmycode
Właściwość CLR jest niepotrzebna w moim przypadku (nie używam IsModified z kodu), ale mimo to istnieje (tylko z publicznym ustawiaczem). Zarówno czas projektowania, jak i środowisko wykonawcze działają dobrze z samą rejestracją właściwości zależności.
Inferis
Samo powiązanie nie używa właściwości CLR, ale podczas definiowania powiązania w języku XAML należy je przetłumaczyć na kod. Myślę, że na tym etapie analizator składni XAML widzi, że właściwość IsModified jest tylko do odczytu i zgłasza wyjątek (nawet przed utworzeniem powiązania).
alex2k8
0

Hmmm ... Nie jestem pewien, czy zgadzam się z którymkolwiek z tych rozwiązań. Co powiesz na określenie wymuszonego wywołania zwrotnego w rejestracji usługi, który ignoruje zewnętrzną zmianę? Na przykład musiałem zaimplementować właściwość zależności Position tylko do odczytu, aby uzyskać pozycję kontrolki MediaElement w kontrolce użytkownika. Oto jak to zrobiłem:

    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); }
    }

Innymi słowy, po prostu zignoruj ​​zmianę i zwróć wartość obsługiwaną przez innego członka, który nie ma modyfikatora public. - W powyższym przykładzie MediaRenderer jest w rzeczywistości prywatną kontrolką MediaElement.

Mario
źródło
Szkoda, że ​​to nie działa w przypadku wstępnie zdefiniowanych właściwości klas BCL: - /
LUB Mapper
0

Sposób obejścia tego ograniczenia polegał na ujawnieniu tylko właściwości Binding w mojej klasie, zachowując całkowicie prywatność DependencyProperty. Zaimplementowałem właściwość tylko do zapisu „PropertyBindingToSource” (ta nie jest DependencyProperty), którą można ustawić na wartość powiązania w xaml. W programie ustawiającym dla tej właściwości tylko do zapisu wywołuję BindingOperations.SetBinding, aby połączyć powiązanie z DependencyProperty.

W przypadku konkretnego przykładu PO wyglądałoby to następująco:

Implementacja FlatThingy:

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;
    }
}

Zwróć uwagę, że statyczny obiekt DependencyProperty tylko do odczytu jest prywatny. W kontrolce dodałem przycisk, którego kliknięcie jest obsługiwane przez Button_Click. Użycie kontrolki FlatThingy w moim 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>

Zauważ, że zaimplementowałem również ViewModel do powiązania z tym, który nie jest tutaj pokazany. Udostępnia właściwość DependencyProperty o nazwie „FlagIsModified”, jak można uzyskać z powyższego źródła.

Działa świetnie, pozwalając mi wypychać informacje z powrotem do ViewModel z widoku w luźno powiązany sposób, z wyraźnie zdefiniowanym kierunkiem przepływu informacji.

John Thoits
źródło
-1

Robisz teraz wiązanie w złym kierunku. OneWayToSource spróbuje zaktualizować FlagIsModified w kontenerze za każdym razem, gdy IsModified zmieni się w tworzonej kontrolce. Chcesz czegoś przeciwnego, czyli powiązania IsModified z container.FlagIsModified. W tym celu należy użyć trybu powiązania OneWay

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

Pełna lista członków wyliczenia: http://msdn.microsoft.com/en-us/library/system.windows.data.bindingmode.aspx

JaredPar
źródło
5
Nie, chcę dokładnie tego scenariusza, który opisałeś, a którego nie chcę robić. FlagThingy.IsModified -> container.FlagIsModified
Inferis
3
Zostanie oznaczonym z powodu niejednoznacznego pytania pytającego wydaje się nieco przesadą.
JaredPar
6
@JaredPar: Nie rozumiem, co jest niejednoznaczne w tym pytaniu. Pytanie stwierdza, że ​​1) istnieje właściwość zależności tylko do odczytu IsIsModified, 2) OP chce zadeklarować powiązanie tej właściwości w XAML i 3) powiązanie powinno działać w OneWayToSourcetrybie. Twoje rozwiązanie nie działa praktycznie, ponieważ, jak opisano w pytaniu, kompilator nie pozwoli ci zadeklarować powiązania dla właściwości tylko do odczytu i nie działa koncepcyjnie, ponieważ IsModifiedjest tylko do odczytu, a zatem jego wartość nie może być zmieniony (przez oprawę).
LUB Mapper