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의에서 바인딩 ActualWidthActualHeight의 너비 및 높이 속성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.