Liên kết OneWayToSource từ thuộc tính chỉ đọc trong XAML


87

Tôi đang cố gắng liên kết với một thuộc Readonlytính có OneWayToSourcechế độ as, nhưng có vẻ như điều này không thể thực hiện được trong XAML:

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

Tôi có:

Không thể đặt thuộc tính 'FlagThingy.IsModified' vì nó không có bộ truy cập tập hợp có thể truy cập.

IsModifiedlà chỉ đọc DependencyPropertytrên FlagThingy. Tôi muốn liên kết giá trị đó với thuộc FlagIsModifiedtính trên vùng chứa.

Để rõ ràng:

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

Điều này có thể chỉ bằng cách sử dụng XAML?


Cập nhật: Chà, tôi đã khắc phục trường hợp này bằng cách đặt ràng buộc trên vùng chứa chứ không phải trên FlagThingy. Nhưng tôi vẫn muốn biết liệu điều này có khả thi không.


Nhưng làm thế nào bạn có thể đặt giá trị cho thuộc tính chỉ đọc?
idursun

3
Bạn không thể. Đó cũng không phải là điều tôi đang cố gắng đạt được. Tôi đang cố lấy thuộc tính FROM readonly sang thuộc tính IsModifiedreadwrite FlagIsModified.
Inferis

Câu hỏi hay. Giải pháp của bạn chỉ hoạt động nếu vùng chứa là DependencyObject và FlagIsModified là DependencyProperty.
Josh G

10
Câu hỏi tuyệt vời, tuy nhiên tôi không hiểu câu trả lời được chấp nhận. Tôi sẽ đánh giá cao nếu một số chuyên gia WPF có thể khai sáng thêm cho tôi - Đây là lỗi hay do mỗi thiết kế?
Oskar

@Oskar theo đây là một lỗi. không có sửa chữa trong tầm nhìn mặc dù.
user1151923

Câu trả lời:


46

Một số kết quả nghiên cứu về OneWayToSource ...

Lựa chọn 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);

Lựa chọn 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}" />

Tùy chọn # 3 (Thuộc tính phụ thuộc chỉ đọc đúng)

System.ArgumentException: Thuộc tính 'IsModified' không thể bị ràng buộc dữ liệu.

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

Người phản ánh đưa ra câu trả lời:

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
Thực ra đó là một lỗi.
Inferis

Nghiên cứu tốt đẹp. Nếu bạn không bày ra nó một cách tử tế ở đây, thì tôi cũng đã bước đi trên con đường đau đớn đó. Đồng ý với @Inferis.
kevinarpe

1
Đây có phải là một lỗi? Tại sao liên kết OneWayToSource không được phép với DependencyProperty chỉ đọc?
Alex Hope O'Connor

Đây không phải là một lỗi. Nó được thiết kế và ghi chép đầy đủ. Đó là do cách công cụ ràng buộc hoạt động cùng với hệ thống thuộc tính phụ thuộc (đích ràng buộc phải là một DependencyPropertyDP). DP chỉ đọc chỉ có thể được sửa đổi bằng cách sử dụng liên kết DependencyPropertyKey. Để đăng ký một BindingExpressioncông cụ phải thao tác dữ liệu meta của DP mục tiêu. Vì DependencyPropertyKeyđược coi là riêng tư để đảm bảo bảo vệ ghi công khai, công cụ sẽ phải bỏ qua khóa này với kết quả là không thể đăng ký ràng buộc trên một DP chỉ đọc.
BionicCode

23

Đây là một hạn chế của WPF và nó là do thiết kế. Nó được báo cáo trên Connect tại đây:
ràng buộc OneWayToSource từ thuộc tính phụ thuộc chỉ đọc

Tôi đã thực hiện một giải pháp để có thể đẩy các thuộc tính phụ thuộc chỉ đọc vào nguồn được gọi là nguồn PushBindingmà tôi đã viết blog ở đây . Ví dụ dưới đây thực hiện OneWayToSourceRàng buộc từ các thuộc tính DP chỉ đọc ActualWidthActualHeightđến các thuộc tính Chiều rộng và Chiều cao củaDataContext

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

