OneWayToSource एक्सएएमएल में आसानी से संपत्ति से बाध्यकारी


88

मैं एक Readonlyसंपत्ति OneWayToSourceको मोड के साथ बांधने की कोशिश कर रहा हूं , लेकिन ऐसा लगता है कि यह XAML में नहीं किया जा सकता है:

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

मुझे मिला:

संपत्ति 'FlagThingy.IsModified' सेट नहीं की जा सकती क्योंकि इसमें एक सुलभ सेट एक्सेसर नहीं है।

IsModifiedपर एक पठनीय DependencyPropertyहै FlagThingy। मैं उस मूल्य को FlagIsModifiedकंटेनर पर बांधना चाहता हूं ।

स्पष्ट होना:

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

क्या यह सिर्फ एक्सएएमएल का उपयोग करना संभव है?


अद्यतन: ठीक है, मैंने इस मामले को कंटेनर पर बाइंडिंग सेट करके तय किया है और इस पर नहीं FlagThingy। लेकिन मैं अभी भी जानना चाहूंगा कि क्या यह संभव है।


लेकिन आप केवल पढ़ी गई संपत्ति के लिए मूल्य कैसे निर्धारित कर सकते हैं?
इडर्सन

3
आप नहीं कर सकते। यह भी नहीं है कि मैं क्या हासिल करने की कोशिश कर रहा हूं। मैं संपत्ति IsModifiedको फिर से लिखने के लिए आसानी से संपत्ति प्राप्त करने की कोशिश कर रहा हूं FlagIsModified
इन्वर्टिस

अच्छा प्रश्न। यदि कंटेनर डिपेंडेंसी ऑबजेक्ट है और फ़्लैगआईस्मोडिफाइड डिपेंडेंसीप्रॉपर्टी है तो आपका वर्कअराउंड काम करता है।
जोश जी

10
महान प्रश्न, हालांकि मैं स्वीकृत उत्तर को समझने में विफल हूं। अगर कोई WPF गुरु मुझे कुछ और बता सकता है - तो क्या यह एक बग या प्रति डिजाइन है?
ओस्कर

के अनुसार @Oskar इस यह एक बग है। हालांकि देखने में कोई फिक्स नहीं।
user1151923

जवाबों:


46

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 से सहमत हैं।
केविनरपे

1
क्या यह एक बग है? OneWayToSource बाइंडिंग को केवल-पढ़ने के लिए निर्भरताप्रणाली के साथ अनुमति क्यों नहीं दी जाएगी?
एलेक्स होप ओ'कॉनर

यह कोई बग नहीं है। यह डिजाइन और अच्छी तरह से प्रलेखित है। इसका कारण यह है कि बाइंडिंग इंजन निर्भरता संपत्ति प्रणाली (बाइंडिंग लक्ष्य डीपी होना चाहिए DependencyProperty) के साथ मिलकर काम करता है । एक केवल पढ़ने वाली डीपी केवल संबंधित का उपयोग करके संशोधित की जा सकती है DependencyPropertyKeyBindingExpressionइंजन को पंजीकृत करने के लिए लक्ष्य डीपी के मेटा डेटा में हेरफेर करना होता है। चूंकि DependencyPropertyKeyसार्वजनिक लेखन सुरक्षा की गारंटी देने के लिए निजी माना जाता है, इंजन को केवल-पढ़ने के लिए डीपी पर बाध्यकारी को पंजीकृत करने में सक्षम नहीं होने के परिणामस्वरूप इस कुंजी को अनदेखा करना होगा।
बायोनिककोड

23

यह WPF की एक सीमा है और यह डिजाइन द्वारा है। यह कनेक्ट पर यहां बताया गया है:
OneWayToSource एक आसानी से निर्भरता संपत्ति से बाध्यकारी

मैंने डायनेमिक रूप से रीड-ओनली डिपेंडेंसी प्रॉपर्टीज़ को उस स्रोत तक पहुँचाने में सक्षम बनाया, PushBindingजिसे मैंने यहाँ ब्लॉग किया था । उदाहरण नीचे करता OneWayToSourceरीड-ओनली डीपी से बाइंडिंग 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दो निर्भरता गुण, श्रोता और दर्पण का उपयोग करके काम करता है। श्रोता OneWayटारगेटप्रॉपर्टी से बँधा होता है और PropertyChangedCallbackइसमें मिरर प्रॉपर्टी को अपडेट करता है जो OneWayToSourceकि बाइंडिंग में निर्दिष्ट की गई चीज़ों से जुड़ी होती है ।

