2
<Setter Property="IsChecked">
    <Setter.Value>
        <MultiBinding>
            <!-- Get value for property -->
            <Binding Path="IsPressed" RelativeSource="{RelativeSource Self}" Mode="OneWay"/>
            <!-- Set value to ViewModel's property -->
            <Binding Path="Shift" Mode="OneWayToSource"/>
        </MultiBinding>
    </Setter.Value>
</Setter>

我需要对属性使用 2 个绑定:一个用于获取属性的值,一个用于为 ViewModel 的属性设置值。我怎样才能实现这种情况?

4

2 回答 2

2

您可以创建几个附加属性。一个将是您的绑定目标,第二个将包含您的代理的绑定。示例:然后在 ProxySource OnChange 实现中,您将获得 TextBox 作为 UIElement,在那里您可以从 ProxySource 读取值并将其写入 ProxyTarget。这不是一个非常干净的方法,但它应该有效。如果你不能让它工作,我可以稍后写一个完整的示例。好的,我已经实现了一切,这是完整的源代码:

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}"
             />

以及编辑文本框时控制台的输出: SourceText:f TargetText:f SourceText:fh TargetText:fh SourceText:fhh TargetText:fhh

于 2011-09-24T16:34:52.463 回答
1

请不要设计您的解决方案IsPressed,这实际上是一些人所说的flash数据,这意味着它会更快地变回默认值(false)。上下文Binding也将有专用的目标、源和模式。不支持以MultiBinding一种方式IsPressed(从源)和其他方式保存回另一种方式Target。要进行双向更新,所有绑定都必须是TowWay.

尽管对此的破解可能是使用MultiConverterTarget自身作为值之一。

     <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;
        }
    }

但强烈建议这样做。

于 2011-09-26T09:29:56.790 回答