The first example passes in a bound value from the code-behind and the control itself through a MultiBinding, to the MultiValueConverter.
<
TextBlock
x:Name
=
"tb1"
Margin
"20"
>
TextBlock.Text
MultiBinding
Converter
"{StaticResource MyConverter}"
Binding
RelativeSource
"{RelativeSource Self}"
/>
Path
"MyValue"
</
The main thing to note here is the RelativeSource of the first binding, being {RelativeSource Self}. This will pass the control itself into the converter.
Here is the converter:
public
class
MyConverter : IMultiValueConverter
{
FrameworkElement myControl;
object
theValue;
Convert(
[] values, System.Type targetType,
parameter, System.Globalization.CultureInfo culture)
myControl = values[0]
as
FrameworkElement;
theValue = values[1];
return
myControl.Name +
" : "
+ values[1];
}
[] ConvertBack(
value, System.Type[] targetTypes,
new
[] {
null
, myControl.Name +
+ theValue };
Notice the values array in MultiValueConverters order the bidings by the same order they are shown in the markup code.
The second example is similar in that it sets a property of UserControl1, but this example includes a couple of extras.
Firstly you will notice the DependancyPropertyChangedCallback parameter of the DependancyProperty constructor is used. Any changes to the MyUserControlvalue property will cause a call to MyUserControlValueChanged. In the example, this method takes the new value (e.NewValue) and adds it to a datestamp into the third textbox of UserControl1. Also notice the control itself was passed in, this is where you can act on the specific object instance.
static
readonly
DependencyProperty MyUserControlValueProperty =
DependencyProperty.Register(
"MyUserControlValue"
,
typeof
(
string
),
(UserControl1),
UIPropertyMetadata(
, MyUserControlValueChanged));
void
MyUserControlValueChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
var uc1 = dp
UserControl1;
uc1.MyChangedDateString = e.NewValue +
" - "
+ DateTime.Now.ToString();
This user control is used just the same as the previous example:This user control is used just the same as the previous example:This user control is used just the same as the previous example:
<local:UserControl1 x:Name=
"uc1"
Background=
"Yellow"
<local:UserControl1.MyUserControlValue>
<MultiBinding Converter=
"{StaticResource MyConverter2}"
<Binding RelativeSource=
<Binding Path=
</MultiBinding>
</local:UserControl1.MyUserControlValue>
</local:UserControl1>
However the converter in this example shows how once you have the control, the converter can safely do stuff on it like calling it's methods.
MyConverter2 : IMultiValueConverter
var uc = values[0]
uc.MyShowTextMethod(
"Set from converter"
);
uc.Name +
throw
System.NotImplementedException();
This is in response to a follow-up question where the poster wanted to use the passed in control in the ConvertBack method. As shown above, the passed in values are kept for use with the ConvertBack method.
It is important to understand how and WHERE you refer to the Converter, not as one StaticResource, but as several localised resources. If it is defined in the top Window/Page level resources, all controls will use the same converter instance, so any passed in values will be written over by the next control. When you try to convert back, you will get whatever the last control to use Convert was.
Instead, you have to define the static resource at CONTROL LEVEL, so only that control uses THAT instance of the converter.This is an important concept to know.
<TextBox x:Name=
Margin=
<TextBox.Resources>
<local:MyConverter x:Key=
"MyConverter"
</TextBox.Resources>
<TextBox.Text>
UpdateSourceTrigger=
"PropertyChanged"
Mode=
"OneTime"
</TextBox.Text>
</TextBox>
"tb2"
"MyValue2"