डेमो प्रोजेक्ट यहां डाउनलोड किया जा सकता है।
इसमें स्रोत कोड और लघु नमूना उपयोग होता है।


दिलचस्प! मैं इसी तरह के समाधान के साथ आया था और इसे एक "नाली" कहा था - आपके डिजाइन और दो अलग-अलग बाइंडिंग के अनुसार कोंडिट में दो निर्भरता गुण थे। मेरे पास उपयोग का मामला XAML में पुरानी पुरानी संपत्तियों को सादे पुराने गुणों से बांध रहा था।
डैनियल पौल

3
मैं देखता हूं कि आपका MS Connect लिंक किसी भी अधिक काम नहीं करता है। क्या इसका मतलब है कि MS ने इसे .NET के नए संस्करण में तय किया है या उन्होंने इसे हटा दिया है?
टिनी

@ टिनी कनेक्ट अंततः दुर्भाग्य से छोड़ दिया गया लगता है। यह कई जगहों से जुड़ा हुआ था। मुझे नहीं लगता कि यह विशेष रूप से इस बारे में कुछ भी बताता है कि क्या कोई मुद्दा तय किया गया था।
UUDdLrLrSs जुआन

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

यहाँ मान्यता के लिए बाध्य करने के लिए एक और कार्यान्वयन है

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 सीएलआर संपत्ति सेटर का उपयोग नहीं करेगा, लेकिन ऐसा लगता है कि यह इसके आधार पर कुछ अजीब सत्यापन करता है।

आपकी स्थिति में यह ठीक हो सकता है:

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

1
इस मामले में सीएलआर संपत्ति का उपयोग नहीं किया जाता है।
इन्वर्टिस

क्या आपका मतलब यह है कि आपने सिर्फ डिपेंडेंसीप्रोपरेटी को परिभाषित किया है और लिखने में सक्षम था <नियंत्रण: फ्लैगशिप इस्मोडिफाइड = "..." />? मेरे लिए यह कहना है: "संपत्ति 'IsModified' XML नाम स्थान में मौजूद नहीं है" अगर मैं CLR संपत्ति नहीं जोड़ता।
एलेक्स 2k8

1
मेरा मानना ​​है कि डिजाइन समय clr गुणों का उपयोग करता है जहां रनटाइम वास्तव में सीधे निर्भरता संपत्ति (यदि यह एक है) में जाता है।
मेन्डमाइकोड

सीएलआर संपत्ति मेरे मामले में अनावश्यक है (मैं कोड से IsModified का उपयोग नहीं करता हूं), लेकिन यह फिर भी है (केवल एक सार्वजनिक सेटर के साथ)। डिजाइनटाइम और रनटाइम, दोनों ही काम पर निर्भर करता है, जो कि केवल डिपेंडेंसीप्रोपरेटी पंजीकरण के साथ ठीक है।
इनफेरिस

बाइंडिंग स्वयं CLR प्रॉपर्टी का उपयोग नहीं कर रहा है, लेकिन जब आप XAML में बाइंडिंग को परिभाषित करते हैं तो इसे कोड में अनुवादित करना होगा। मैं इस स्तर पर अनुमान लगाता हूं कि XAML पार्सर देखता है कि IsModified संपत्ति आसानी से है, और अपवाद को फेंकता है (बनाए गए बंधन से पहले भी)।
एलेक्स २13 .13

0

हम्म ... मुझे यकीन नहीं है कि मैं इनमें से किसी भी समाधान से सहमत हूं। बाहरी परिवर्तन को अनदेखा करने वाली आपकी संपत्ति पंजीकरण में एक जबरदस्ती कॉलबैक को निर्दिष्ट करने के बारे में कैसे? उदाहरण के लिए, मुझे उपयोगकर्ता नियंत्रण के अंदर MediaElement नियंत्रण की स्थिति प्राप्त करने के लिए केवल-पढ़ने की स्थिति निर्भरता गुण को लागू करने की आवश्यकता थी। यहाँ है कि मैं यह कैसे किया:

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

