<Setter Property="IsChecked">
<Setter.Value>
<MultiBinding>
<!-- Get value for property -->
<Bin开发者_如何学Cding Path="IsPressed" RelativeSource="{RelativeSource Self}" Mode="OneWay"/>
<!-- Set value to ViewModel's property -->
<Binding Path="Shift" Mode="OneWayToSource"/>
</MultiBinding>
</Setter.Value>
</Setter>
I need to use 2 bindings for property: one to get value for property and one to set value to ViewModel's property. How I can realize this scenario?
You can create a couple of attached properties. One will be the target of your binding, and second will contain binding for your proxy. Example: Then in ProxySource OnChange implementation you will get TextBox as UIElement, there you can read value from ProxySource and write it to ProxyTarget. This is not a very clean aproach, but it should work. If you can't get it working, I can write a complete sample later. Ok, I've implemented everything, here's complete source:
public class ViewModel : ViewModelBase
{
string sourceText;
public string SourceText
{
get { return sourceText; }
set
{
if (sourceText == value) return;
sourceText = value;
System.Diagnostics.Debug.WriteLine("SourceText:" + value);
RaisePropertyChanged("SourceText");
}
}
string targetText;
public string TargetText
{
get { return targetText; }
set
{
if (targetText == value) return;
targetText = value;
System.Diagnostics.Debug.WriteLine("TargetText:" + value);
RaisePropertyChanged("TargetText");
}
}
}
public static class AttachedPropertiesHost
{
public static object GetProxySource(DependencyObject obj)
{
return obj.GetValue(ProxySourceProperty);
}
public static void SetProxySource(DependencyObject obj, object value)
{
obj.SetValue(ProxySourceProperty, value);
}
public static readonly DependencyProperty ProxySourceProperty =
DependencyProperty.RegisterAttached(
"ProxySource", typeof(object), typeof(AttachedPropertiesHost),
new UIPropertyMetadata(null, ProxySourcePropertyPropertyChanged)
);
private static void ProxySourcePropertyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
dependencyObject.Dispatcher.BeginInvoke(
new { Dp = dependencyObject, NewValue = e.NewValue },
args => SetProxyTarget(args.Dp, args.NewValue)
);
}
public static object GetProxyTarget(DependencyObject obj)
{
return obj.GetValue(ProxyTargetProperty);
}
public static void SetProxyTarget(DependencyObject obj, object value)
{
obj.SetValue(ProxyTargetProperty, value);
}
public static readonly DependencyProperty ProxyTargetProperty =
DependencyProperty.RegisterAttached("ProxyTarget", typeof(object), typeof(AttachedPropertiesHost));
}
<TextBox Text="{Binding SourceText, UpdateSourceTrigger=PropertyChanged}"
WpfDataGridLayout:AttachedPropertiesHost.ProxySource="{Binding RelativeSource={RelativeSource Self}, Path=Text, UpdateSourceTrigger=PropertyChanged}"
WpfDataGridLayout:AttachedPropertiesHost.ProxyTarget="{Binding TargetText, Mode=OneWayToSource}"
/>
And the output from console while editing textbox: SourceText:f TargetText:f SourceText:fh TargetText:fh SourceText:fhh TargetText:fhh
Please dont design your solution around IsPressed
, thats actually what some call a flash
data which means it changes back to a default value (false) sooner. Also contextually Binding
will have dedicated target, source and mode. In MultiBinding
acheiving one way IsPressed
(from a Source) and other way saving back to another Target
is not supported. For two way update to occur, all bindings have to be TowWay
.
Although a Hack to this could be using MultiConverter
having a Target
itself as one of the values.
<MultiBinding Converter="MyMultiBindingConverter">
<!-- Get value for property -->
<Binding Path="IsPressed"
RelativeSource="{RelativeSource Self}" Mode="OneWay"/>
<!-- Set value to ViewModel's property -->
<Binding BindsDirectlyToSource="True"/>
</MultiBinding>
MyMultiBindingConverter.Convert()
{
var myViewModel = values[1] as MyViewModel;
var isPressed = bool.Parse(values[0].ToString());
if (isPressed)
{
myViewModel.Shift = !myViewModel.Shift;
}
}
But this is strongly NOT recommended.
精彩评论