XAML의 읽기 전용 속성에서 OneWayToSource 바인딩


87

as 모드 를 사용하여 Readonly속성 에 바인딩하려고하는데 OneWayToSourceXAML에서 수행 할 수없는 것 같습니다.

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

나는 얻다:

액세스 가능한 집합 접근자가 없으므로 'FlagThingy.IsModified'속성을 설정할 수 없습니다.

IsModified에 대한 읽기 전용 DependencyProperty입니다 FlagThingy. 해당 값을 FlagIsModified컨테이너 의 속성에 바인딩하고 싶습니다 .

확실하게:

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

XAML만으로 가능합니까?


업데이트 : 글쎄, 나는 FlagThingy. 그러나 이것이 가능한지 여전히 알고 싶습니다.


하지만 값을 읽기 전용 속성으로 어떻게 설정할 수 있습니까?
— idursun

3
당신은 할 수 없습니다. 또한 내가 달성하려는 것이 아닙니다. 읽기 전용 속성에서 읽기 IsModified쓰기 속성 을 얻으려고 합니다 FlagIsModified.
— Inferis

좋은 질문. 해결 방법은 컨테이너가 DependencyObject이고 FlagIsModified가 DependencyProperty 인 경우에만 작동합니다.
— Josh G

10
좋은 질문이지만 받아 들인 대답을 이해하지 못했습니다. 일부 WPF 전문가가 저를 좀 더 계몽 해 주시면 감사하겠습니다. 이것은 버그입니까, 아니면 디자인에 따른 것입니까?
— Oskar

에 따라 @Oskar 이 이 버그입니다. 그래도 시야에 수정이 없습니다.
— user1151923

답변:


45

OneWayToSource에 대한 일부 연구 결과 ...

옵션 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);

옵션 # 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}" />

옵션 # 3 (참 읽기 전용 종속성 속성)

System.ArgumentException : 'IsModified'속성은 데이터 바인딩 될 수 없습니다.

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

리플렉터는 다음과 같은 답을 제공합니다.

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

30
사실 그것은 버그입니다.
— Inferis

좋은 연구입니다. 여기에 그렇게 멋지게 배치하지 않았다면 나도 그와 같은 고통스러운 길을 걸었을 것입니다. @Inferis에 동의합니다.
— kevinarpe

1
이것은 버그입니까? 읽기 전용 DependencyProperty에 OneWayToSource 바인딩이 허용되지 않는 이유는 무엇입니까?
— Alex Hope O'Connor

이것은 버그 가 아닙니다 . 그것은 설계 상이며 잘 문서화되어 있습니다. 바인딩 엔진이 종속성 속성 시스템과 함께 작동하는 방식 때문입니다 (바인딩 대상 은DependencyProperty DP 여야 함 ). 읽기 전용 DP는 연결된 DependencyPropertyKey. BindingExpression엔진 을 등록하려면 대상 DP의 메타 데이터를 조작해야합니다. DependencyPropertyKey공개 쓰기 보호를 보장하기 위해 비공개로 간주 되기 때문에 엔진은 읽기 전용 DP에 바인딩을 등록 할 수없는 결과로이 키를 무시해야합니다.
— BionicCode

23

이것은 WPF의 제한 사항이며 의도적으로 설계된 것입니다. Connect에보고됩니다.
. 읽기 전용 종속성 속성의 OneWayToSource 바인딩

나는 해결책을 동적으로 불리는 소스에 읽기 전용 종속성 속성을 밀어 수 있도록 만든 PushBinding내가 여기에 대해 블로그 . 아래의 예는 않습니다 OneWayToSource읽기 전용 DP의에서 바인딩 ActualWidth과 ActualHeight의 너비 및 높이 속성DataContext

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

PushBinding두 개의 종속성 속성, 리스너 및 미러를 사용하여 작동합니다. 리스너는 OneWayTargetProperty에 바인딩 되어 있으며 바인딩 된 PropertyChangedCallbackMirror 속성을 업데이트합니다.OneWayToSource 에 바인딩되어 있으며 바인딩에 지정된 항목에 .

데모 프로젝트는 여기에서 다운로드 할 수 있습니다.
여기에는 소스 코드와 간단한 샘플 사용이 포함되어 있습니다.


흥미 롭군요! 비슷한 솔루션을 생각 해냈고이를 "Conduit"이라고 불렀습니다. Conduit에는 디자인에 따라 두 개의 종속성 속성과 두 개의 개별 바인딩이 있습니다. 내가 가진 사용 사례는 XAML에서 일반 오래된 속성을 일반 오래된 속성에 바인딩하는 것입니다.
— Daniel Paull jul.

3
MS Connect 링크가 더 이상 작동하지 않는 것을 확인했습니다. MS가 최신 버전의 .NET에서 수정했거나 방금 삭제했음을 의미합니까?
— Tiny

불행히도 @Tiny Connect는 결국 포기 된 것 같습니다. 여러 곳에서 연결되었습니다. 나는 그것이 문제가 해결되었는지 여부에 대해 구체적으로 의미하지 않는다고 생각합니다.
— UuDdLrLrSs

나는이 정확한 것을 쓰려고했다. 잘 했어!
— aaronburro

5

이것을 썼다 :

용법:

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

암호:

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

아직 스타일과 템플릿에서 테스트하지 않았으므로 특수 케이스가 필요합니다.


2

여기에 자세히 설명 된 SizeObserver를 기반으로하는 또 다른 연결된 속성 솔루션이 있습니다. 읽기 전용 GUI 속성을 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);
    }
}