दूसरे शब्दों में, केवल परिवर्तन को अनदेखा करें और एक अलग सदस्य द्वारा समर्थित मान लौटाएं जिसमें सार्वजनिक संशोधक नहीं है। - उपरोक्त उदाहरण में, MediaRenderer वास्तव में निजी MediaElement नियंत्रण है।


बहुत बुरा यह बीसीएल वर्गों के पूर्व-परिभाषित गुणों के लिए काम नहीं करता है: - /
या मैपर

0

जिस तरह से मैंने इस सीमा के इर्द-गिर्द काम किया, वह था डिपेंडेंसीप्रॉपर्टी प्राइवेट को पूरी तरह से रखते हुए मेरी क्लास में केवल एक बाइंडिंग प्रॉपर्टी का पर्दाफाश करना। मैंने "प्रॉपर्टीबाइंडिंग सोर्स" राइट-ओनली प्रॉपर्टी (यह एक डिपेंडेंसीप्रॉपर्टी नहीं है) को लागू किया, जिसे xaml में बाइंडिंग वैल्यू पर सेट किया जा सकता है। इस राइट-ओनली प्रॉपर्टी के लिए सेटर में मैं बाइंडिंगऑपरेशन को कॉल करता हूं। बाइंडिंग को डिपेंडेंसीप्रॉपर्टी से जोड़ने के लिए बाइंडिंग।

ओपी के विशिष्ट उदाहरण के लिए, यह इस तरह दिखेगा:

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

ध्यान दें कि स्थैतिक आसानी से निर्भरताप्राय वस्तु निजी है। नियंत्रण में मैंने एक बटन जोड़ा जिसका बटन Button_Click ने संभाला है। मेरी विंडो में FlatThingy नियंत्रण का उपयोग। 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>

ध्यान दें कि मैंने उस पर बाध्यकारी के लिए एक ViewModel भी लागू किया है जो यहां नहीं दिखाया गया है। यह "फ्लैगइमोडिफाइड" नाम के एक डिपेंडेंसीप्रोपरेटी को उजागर करता है क्योंकि आप ऊपर के स्रोत से चमक सकते हैं।

यह बहुत अच्छा काम करता है, जिससे मुझे सूचनाओं को दृश्य में दृश्य से पीछे धकेलने की अनुमति मिलती है, जो कि शिथिल रूप से परिभाषित सूचना प्रवाह की दिशा के साथ, शिथिल युग्मित तरीके से होती है।


-1

आप अभी गलत दिशा में बाइंडिंग कर रहे हैं। OneWayToSource जब भी आपके द्वारा बनाए जा रहे नियंत्रण पर IsModified परिवर्तन करता है, तो कंटेनर पर FlagIsModified का प्रयास और अद्यतन करेगा। आप विपरीत चाहते हैं, जो IsModified बाँध कंटेनर के लिए है ।lagIsModified। उसके लिए आपको बाइंडिंग मोड 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 -> कंटेनर
।lagIsModified

3
नीचे चिह्नित किया जा रहा है क्योंकि प्रश्नकर्ता के पास अस्पष्ट प्रश्न था जो थोड़ा अधिक लगता है।
जेरेडपर

6
@JaredPar: मैं यह नहीं देखता कि सवाल के बारे में क्या अस्पष्ट है। प्रश्न में कहा गया है कि 1) केवल पढ़ने के लिए निर्भरता संपत्ति है IsIsModified, 2) ओपी उस संपत्ति पर XAML में बाध्यकारी घोषित करना चाहता है और यह 3) बाध्यकारी OneWayToSourceमोड में काम करने वाला है। आपका समाधान व्यावहारिक रूप से काम नहीं करता क्योंकि, जैसा कि प्रश्न में वर्णित है, संकलक आपको रीड-ओनली प्रॉपर्टी पर बाध्यकारी घोषित नहीं करने देगा, और यह वैचारिक रूप से काम नहीं करता है क्योंकि IsModifiedकेवल-पढ़ने के लिए है और इस प्रकार इसका मूल्य नहीं हो सकता है परिवर्तित (बाइंडिंग द्वारा)।
या मैपर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.