开发者

How to use Binding like proxy?

开发者 https://www.devze.com 2023-04-07 10:40 出处:网络
<Setter Property=\"IsChecked\"> <Setter.Value> <MultiBinding> <!-- Get value for property -->
<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.

0

精彩评论

暂无评论...
验证码 换一张
取 消