PushBindinghoạt động bằng cách sử dụng hai Thuộc tính Phụ thuộc, Listener và Mirror. Listener bị ràng buộc OneWayvới TargetProperty và trong PropertyChangedCallbackđó nó cập nhật thuộc tính Mirror được liên kết OneWayToSourcevới bất kỳ thứ gì được chỉ định trong Binding.

Dự án Demo có thể được tải xuống tại đây.
Nó chứa mã nguồn và cách sử dụng mẫu ngắn.


Hấp dẫn! Tôi đã đưa ra một giải pháp tương tự và gọi nó là "Ống dẫn" - Ống dẫn có hai thuộc tính phụ thuộc theo thiết kế của bạn và hai ràng buộc riêng biệt. Trường hợp sử dụng mà tôi có là liên kết các thuộc tính cũ thuần túy với các thuộc tính cũ thuần túy trong XAML.
Daniel Paull

3
Tôi thấy rằng liên kết MS Connect của bạn không hoạt động nữa. Có nghĩa là MS đã sửa nó trong phiên bản .NET mới hơn hay họ vừa xóa nó?
Tiny

@Tiny Connect dường như cuối cùng đã bị bỏ rơi, thật không may. Nó đã được liên kết đến ở nhiều nơi. Tôi không nghĩ rằng nó ngụ ý cụ thể bất cứ điều gì về việc liệu sự cố đã được khắc phục hay chưa,
UuDdLrLrSs

Tôi đã định viết điều chính xác này. Làm tốt lắm!
aaronburro

5

Đã viết cái này:

Sử dụng:

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

Mã:

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

Chưa thử nghiệm nó trong các kiểu và mẫu, hãy đoán nó cần vỏ bọc đặc biệt.


2

Đây là một giải pháp thuộc tính đính kèm khác dựa trên SizeObserver được nêu chi tiết tại đây Đẩy các thuộc tính GUI chỉ đọc trở lại 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);
    }
}

Khai báo thuộc tính đính kèm trong quyền kiểm soát

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

1

Đây là một triển khai khác để liên kết với Xác thực.

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

Cách sử dụng trong 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>

Việc triển khai này cụ thể để ràng buộc Validation.HasError


0

WPF sẽ không sử dụng bộ thiết lập thuộc tính CLR, nhưng có vẻ như nó thực hiện một số xác nhận kỳ lạ dựa trên nó.

Có thể trong tình huống của bạn, điều này có thể ổn:

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

1
Thuộc tính CLR không được sử dụng trong trường hợp này.
Inferis

Có phải ý bạn là bạn vừa xác định DependencyProperty và có thể viết <điều khiển: FlagThingy IsModified = "..." /> không? Đối với tôi, nó nói: "Thuộc tính 'IsModified' không tồn tại trong không gian tên XML" nếu tôi không thêm thuộc tính CLR.
alex2k8

1
Tôi tin rằng thời gian thiết kế sử dụng các thuộc tính clr trong đó thời gian chạy thực sự đi trực tiếp đến thuộc tính phụ thuộc (nếu nó là một).
mandmycode

Thuộc tính CLR là không cần thiết trong trường hợp của tôi (tôi không sử dụng IsModified from code), nhưng nó vẫn ở đó (chỉ với một bộ cài công khai). Cả thời gian chỉ định và thời gian chạy đều hoạt động tốt chỉ với việc đăng ký phụ thuộc.
Inferis

Bản thân ràng buộc không sử dụng thuộc tính CLR, nhưng khi bạn xác định ràng buộc trong XAML, nó phải được dịch thành mã. Tôi đoán trong giai đoạn này trình phân tích cú pháp XAML thấy rằng thuộc tính IsModified là chỉ đọc và ném ngoại lệ (ngay cả trước khi liên kết được tạo).
alex2k8

0

