Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当一个转换的值在未设置的值中时,使用convertback的多重绑定不起作用_C#_Wpf_Binding_Unset - Fatal编程技术网

C# 当一个转换的值在未设置的值中时,使用convertback的多重绑定不起作用

C# 当一个转换的值在未设置的值中时,使用convertback的多重绑定不起作用,c#,wpf,binding,unset,C#,Wpf,Binding,Unset,我有以下多重绑定: <Grid.Visibility> <MultiBinding Converter="{StaticResource MyMultiValueConverter}" Mode="TwoWay"> <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="MyVisibilityDependencyProperty" Mode="TwoWay"/>

我有以下多重绑定:

 <Grid.Visibility>
    <MultiBinding Converter="{StaticResource MyMultiValueConverter}" Mode="TwoWay">
      <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="MyVisibilityDependencyProperty" Mode="TwoWay"/>
      <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="MyBoolProperty" Mode="TwoWay"/>
   </MultiBinding>
</Grid.Visibility>
现在的场景是:我做smth。这会触发对ConvertBack方法的调用,这意味着我遇到了一个断点。之后,我在MyVisibilityDependencyProperty的OnPropertyChangedCallback中遇到了一个断点。在这里,我可以看到MyVisibilityDependencyProperty的新值是在ConvertBack方法中设置的值

现在我不明白这个问题。我将ConvertBack方法的实现更改为:

public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return new[] { value, DependencyProperty.UnsetValue};
    }
现在我遵循完全相同的场景。我做smth。这会触发对ConvertBack方法的调用,这意味着我遇到了一个断点。之后什么也没发生。不会调用OnPropertyChangedCallback,并且不会更新MyVisibilityDependencyProperty。为什么?

如果数组中的一个值是DependencyProperty.UnsetValue,则所有值的传播都将停止。不仅针对该值,还针对数组中的所有值。以下行为支持这一点:

return new[] { Binding.DoNothing, false };
这将导致调用MyBoolProperty的setter

return new[] { DependencyProperty.UnsetValue, false };
这不会调用MyBoolProperty的setter

我在文档中找不到任何解释的线索,在我看来,这是没有意义的

根据MSDN:

UnsetValue是一个sentinel值,用于WPF属性系统无法确定请求的DependencyProperty值的场景。使用UnsetValue而不是null,因为null可以是有效的属性值,也可以是有效的(经常使用的)DefaultValue

事实上,您不能将
dependencProperty
设置为
UnsetValue
,您只需与它进行比较即可设置为未设置的值没有效果,您可以自己尝试。

尝试以下操作:

将源值转换为绑定目标的值。数据绑定引擎在将值从源绑定传播到绑定目标时调用此方法

    ///param name="values"> The array of values taht the source bindings in the<see cref="T:System.Windows.Data.MultiBinding"/>produces.The value <see cref="F:System.Windows.DependencyProperty.UnsetValue"/> indicates that the source binding has no value to provide for conversion.</param>
    /// <param name="targetType">The type of the binding target property.</param>
    /// <param name="parameter">The converter parameter to use.</param>
    /// <param name="culture">The culture to use in the converter.</param>
    /// <returns>
    /// A converted value.
    /// If the method returns null, the valid null value is used.
    /// A return value of <see cref="T:System.Windows.DependencyProperty"/>.<see cref="F:System.Windows.DependencyProperty.UnsetValue"/> indicates that the converter did not produce a value, and that the binding will use the <see cref="P:System.Windows.Data.BindingBase.FallbackValue"/> if it is available, or else will use the default value.
    /// A return value of <see cref="T:System.Windows.Data.Binding"/>.<see cref="F:System.Windows.Data.Binding.DoNothing"/> indicates that the binding does not transfer the value or use the <see cref="P:System.Windows.Data.BindingBase.FallbackValue"/> or the default value.
    /// </returns>

public object ConvertBack( object[] values, Type targetType, object parameter, System.Globalization.CultureInfo clture )
    {
        if( parameter == null )
           { return null;}


        return String.Format( parameter.ToString(), values );

    }
///param name=“values”>产品中源绑定的值数组。该值表示源绑定没有可供转换的值。
///绑定目标属性的类型。
///要使用的转换器参数。
///要在转换器中使用的区域性。
/// 
///转换后的值。
///如果该方法返回null,则使用有效的null值。
///返回值为。指示转换器未生成值,并且绑定将使用(如果可用),否则将使用默认值。
///返回值为。指示绑定不传输值或不使用或默认值。
/// 
公共对象转换回(对象[]值,类型targetType,对象参数,System.Globalization.CultureInfo-clture)
{
if(参数==null)
{返回null;}
返回String.Format(参数.ToString(),值);
}
我在文档中找不到任何解释的线索,在我看来,这是没有意义的

