Reputation: 537
It is not possible to bind a value to ConverterParametr
of Binding
. Binding
can be only set on a DependencyProperty
of a DependencyObject
.
I'm curious about implementing IValueConverter
converter as DependencyObject
.
public class AddConverter : DependencyObject, IValueConverter
{
public static readonly DependencyProperty AddIntegerProperty =
DependencyProperty.Register(nameof(AddInteger),
typeof(int),
typeof(AddConverter),
new PropertyMetadata(0));
public int AddInteger
{
get => (int)GetValue(AddIntegerProperty);
set => SetValue(AddIntegerProperty, value);
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is int intValue)) return 0;
return intValue + AddInteger;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
int intValue;
try
{
intValue = System.Convert.ToInt32(value);
}
catch (Exception)
{
return 0;
}
return intValue - AddInteger;
}
}
Let's us it in example View.
<TextBox>
<TextBox.Text>
<Binding Path="MyIntegerProperty">
<Binding.Converter>
<local:AddConverter AddInteger="{Binding MyAddIntegerProperty, Mode=OneWay}" />
</Binding.Converter>
</Binding>
</TextBox.Text>
</TextBox>
The result is that AddInteger
still returns the default value. What is the reason that there is no change of AddInteger
Dependency Property via provided Binding
?
Footnote: The MultiBinding
does not help me because of ConvertBack
method consists only of value provided by a control. This stuff should also be solved in ViewModel, but I'm curious about a solution with a converter.
Upvotes: 0
Views: 1872
Reputation: 37059
The problem is, first, that the converter can't inherit the DataContext where it is, so the binding can't work: You'll see "Framework mentor not found" in the VS output if you put a trace on the binding you have (see appendix A). This is also why you can't just derive from FrameworkElement and use RelativeSource={RelativeSource AncestorType=Whatever}
: You're out of the visual tree. There are no ancestors. Also, even if there were a framework mentor, a DependencyObject can't provide a source for the binding. The source would have to be explicit. Only classes that inherit from FrameworkElement can inherit a DataContext.
So I stole a BindingProxy class (from this answer) and used that to provide a source for the binding. This is slightly clumsyish, but the other alternative I thought of was to inherit the converter from Freezable, essentially giving it the properties of a BindingProxy, and creating the converter in resources. It worked but I prefer the way this is organized.
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
#region Data Property
public Object Data
{
get { return (Object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register(nameof(Data), typeof(Object), typeof(BindingProxy),
new PropertyMetadata(null));
#endregion Data Property
}
XAML
<StackPanel.Resources>
<local:BindingProxy
x:Key="VMProxy"
Data="{Binding}"
/>
</StackPanel.Resources>
<TextBlock>
<TextBlock.Text>
<Binding Path="MyIntegerProperty">
<Binding.Converter>
<local:AddConverter
AddInteger="{Binding Data.MyAddIntegerProperty, Source={StaticResource VMProxy}}"
/>
</Binding.Converter>
</Binding>
</TextBlock.Text>
</TextBlock>
AddInteger="{Binding MyAddIntegerProperty, Mode=OneWay,
PresentationTraceSources.TraceLevel=High}"
System.Windows.Data Warning: 56 : Created BindingExpression (hash=14964341) for Binding (hash=21653700)
System.Windows.Data Warning: 58 : Path: 'MyAddIntegerProperty'
System.Windows.Data Warning: 60 : BindingExpression (hash=14964341): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=14964341): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=14964341): Attach to WpfApp2.AddConverter2.AddInteger (hash=57434139)
System.Windows.Data Warning: 64 : BindingExpression (hash=14964341): Use Framework mentor <null>
System.Windows.Data Warning: 67 : BindingExpression (hash=14964341): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=14964341): Framework mentor not found
System.Windows.Data Warning: 65 : BindingExpression (hash=14964341): Resolve source deferred
System.Windows.Data Warning: 67 : BindingExpression (hash=14964341): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=14964341): Framework mentor not found
Upvotes: 1