Hmmm ... Tôi không chắc mình đồng ý với bất kỳ giải pháp nào trong số này. Làm thế nào về việc chỉ định một lệnh gọi lại cưỡng chế trong đăng ký thuộc tính của bạn mà bỏ qua thay đổi bên ngoài? Ví dụ: tôi cần triển khai thuộc tính phụ thuộc Vị trí chỉ đọc để có được vị trí của điều khiển MediaElement bên trong điều khiển của người dùng. Đây là cách tôi đã làm điều đó:

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

Nói cách khác, chỉ cần bỏ qua thay đổi và trả về giá trị được hỗ trợ bởi một thành viên khác không có công cụ sửa đổi. - Trong ví dụ trên, MediaRenderer thực sự là điều khiển MediaElement riêng.


Quá tệ, điều này không hoạt động đối với các thuộc tính được xác định trước của các lớp BCL: - /
HOẶC Người lập bản đồ

0

Cách tôi đã giải quyết hạn chế này là chỉ để lộ một thuộc tính Binding trong lớp của mình, giữ cho DependencyProperty ở chế độ riêng tư. Tôi đã triển khai thuộc tính chỉ ghi "PropertyBindingToSource" (thuộc tính này không phải Thuộc tính phụ thuộc) có thể được đặt thành giá trị ràng buộc trong xaml. Trong trình thiết lập cho thuộc tính chỉ ghi này, tôi gọi BindingOperations.SetBinding để liên kết ràng buộc với Thuộc tính phụ thuộc.

Đối với ví dụ cụ thể của OP, nó sẽ như thế này:

Việc triển khai 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;
    }
}

Lưu ý rằng đối tượng DependencyProperty chỉ đọc tĩnh là riêng tư. Trong điều khiển, tôi đã thêm một nút có lần nhấp do Button_Click xử lý. Việc sử dụng điều khiển FlatThingy trong window.xaml của tôi:

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

Lưu ý rằng tôi cũng đã triển khai ViewModel để liên kết với nó không được hiển thị ở đây. Nó cho thấy Thuộc tính phụ thuộc có tên "FlagIsModified" như bạn có thể thu thập từ nguồn ở trên.

Nó hoạt động tuyệt vời, cho phép tôi đẩy thông tin trở lại ViewModel từ View theo cách kết hợp lỏng lẻo, với hướng của luồng thông tin đó được xác định rõ ràng.


-1

Bạn đang thực hiện ràng buộc sai hướng ngay bây giờ. OneWayToSource sẽ thử và cập nhật FlagIsModified trên vùng chứa bất cứ khi nào IsModified thay đổi trên điều khiển bạn đang tạo. Bạn muốn điều ngược lại, đó là có IsModified liên kết với container. FlagIsModified. Vì vậy, bạn nên sử dụng chế độ ràng buộc OneWay

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

Danh sách đầy đủ các thành viên điều tra: http://msdn.microsoft.com/en-us/library/system.windows.data.bindingmode.aspx


5
Không, tôi muốn chính xác kịch bản mà bạn mô tả mà tôi không muốn làm. FlagThingy.IsModified -> containerr.FlagIsModified
Inferis

3
Việc bị đánh dấu bởi vì người hỏi có một câu hỏi lớn có vẻ hơi quá mức cần thiết.
JaredPar

6
@JaredPar: Tôi không thấy có gì mơ hồ về câu hỏi. Câu hỏi nói rằng 1) có một thuộc tính phụ thuộc chỉ đọc IsIsModified, rằng 2) OP muốn khai báo một ràng buộc đối với thuộc tính đó trong XAML và 3) ràng buộc phải hoạt động trong OneWayToSourcechế độ. Giải pháp của bạn không hoạt động trên thực tế bởi vì, như được mô tả trong câu hỏi, trình biên dịch sẽ không cho phép bạn khai báo ràng buộc trên thuộc tính chỉ đọc và nó không hoạt động về mặt khái niệm vì IsModifiedlà chỉ đọc và do đó giá trị của nó không thể thay đổi (bởi ràng buộc).
HOẶC Người lập bản đồ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.