我不记得在文档中见过它,但您的观察是正确的:

如果
IMultiValueConverter.ConvertBack
结果中的任何元素是
未设置值
,则整个建议值集将被拒绝,即转换失败,并且没有子绑定更新其源值

相关代码可以在
MultiBindingExpression
类中找到。下面是一个简短的摘录

internal override object ConvertProposedValue(object value)
{
    object result;
    bool success = ConvertProposedValueImpl(value, out result);
    {
        result = DependencyProperty.UnsetValue;
        ...
    }
    return result;
}

private bool ConvertProposedValueImpl(object value, out object result)
{
    result = GetValuesForChildBindings(value);

    object[] values = (object[])result;
    int count = MutableBindingExpressions.Count;
    bool success = true;

    // use the smaller count
    if (values.Length < count)
        count = values.Length;

    for (int i = 0; i < count; ++i)
    {
        value = values[i];
        ...
        if (value == DependencyProperty.UnsetValue)
            success = false; // if any element is UnsetValue, conversion fails
        values[i] = value;
    }

    result = values;
    return success;
}
内部覆盖对象ConvertedValue(对象值)
{
客观结果;
bool success=ConvertProposedValueImpl(值,输出结果);
{
结果=DependencyProperty.Unset值;
...
}
返回结果;
}
private bool ConvertedValueImpl(对象值,输出对象结果)
{
结果=GetValuesForChildBindings(值);
对象[]值=(对象[])结果;
int count=MutableBindingExpressions.count;
布尔成功=真;
//使用较小的计数
如果(值.长度<计数)
计数=值。长度;
对于(int i=0;i
至于它是否有意义,我认为是的。结果数组中的
DoNothing
值表示应跳过相应的子绑定,即不应更新其源值。这实际上为部分更新提供了一种机制。如果您仔细想想,我们关心的唯一场景是:

  • 所有源已成功更新
  • 某些源已成功更新
  • 完全失败:未更新任何源

  • 正常行为提供(1),使用
    DoNothing
    可以满足(2)。使用
    未设置的值
    来表示完全失败是有道理的。这也与单值转换器的含义一致:
    UnsetValue
    表示转换失败。唯一的区别是
    ConvertBack
    返回
    object[]
    ,因此不能直接返回
    UnsetValue
    。但是,您可以返回一个只包含未设置值的数组:因为它的存在意味着整个结果都会被抛出,所以数组长度实际上不必与子绑定的数量匹配。

    我不久前遇到过类似的问题[]

    对我来说,有效的方法是“延迟”分配
    DependencyProperty.UnsetValue
    :由于
    MultiBinding
    在某种程度上是绑定的“集合”,您可以按如下方式为每个涉及的1-1绑定分配
    IValueConverter

    (1) XAML标记:引入转换
    internal override object ConvertProposedValue(object value)
    {
        object result;
        bool success = ConvertProposedValueImpl(value, out result);
        {
            result = DependencyProperty.UnsetValue;
            ...
        }
        return result;
    }
    
    private bool ConvertProposedValueImpl(object value, out object result)
    {
        result = GetValuesForChildBindings(value);
    
        object[] values = (object[])result;
        int count = MutableBindingExpressions.Count;
        bool success = true;
    
        // use the smaller count
        if (values.Length < count)
            count = values.Length;
    
        for (int i = 0; i < count; ++i)
        {
            value = values[i];
            ...
            if (value == DependencyProperty.UnsetValue)
                success = false; // if any element is UnsetValue, conversion fails
            values[i] = value;
        }
    
        result = values;
        return success;
    }
    
    <Grid.Visibility>
        <MultiBinding Converter="{StaticResource MyMultiValueConverter}" Mode="TwoWay">
            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="MyVisibilityDependencyProperty" Mode="TwoWay" />
            <Binding Converter="UnsetValueConverter" RelativeSource="{RelativeSource TemplatedParent}" Path="MyBoolProperty" Mode="TwoWay"/>
        </MultiBinding>
    </Grid.Visibility>
    
    public class MyMultiValueConverter: IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
           //Not interesting
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            return new[] { value, value };
        }
    }
    
    public class UnsetValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return DependencyProperty.UnsetValue;
        }
    }