बाइंडिंग कन्वर्टर


165

वहाँ एक तरह से मैं यह कर सकता है Style:

<Style TargetType="FrameworkElement">
    <Setter Property="Visibility">
        <Setter.Value>
            <Binding Path="Tag"
                RelativeSource="{RelativeSource AncestorType=UserControl}"
                Converter="{StaticResource AccessLevelToVisibilityConverter}"
                ConverterParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Tag}" />                        
        </Setter.Value>
    </Setter>
</Style>

मुझे बस Tagशीर्ष स्तर के माता-पिता और Tagअपने स्वयं के नियंत्रण वर्ग को भेजने की आवश्यकता है ।

जवाबों:


303

ConverterParameterसंपत्ति के लिए बाध्य नहीं किया जा सकता क्योंकि यह एक निर्भरता संपत्ति नहीं है।

चूंकि इसके किसी भी गुण Bindingसे व्युत्पन्न नहीं है, इसलिए यह DependencyObjectनिर्भरता गुण हो सकता है। एक परिणाम के रूप में, एक बंधन कभी भी दूसरे बंधन का लक्ष्य वस्तु नहीं हो सकता है।

हालांकि एक वैकल्पिक समाधान है। आप सामान्य बाइंडिंग के बजाय बहु-मूल्य कनवर्टर केMultiBinding साथ उपयोग कर सकते हैं :

<Style TargetType="FrameworkElement">
    <Setter Property="Visibility">
        <Setter.Value>
            <MultiBinding Converter="{StaticResource AccessLevelToVisibilityConverter}">
                <Binding Path="Tag" RelativeSource="{RelativeSource Mode=FindAncestor,
                                                     AncestorType=UserControl}"/>
                <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}"/>
            </MultiBinding>
        </Setter.Value>
    </Setter>
</Style>

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

public class AccessLevelToVisibilityConverter : IMultiValueConverter
{
    public object Convert(
        object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return values.All(v => (v is bool && (bool)v))
            ? Visibility.Visible
            : Visibility.Hidden;
    }

    public object[] ConvertBack(
        object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

36

नहीं, दुर्भाग्य से यह संभव नहीं होगा क्योंकि ConverterParameterऐसा नहीं है DependencyPropertyकि आप बाइंडिंग का उपयोग नहीं कर पाएंगे

लेकिन शायद आप को धोखा देने और एक इस्तेमाल कर सकते हैं MultiBindingके साथ IMultiValueConverter2 में पारित करने के लिए Tagगुण।


13

उपयोग MarkupExtensionकरने के लिए उपयोग करने के लिए एक वैकल्पिक तरीका भी Bindingहै ConverterParameter। इस समाधान के साथ आप अभी भी डिफ़ॉल्ट उपयोग कर सकते हैं IValueConverterके बजाय IMultiValueConverterक्योंकि ConverterParameterमें पारित हो जाता IValueConverter, जैसा कि आपने अपना पहला नमूना में होने की उम्मीद।

यहाँ मेरा पुन MarkupExtension: प्रयोज्य है :

/// <summary>
///     <example>
///         <TextBox>
///             <TextBox.Text>
///                 <wpfAdditions:ConverterBindableParameter Binding="{Binding FirstName}"
///                     Converter="{StaticResource TestValueConverter}"
///                     ConverterParameterBinding="{Binding ConcatSign}" />
///             </TextBox.Text>
///         </TextBox>
///     </example>
/// </summary>
[ContentProperty(nameof(Binding))]
public class ConverterBindableParameter : MarkupExtension
{
    #region Public Properties

    public Binding Binding { get; set; }
    public BindingMode Mode { get; set; }
    public IValueConverter Converter { get; set; }
    public Binding ConverterParameter { get; set; }

    #endregion

    public ConverterBindableParameter()
    { }

    public ConverterBindableParameter(string path)
    {
        Binding = new Binding(path);
    }

    public ConverterBindableParameter(Binding binding)
    {
        Binding = binding;
    }

    #region Overridden Methods

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var multiBinding = new MultiBinding();
        Binding.Mode = Mode;
        multiBinding.Bindings.Add(Binding);
        if (ConverterParameter != null)
        {
            ConverterParameter.Mode = BindingMode.OneWay;
            multiBinding.Bindings.Add(ConverterParameter);
        }
        var adapter = new MultiValueConverterAdapter
        {
            Converter = Converter
        };
        multiBinding.Converter = adapter;
        return multiBinding.ProvideValue(serviceProvider);
    }

    #endregion

    [ContentProperty(nameof(Converter))]
    private class MultiValueConverterAdapter : IMultiValueConverter
    {
        public IValueConverter Converter { get; set; }

        private object lastParameter;

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (Converter == null) return values[0]; // Required for VS design-time
            if (values.Length > 1) lastParameter = values[1];
            return Converter.Convert(values[0], targetType, lastParameter, culture);
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            if (Converter == null) return new object[] { value }; // Required for VS design-time

            return new object[] { Converter.ConvertBack(value, targetTypes[0], lastParameter, culture) };
        }
    }
}

MarkupExtensionअपने कोड आधार में इसके साथ आप ConverterParameterनिम्नलिखित तरीके से बाँध सकते हैं :

<Style TargetType="FrameworkElement">
<Setter Property="Visibility">
    <Setter.Value>
     <wpfAdditions:ConverterBindableParameter Binding="{Binding Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}"
                 Converter="{StaticResource AccessLevelToVisibilityConverter}"
                 ConverterParameterBinding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Tag}" />          
    </Setter.Value>
</Setter>

जो लगभग आपके शुरुआती प्रस्ताव जैसा लगता है।


4
यह उपयोगी है। हालांकि, MultiValueConverterAdapterगायब है। मैंने इसे यहां पाया ।
blearyeye
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.