컨트롤에서 연결된 속성 선언

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

1

다음은 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);
        }
    }
}

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>

이 구현은 바인딩에만 적용됩니다. Validation.HasError


0

WPF는 CLR 속성 setter를 사용하지 않지만이를 기반으로 이상한 유효성 검사를 수행하는 것 같습니다.

귀하의 상황에있을 수 있습니다. 이것은 괜찮을 수 있습니다.

    public bool IsModified
    {
        get { return (bool)GetValue(IsModifiedProperty); }
        set { throw new Exception("An attempt ot modify Read-Only property"); }
    }

1
이 경우 CLR 속성이 사용되지 않습니다.
— Inferis

방금 DependencyProperty를 정의하고 <controls : FlagThingy IsModified = "..."/>를 작성할 수 있다는 뜻입니까? 나에게 CLR 속성을 추가하지 않으면 " 'IsModified'속성이 XML 네임 스페이스에 존재하지 않습니다."라고 말합니다.
— alex2k8

1
나는 디자인 타임이 clr 속성을 사용한다고 믿으며 런타임이 실제로 종속성 속성 (있는 경우)으로 직접 이동합니다.
— meandmycode 09 년

내 경우에는 CLR 속성이 필요하지 않지만 (코드에서 IsModified를 사용하지 않음) 그럼에도 불구하고 존재합니다 (공용 세터 만 있음). 디자인 타임과 런타임 모두 종속성 속성 등록만으로 잘 작동합니다.
— Inferis

바인딩 자체는 CLR 속성을 사용하지 않지만 XAML에서 바인딩을 정의 할 때 코드로 변환해야합니다. 이 단계에서 XAML 파서가 IsModified 속성이 읽기 전용임을 확인하고 바인딩이 생성되기 전에도 예외를 throw합니다.
— alex2k8

0

흠 ...이 솔루션에 동의하는지 잘 모르겠습니다. 속성 등록에서 외부 변경을 무시하는 강제 콜백을 지정하는 것은 어떻습니까? 예를 들어 사용자 컨트롤 내에서 MediaElement 컨트롤의 위치를 ​​가져 오려면 읽기 전용 Position 종속성 속성을 구현해야했습니다. 내가 한 방법은 다음과 같습니다.

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

즉, 변경 사항을 무시하고 public 한정자가없는 다른 멤버가 지원하는 값을 반환하면됩니다. -위의 예에서 MediaRenderer는 실제로 개인 MediaElement 컨트롤입니다.


안타깝게도 BCL 클래스의 미리 정의 된 속성에는 작동하지 않습니다.-/
— 또는 Mapper

0

이 제한을 해결하는 방법은 DependencyProperty를 모두 비공개로 유지하면서 클래스에 Binding 속성 만 노출하는 것이 었습니다. xaml에서 바인딩 값으로 설정할 수있는 "PropertyBindingToSource"쓰기 전용 속성 (DependencyProperty가 아님)을 구현했습니다. 이 쓰기 전용 속성의 setter에서 BindingOperations.SetBinding을 호출하여 바인딩을 DependencyProperty에 연결합니다.

OP의 특정 예의 경우 다음과 같습니다.

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

정적 읽기 전용 DependencyProperty 개체는 전용입니다. 컨트롤에서 Button_Click에 의해 클릭이 처리되는 버튼을 추가했습니다. 내 window.xaml에서 FlatThingy 컨트롤 사용 :

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

여기에 표시되지 않은 바인딩을 위해 ViewModel도 구현했습니다. 위의 소스에서 수집 할 수있는 "FlagIsModified"라는 DependencyProperty를 노출합니다.

그것은 훌륭하게 작동하여 정보 흐름의 방향이 명시 적으로 정의 된 느슨하게 결합 된 방식으로 View에서 ViewModel로 정보를 다시 푸시 할 수 있습니다.


-1

지금 잘못된 방향으로 바인딩하고 있습니다. OneWayToSource는 만드는 컨트롤에서 IsModified가 변경 될 때마다 컨테이너에서 FlagIsModified를 업데이트하려고 시도합니다. 반대의 경우 IsModified가 container.FlagIsModified에 바인딩되도록합니다. 이를 위해 바인딩 모드 OneWay를 사용해야합니다.

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

열거 형 멤버의 전체 목록 : http://msdn.microsoft.com/en-us/library/system.windows.data.bindingmode.aspx


5
아니, 나는 당신이 설명하고 싶지 않은 시나리오를 정확하게 원합니다. FlagThingy.IsModified -> container.FlagIsModified
— Inferis

3
질문자가 모호한 질문을했기 때문에 점수를 매기는 것은 약간 과잉 인 것 같습니다.
— JaredPar

6
@JaredPar : 질문에 대해 모호한 것이 무엇인지 모르겠습니다. 질문은 1) 읽기 전용 종속성 속성이 IsIsModified있고 2) OP가 XAML에서 해당 속성에 대한 바인딩을 선언하려고하며 3) 바인딩이 OneWayToSource모드 에서 작동해야한다는 것입니다 . 질문에서 설명했듯이 컴파일러는 읽기 전용 속성에 대한 바인딩을 선언 IsModified할 수 없으며 읽기 전용 이므로 개념적으로 작동하지 않으므로 솔루션이 실제로 작동 하지 않습니다. 변경됨 (바인딩에 의해).
— 또는 Mapper
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.